我正在尝试计算vb.net中两个日期/时间之间的时间量,以便在aspx网页上使用。我在这里和其他来源搜索了很多年,但我没有走得太远。我找到的所有示例都是PHP或SQL相关的。
基本上我有以下......
Dim StartDateTime As DateTime = #5/27/2013 6:00:00 AM#
Dim FinishDateTime As DateTime = #5/28/2013 10:30:00 AM#
Dim Minutes As Long = DateDiff(DateInterval.Minute, StartDateTime, FinishDateTime, Microsoft.VisualBasic.FirstDayOfWeek.Monday)
计算出开始和结束之间的分钟数。问题是我只想让它计算我们设定营业时间(9-5)的时间,因此在示例中它应该返回9.5小时或570分钟,并且如果周期超过一个周末,最终不计算任何时间。
开始时间可以是任何事情(因此可以在营业时间之前或之后下降),虽然结束时间通常是在营业时间,但我们必须假设它也可以是任何东西。
我也许可以使用大量的IF语句实现这一点,这似乎是一种无用的方法我想知道是否有人有任何指示让我朝着正确的方向前进。
非常感谢答案 0 :(得分:1)
我已经创建了一个函数来获取2个日期(含),减去假日和周末之间的工作日列表,如下所示:
Function GetWorkingDates(startDate As Date, endDate As Date, holidayDates As Date()) As List(Of Date)
If endDate < startDate Then
Throw New ArgumentOutOfRangeException("endDate", "Value must be equal or larger than 'startDate' parameter.")
End If
Dim listDate As List(Of Date) = Enumerable.Range(0, 1 + CInt((endDate - startDate).TotalDays)).Select(Function(n) startDate.AddDays(n)).ToList
' if defined, remove holidays from listDate
If holidayDates IsNot Nothing Then listDate.RemoveAll(Function(d) holidayDates.Contains(d))
' remove weekends as defined below
Dim weekends As DayOfWeek() = {DayOfWeek.Saturday, DayOfWeek.Sunday}
listDate.RemoveAll(Function(d) weekends.Contains(d.DayOfWeek))
Return listDate
End Function
为了获得总小时数,我刚刚创建了一个新函数来从上面现有函数的结果中得到总时间跨度:
Function GetTotalWorkingTimeSpan(startDateTime As Date, endDateTime As Date, startWorkTime As TimeSpan, endWorkTime As TimeSpan, holidayDates As Date()) As TimeSpan
If endDateTime < startDateTime Then
Throw New ArgumentOutOfRangeException("endDate", "Value must be equal or larger than 'startDate' parameter.")
End If
If endWorkTime < startWorkTime Then
Throw New ArgumentOutOfRangeException("endWorkTime", "Value must be equal or larger than 'startWorkTime' parameter.")
End If
' get list of working days minus weekends and holidays
Dim lstWorkDays As List(Of Date) = GetWorkingDates(startDateTime.Date, endDateTime.Date, holidayDates)
' get total minutes by bultiplying total working days and total minutes per day
Dim totalMinutes As Double = lstWorkDays.Count * (endWorkTime - startWorkTime).TotalMinutes
' deduct the first day's hour if occured later than the startWorkTime, only if startDateTime is a working day
If lstWorkDays.Contains(startDateTime.Date) Then
Dim minutesOffset As Double = (startDateTime.TimeOfDay - startWorkTime).TotalMinutes
If minutesOffset > 0 Then totalMinutes -= minutesOffset
End If
' deduct the last day's hour if occured ealier than the endWorkTime, only if endDateTime is a working day
If lstWorkDays.Contains(endDateTime.Date) Then
Dim minutesOffset As Double = (endWorkTime - endDateTime.TimeOfDay).TotalMinutes
If minutesOffset > 0 Then totalMinutes -= minutesOffset
End If
Return TimeSpan.FromMinutes(totalMinutes)
End Function
使用您的数据,我创建了一个测试控制台:
Sub Main()
Dim sdt As Date = #5/27/2013 6:00:00 AM#
Dim edt As Date = #5/28/2013 10:30:00 AM#
Dim hols() As Date = {} ' add holiday dates here
Dim lst As List(Of Date) = GetWorkingDates(sdt, edt, Nothing) ' or simply Nothing to not check for holidays
Console.WriteLine("Num of working days = " & lst.Count)
Console.WriteLine()
Console.WriteLine("List of working dates:")
lst.ForEach(Sub(d) Console.WriteLine("* " & d.ToLongDateString))
Console.WriteLine()
Dim totalWorkingTimeSpan As TimeSpan = GetTotalWorkingTimeSpan(sdt, edt, New TimeSpan(9, 0, 0), New TimeSpan(17, 0, 0), hols)
Console.WriteLine("Total working hours = " & totalWorkingTimeSpan.TotalMinutes & " minutes, or " & totalWorkingTimeSpan.TotalHours & " hours")
PromptExit()
End Sub
控制台应用的输出:
答案 1 :(得分:0)
基本上,您只计算开始和结束之间非营业时间的时间
因此,您所做的是为日期范围
创建非工作时间的“表格”说它是1/1/2013 08:20到3/1/2013 17:30
1/1/2013 00:00:00 to 1/1/2013 08:59:59
1/1/2013 17:00:00 to 1/1/2013 23:59:59
2/1/2013 00:00:00 to 1/2/2013 08:59:59
2/1/2013 17:00:00 to 1/2/2013 23:59:59
3/1/2013 00:00:00 to 3/1/2013 08:59:59
3/1/2013 17:00:00 to 3/1/2013 23:59:59
然后您将第一个开始时间和最后结束时间替换为
1/1/2013 08:20:00 to 1/1/2013 08:59:59
1/1/2013 17:00:00 to 1/1/2013 23:59:59
2/1/2013 00:00:00 to 1/2/2013 08:59:59
2/1/2013 17:00:00 to 1/2/2013 23:59:59
3/1/2013 00:00:00 to 3/1/2013 08:59:59
3/1/2013 17:00:00 to 3/1/2013 17:30:00
上述持续时间的总和是非营业时间。所以你只需从最后开始减去它。
有很多不同的方法。在这里搜索,你会发现如何使用CTE在SQL中执行此操作
答案 2 :(得分:0)
这可以通过代码完成。有一些计算需要将开始和结束时间“标准化”到工作时间,以及确定周末所需的一些额外计算,但这是一个相对简单的练习:
' Define the start and end hour of the work day
Const START_HOUR As Integer = 9
Const FINISH_HOUR As Integer = 17
Dim StartDateTime As DateTime = #5/27/2013 6:00:00 AM#
Dim FinishDateTime As DateTime = #5/28/2013 10:30:00 AM#
If StartDateTime.Hour < START_HOUR Then
' If the current hour is less than the start hour, go to the start of the current day
StartDateTime = New DateTime(StartDateTime.Year, StartDateTime.Month, StartDateTime.Day, START_HOUR, 0, 0)
ElseIf StartDateTime.Hour > FINISH_HOUR Then
' If the current hour is greater than the end hour, go to the start of the next day
StartDateTime = New DateTime(StartDateTime.Year, StartDateTime.Month, StartDateTime.Day + 1, START_HOUR, 0, 0)
End If
If FinishDateTime.Hour < START_HOUR Then
' If the current hour is less than the start hour, go back to the end of the previous day
FinishDateTime = New DateTime(FinishDateTime.Year, FinishDateTime.Month, FinishDateTime.Day - 1, FINISH_HOUR, 0, 0)
ElseIf FinishDateTime.Hour > FINISH_HOUR Then
' If the current hour is greater than the end hour, go to the end hour of the current day
FinishDateTime = New DateTime(FinishDateTime.Year, FinishDateTime.Month, FinishDateTime.Day, FINISH_HOUR, 0, 0)
End If
' Determine the total number of actual days the date range crosses
Dim Days = Math.Ceiling(FinishDateTime.Subtract(StartDateTime).TotalDays)
Dim Weekends As Double
' Determine the number of weekends (might need work)
If FinishDateTime.DayOfWeek > StartDateTime.DayOfWeek Then
' I'm sure this needs work
Weekends = Math.Floor(Days / 7) + 1
Else
Weekends = Math.Floor(Days / 7)
End If
' Determine the number of minutes between the start of the work day and the actual start time
Dim StartMinutesOffset = ((StartDateTime.Hour * 60) + StartDateTime.Minute) - (START_HOUR * 60)
' Determine number of minutes between the finish time and the end of the work day
Dim FinishMinutesOffset = (FINISH_HOUR * 60) - ((FinishDateTime.Hour * 60) + FinishDateTime.Minute)
' The number of minutes is the number of days less 2 * the number of weekends less the start time offset less the finish time offset
Dim TotalMinutes = (Days - (Weekends * 2)) * ((FINISH_HOUR - START_HOUR) * 60) - StartMinutesOffset - FinishMinutesOffset
Debug.WriteLine(TotalMinutes)