如何通过设置时间限制并排除周末来对 DateTime 小时数求和
How to sum DateTime hours by setting limit of time and excluding weekends
我有一个包含如下列的 DataGridView:
持续时间(小时)
日期时间 1
日期时间2
12
2020-8-108:00
?
28
?
?
Datetime2
的值是 Duration 和 Datetime1
之间的小时数总和;格式应为 yyyy-mm-dd H:mm
.
时间限制是从 8 点到 16 点,因此如果求和结果高于 16 点,日期将从 8 点开始增加。
它还应该不包括周末(周六和周日)
我期望的结果是这样的:
持续时间(小时)
日期时间 1
日期时间2
12
2021-8-108:00
2021-8-1112:00
27
2021-8-11 12.00
2021-8-1615:00
我的代码不考虑时间限制和周末排除:
For i As Integer = 0 To dgv.Rows.Count - 1
Dim hoursToAdd As Double
Dim datefrom As DateTime
If (Double.TryParse(dgv.Rows(i).Cells("Duration").Value, hoursToAdd) AndAlso DateTime.TryParse(dgv.Rows(i).Cells("Datetime1").Value, datefrom)) Then
Dim dateTo = datefrom.AddHours(hoursToAdd)
dgv.Rows(i).Cells("Datetime2").Value = dateTo.ToString("yyyy-MM-dd H:mm")
For j As Integer = 1 To dgv.Rows.Count - 2
If dgv.Rows(j).Cells("Datetime2").Value IsNot DBNull.Value Then
dgv.Rows(j).Cells("Datetime1").Value = dgv.Rows(j - 1).Cells("Datetime2").Value
End If
Next
End If
Next
如果没有时间限制,结果如下T.T
持续时间(小时)
日期时间 1
日期时间2
12
2021-8-108:00
2021-8-1020:00
27
2021-8-10 20.00
2021-8-1119:00
排除周末
尝试在 dateFrom
声明后使用 DayOfWeek
。喜欢
Dim datefrom As DateTime
If datefrom.DayOfWeek = 0 or datefrom.DayOfWeek = 6 Then
' Do nothing
Else
' Your If Statement Here
' If (Double.TryParse(dgv.Rows(i).Cells("Duration").Value...
End If
或
Dim datefrom As DateTime
If datefrom.DayOfWeek <> 0 AND datefrom.DayOfWeek <> 6 Then
' Your If Statement Here
' If (Double.TryParse(dgv.Rows(i).Cells("Duration").Value...
End If
The value of the constants in the DayOfWeek enumeration ranges from DayOfWeek.Sunday to DayOfWeek.Saturday. If cast to an integer, its value ranges from zero (which indicates DayOfWeek.Sunday) to six (which indicates DayOfWeek.Saturday).
这是一个可以满足您要求的函数。它首先创建 DateTime variable for 16:00 on given day. It uses this variable with the given start time to calculate a TimeSpan 剩余小时数,直到 16:00。然后它从所需的总小时数中减去该数字并移动到第二天,检查它是否不是周末。这在循环中重复,直到所需的小时数为 0。
Function AddHours(start As DateTime, hours As Integer) As DateTime
' Copy number of hours to add
Dim hoursLeft As Integer = hours
Dim currentDate As DateTime = start
Do While hoursLeft > 0
' Create a new variable representing 16:00
Dim endOfDay As DateTime = New DateTime(currentDate.Year, currentDate.Month, currentDate.Day, 16, 0, 0)
' Calculate the number of usable hours
Dim dayTimeSpan As TimeSpan = endOfDay - currentDate
If hoursLeft > dayTimeSpan.TotalHours Then
' Subtract usable hours from hoursLeft
hoursLeft -= dayTimeSpan.TotalHours
Else
' End date is found
Return currentDate.AddHours(hoursLeft)
End If
' Set currentDate to next working day
Select Case currentDate.DayOfWeek
Case DayOfWeek.Friday
currentDate = currentDate.AddDays(3)
Case Else
currentDate = currentDate.AddDays(1)
End Select
' Set hour to 8:00
currentDate = New DateTime(currentDate.Year, currentDate.Month, currentDate.Day, 8, 0, 0)
Loop
End Function
下面显示了如何在给定持续时间(作为 TimeSpan)、起始 Date/Time 值、工作日开始时间和工作日结束时间的情况下计算结束 Date/Time 值。
注意:下面的代码已经使用“用法”下列出的值进行了测试。
计算结束DT
Private Function CalculateEndDT(duration As TimeSpan, dateTime1 As DateTime, workdayStart As DateTime, workDayEnd As DateTime) As DateTime
Dim endDT As DateTime = DateTime.MinValue
'since workday starts and ends on same day
'use the year, month, and day of dateTime1
Dim wdStart As DateTime = New DateTime(dateTime1.Year, dateTime1.Month, dateTime1.Day, workdayStart.Hour, workdayStart.Minute, workdayStart.Second)
Dim wdEnd As DateTime = New DateTime(dateTime1.Year, dateTime1.Month, dateTime1.Day, workDayEnd.Hour, workDayEnd.Minute, workDayEnd.Second)
'calculate hours in a workday
Dim tsWorkday As TimeSpan = wdEnd - wdStart
Dim numDays As Integer = 0
Dim timeRemaining As TimeSpan = duration - (wdEnd - dateTime1)
'Debug.WriteLine("timeRemaining - " & timeRemaining.Hours & ":" & timeRemaining.Minutes & ":" & timeRemaining.Seconds)
If timeRemaining.TotalMinutes > 0 Then
Do
numDays += 1 'increment
'calculate
timeRemaining = timeRemaining - tsWorkday
If timeRemaining.TotalMinutes <= 0 Then
Dim tempTs As TimeSpan = New TimeSpan(24 * numDays, 0, 0)
endDT = wdEnd.Add(tempTs)
endDT = endDT.Add(timeRemaining)
End If
Loop While timeRemaining.TotalMinutes > 0
Else
endDT = wdEnd.Subtract(timeRemaining)
End If
'add day for each weekend day
If endDT.DayOfWeek = 0 Then
endDT = endDT.AddDays(1)
ElseIf endDT.DayOfWeek = 6 Then
endDT = endDT.AddDays(2)
End If
Return endDT
End Function
给定:
- 持续时间:12 小时
- dateTime1: 2021/08/10 08:00:00(您要从中开始计算的 Date/Time)
- 工作日开始: 08:00
- 工作日结束: 16:00
这转化为以下内容(见下文):
- 持续时间:新时间跨度(0, 12, 0, 0) - 这是 12 小时
- dateTime1: New DateTime(2021, 8, 10, 8, 0, 0) - 这是
2021/08/10 08:00:00
- workdayStart: New DateTime(2021, 8, 10, 8, 0, 0) - 未使用年、月和日的值
- workdayEnd: New DateTime(2021, 8, 10, 16, 0, 0) - 未使用年、月和日的值
注意:workdayStart
和workdayEnd
不使用年、月、日的值,但小时、分钟、第二个被使用。
用法:
Dim endDT1 As DateTime = CalculateEndDT(New TimeSpan(0, 12, 0, 0), New DateTime(2021, 8, 10, 8, 0, 0), New DateTime(2021, 8, 10, 8, 0, 0), New DateTime(2021, 8, 10, 16, 0, 0))
Dim endDT2 As DateTime = CalculateEndDT(New TimeSpan(0, 27, 0, 0), New DateTime(2021, 8, 11, 12, 0, 0), New DateTime(2021, 8, 11, 8, 0, 0), New DateTime(2021, 8, 11, 16, 0, 0))
Debug.WriteLine(endDT1.ToString("yyyy-M-d HH:mm"))
Debug.WriteLine(endDT2.ToString("yyyy-M-d HH:mm"))
结果:
2021-8-11 12:00
2021-8-16 15:00
我相信有很多方法可以做到这一点。以下是一种可能的解决方案。
下面的代码做出了一些假设……
- Datetime1 可以是任何日期。这个日期可以是周末约会。这个日期可以是具有小时时间值的日期,该时间值可以是……8 点之前(上午 8 点)……或者……16 点之后(下午 4 点)。
- Datetime2 只能是不在周末(周六或周日)的日期,并且小时时间值将始终为……大于或等于 8(dt2.Hour >= 8)……并且……小于或等于 16 (dt.Hour <= 16)。基本上 Datetime2 将始终是一个工作日(周一至周五),时间为上午 8 点至下午 4 点。
如果 Datetime1 始终是工作日,并且在上午 8 点到下午 4 点之间……那么下面的代码可以简化。但是下面的代码支持第一个假设。
为了解决这个问题,一种特殊的方法可能会派上用场。此方法将采用 DateTime
对象和 return 从给定日期开始的下一个工作日(周一至周五)。注意……如果给定日期已经是工作日,则原始给定日期为 returned。这有什么帮助,因为我们可能会在日期中添加“天数”……我们可能需要多次检查周末。在这一点上这有什么帮助可能并不明显;但是,当您看到它在 main 方法中的使用方式时,它应该会变得更加清晰。基本上,这种方法只是用来减少代码重复。
Private Function GetNextWorkday(Date1 As DateTime) As DateTime
Dim ReturnDate = Date1
While ReturnDate.DayOfWeek.Equals(DayOfWeek.Saturday) Or
ReturnDate.DayOfWeek.Equals(DayOfWeek.Sunday)
ReturnDate = ReturnDate.AddDays(1)
End While
Return ReturnDate
End Function
接下来我们有一个方法,它接受一个 DateTime
对象 Date1
和一个 int32
Duration
。此方法将 return 我们正在寻找的 Datetime2
值。
遍历下面的代码……首先我们假设给定日期 Date1
可能是周末(周六或周日)日期。所以第 1 步是使用我们上面的方法来获取从给定日期开始的下一个工作日日期。我们知道给定日期是否已经是工作日日期,那么我们上面的方法将简单地 return 相同的日期。这是通过以下行完成的...
Date1 = GetNextWorkday(Date1)
接下来我们创建一个名为 HoursLeft
的 Int32
变量并将其设置为给定的 Duration
值。我们将使用此变量“倒计时”到 8 或更小的值。这就是 While
循环正在做的事情。需要注意的是,由于我们可能会添加多天,所以我们需要调用上面的方法来忽略周末。
while 循环结束后,HoursLeft
将是一个等于或小于 8 的值。这是我们需要添加 Date1
日期的小时数。添加这些最后几个小时后,我们需要进行最后一次检查以确保添加这些小时不会发送日期 HOUR 值 PAST 16(下午 4 点)。
如果在添加最后几个小时后,小时值大于 16,那么,我们将知道我们需要再添加一天并将剩余小时数添加到新日期,其中 HOUR 为 8(上午 8 点) ) 加上剩余时间。
示例:如果在添加最后几个小时后日期的 HOUR 值为 18,那么我们就会知道我们需要在日期上添加一 (1) 天,然后将小时设置为 (18-16=2) + 8 = 10。换句话说,18 的值是 16 点后 2 小时,因此我们想在下一个工作日的 8(上午 8 点)开始增加两 (2) 小时。同样,因为我们可能会在日期中添加一天,所以我们需要第三次调用上面的方法。我希望这是有道理的。
Private Function ComputeDate2(Date1 As DateTime, Duration As Int32) As DateTime
Date1 = GetNextWorkday(Date1)
If (Duration < 0) Then
Duration = Math.Abs(Duration)
End If
Dim HoursLeft As Int32 = Duration
While HoursLeft > 8
HoursLeft -= 8
Date1 = Date1.AddDays(1)
Date1 = GetNextWorkday(Date1)
End While
Date1 = Date1.AddHours(HoursLeft)
If Date1.Hour > 16 Then
Dim dif As Int32 = Date1.Hour - 16
Date1 = Date1.AddDays(1)
Date1 = GetNextWorkday(Date1)
Date1 = New DateTime(Date1.Year, Date1.Month, Date1.Day, 8 + dif, 0, 0)
End If
Return Date1
End Function
要对此进行测试并完成示例,请创建一个新的 VB winforms 解决方案,将 DataGridView
和 Button
拖放到表单上。该按钮用于遍历网格中的所有行并设置 Datetime2
单元格值。
Dim GridTable As DataTable
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GridTable = GetData()
DataGridView1.DataSource = GridTable
DataGridView1.Columns("Date1").DefaultCellStyle.Format = "yyyy-MM-dd HH:mm"
DataGridView1.Columns("Date2").DefaultCellStyle.Format = "yyyy-MM-dd HH:mm"
DataGridView1.Columns("Date1").Width = 150
DataGridView1.Columns("Date2").Width = 150
End Sub
Function GetData() As DataTable
Dim dt = New DataTable
dt.Columns.Add("Duration", GetType(Int32))
dt.Columns.Add("Date1", GetType(DateTime))
dt.Columns.Add("Date2", GetType(DateTime))
dt.Rows.Add(12, New DateTime(2021, 8, 10, 8, 0, 0))
dt.Rows.Add(27, New DateTime(2021, 8, 11, 12, 0, 0))
dt.Rows.Add(28, New DateTime(2021, 8, 11, 12, 0, 0))
dt.Rows.Add(29, New DateTime(2021, 8, 11, 12, 0, 0))
dt.Rows.Add(40, New DateTime(2021, 8, 1, 8, 0, 0))
dt.Rows.Add(8, New DateTime(2021, 8, 7, 8, 0, 0))
Return dt
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim drv As DataRowView
Dim Dur As Int32
Dim date1 As DateTime
For Each row As DataGridViewRow In DataGridView1.Rows
If Not row.IsNewRow Then
drv = CType(row.DataBoundItem, DataRowView)
Dur = CType(drv("Duration"), Int32)
date1 = CType(drv("Date1"), DateTime)
If (date1.Hour > 16 Or date1.Hour < 8) Then
date1 = New DateTime(date1.Year, date1.Month, date1.Day, 8, 0, 0)
End If
drv("Date2") = ComputeDate2(date1, Dur)
End If
Next
DataGridView1.Refresh()
End Sub
我希望这是有道理的。
我有一个包含如下列的 DataGridView:
持续时间(小时) | 日期时间 1 | 日期时间2 |
---|---|---|
12 | 2020-8-108:00 | ? |
28 | ? | ? |
Datetime2
的值是 Duration 和 Datetime1
之间的小时数总和;格式应为 yyyy-mm-dd H:mm
.
时间限制是从 8 点到 16 点,因此如果求和结果高于 16 点,日期将从 8 点开始增加。
它还应该不包括周末(周六和周日)
我期望的结果是这样的:
持续时间(小时) | 日期时间 1 | 日期时间2 |
---|---|---|
12 | 2021-8-108:00 | 2021-8-1112:00 |
27 | 2021-8-11 12.00 | 2021-8-1615:00 |
我的代码不考虑时间限制和周末排除:
For i As Integer = 0 To dgv.Rows.Count - 1
Dim hoursToAdd As Double
Dim datefrom As DateTime
If (Double.TryParse(dgv.Rows(i).Cells("Duration").Value, hoursToAdd) AndAlso DateTime.TryParse(dgv.Rows(i).Cells("Datetime1").Value, datefrom)) Then
Dim dateTo = datefrom.AddHours(hoursToAdd)
dgv.Rows(i).Cells("Datetime2").Value = dateTo.ToString("yyyy-MM-dd H:mm")
For j As Integer = 1 To dgv.Rows.Count - 2
If dgv.Rows(j).Cells("Datetime2").Value IsNot DBNull.Value Then
dgv.Rows(j).Cells("Datetime1").Value = dgv.Rows(j - 1).Cells("Datetime2").Value
End If
Next
End If
Next
如果没有时间限制,结果如下T.T
持续时间(小时) | 日期时间 1 | 日期时间2 |
---|---|---|
12 | 2021-8-108:00 | 2021-8-1020:00 |
27 | 2021-8-10 20.00 | 2021-8-1119:00 |
排除周末
尝试在 dateFrom
声明后使用 DayOfWeek
。喜欢
Dim datefrom As DateTime
If datefrom.DayOfWeek = 0 or datefrom.DayOfWeek = 6 Then
' Do nothing
Else
' Your If Statement Here
' If (Double.TryParse(dgv.Rows(i).Cells("Duration").Value...
End If
或
Dim datefrom As DateTime
If datefrom.DayOfWeek <> 0 AND datefrom.DayOfWeek <> 6 Then
' Your If Statement Here
' If (Double.TryParse(dgv.Rows(i).Cells("Duration").Value...
End If
The value of the constants in the DayOfWeek enumeration ranges from DayOfWeek.Sunday to DayOfWeek.Saturday. If cast to an integer, its value ranges from zero (which indicates DayOfWeek.Sunday) to six (which indicates DayOfWeek.Saturday).
这是一个可以满足您要求的函数。它首先创建 DateTime variable for 16:00 on given day. It uses this variable with the given start time to calculate a TimeSpan 剩余小时数,直到 16:00。然后它从所需的总小时数中减去该数字并移动到第二天,检查它是否不是周末。这在循环中重复,直到所需的小时数为 0。
Function AddHours(start As DateTime, hours As Integer) As DateTime
' Copy number of hours to add
Dim hoursLeft As Integer = hours
Dim currentDate As DateTime = start
Do While hoursLeft > 0
' Create a new variable representing 16:00
Dim endOfDay As DateTime = New DateTime(currentDate.Year, currentDate.Month, currentDate.Day, 16, 0, 0)
' Calculate the number of usable hours
Dim dayTimeSpan As TimeSpan = endOfDay - currentDate
If hoursLeft > dayTimeSpan.TotalHours Then
' Subtract usable hours from hoursLeft
hoursLeft -= dayTimeSpan.TotalHours
Else
' End date is found
Return currentDate.AddHours(hoursLeft)
End If
' Set currentDate to next working day
Select Case currentDate.DayOfWeek
Case DayOfWeek.Friday
currentDate = currentDate.AddDays(3)
Case Else
currentDate = currentDate.AddDays(1)
End Select
' Set hour to 8:00
currentDate = New DateTime(currentDate.Year, currentDate.Month, currentDate.Day, 8, 0, 0)
Loop
End Function
下面显示了如何在给定持续时间(作为 TimeSpan)、起始 Date/Time 值、工作日开始时间和工作日结束时间的情况下计算结束 Date/Time 值。
注意:下面的代码已经使用“用法”下列出的值进行了测试。
计算结束DT
Private Function CalculateEndDT(duration As TimeSpan, dateTime1 As DateTime, workdayStart As DateTime, workDayEnd As DateTime) As DateTime
Dim endDT As DateTime = DateTime.MinValue
'since workday starts and ends on same day
'use the year, month, and day of dateTime1
Dim wdStart As DateTime = New DateTime(dateTime1.Year, dateTime1.Month, dateTime1.Day, workdayStart.Hour, workdayStart.Minute, workdayStart.Second)
Dim wdEnd As DateTime = New DateTime(dateTime1.Year, dateTime1.Month, dateTime1.Day, workDayEnd.Hour, workDayEnd.Minute, workDayEnd.Second)
'calculate hours in a workday
Dim tsWorkday As TimeSpan = wdEnd - wdStart
Dim numDays As Integer = 0
Dim timeRemaining As TimeSpan = duration - (wdEnd - dateTime1)
'Debug.WriteLine("timeRemaining - " & timeRemaining.Hours & ":" & timeRemaining.Minutes & ":" & timeRemaining.Seconds)
If timeRemaining.TotalMinutes > 0 Then
Do
numDays += 1 'increment
'calculate
timeRemaining = timeRemaining - tsWorkday
If timeRemaining.TotalMinutes <= 0 Then
Dim tempTs As TimeSpan = New TimeSpan(24 * numDays, 0, 0)
endDT = wdEnd.Add(tempTs)
endDT = endDT.Add(timeRemaining)
End If
Loop While timeRemaining.TotalMinutes > 0
Else
endDT = wdEnd.Subtract(timeRemaining)
End If
'add day for each weekend day
If endDT.DayOfWeek = 0 Then
endDT = endDT.AddDays(1)
ElseIf endDT.DayOfWeek = 6 Then
endDT = endDT.AddDays(2)
End If
Return endDT
End Function
给定:
- 持续时间:12 小时
- dateTime1: 2021/08/10 08:00:00(您要从中开始计算的 Date/Time)
- 工作日开始: 08:00
- 工作日结束: 16:00
这转化为以下内容(见下文):
- 持续时间:新时间跨度(0, 12, 0, 0) - 这是 12 小时
- dateTime1: New DateTime(2021, 8, 10, 8, 0, 0) - 这是
2021/08/10 08:00:00
- workdayStart: New DateTime(2021, 8, 10, 8, 0, 0) - 未使用年、月和日的值
- workdayEnd: New DateTime(2021, 8, 10, 16, 0, 0) - 未使用年、月和日的值
注意:workdayStart
和workdayEnd
不使用年、月、日的值,但小时、分钟、第二个被使用。
用法:
Dim endDT1 As DateTime = CalculateEndDT(New TimeSpan(0, 12, 0, 0), New DateTime(2021, 8, 10, 8, 0, 0), New DateTime(2021, 8, 10, 8, 0, 0), New DateTime(2021, 8, 10, 16, 0, 0))
Dim endDT2 As DateTime = CalculateEndDT(New TimeSpan(0, 27, 0, 0), New DateTime(2021, 8, 11, 12, 0, 0), New DateTime(2021, 8, 11, 8, 0, 0), New DateTime(2021, 8, 11, 16, 0, 0))
Debug.WriteLine(endDT1.ToString("yyyy-M-d HH:mm"))
Debug.WriteLine(endDT2.ToString("yyyy-M-d HH:mm"))
结果:
2021-8-11 12:00
2021-8-16 15:00
我相信有很多方法可以做到这一点。以下是一种可能的解决方案。
下面的代码做出了一些假设……
- Datetime1 可以是任何日期。这个日期可以是周末约会。这个日期可以是具有小时时间值的日期,该时间值可以是……8 点之前(上午 8 点)……或者……16 点之后(下午 4 点)。
- Datetime2 只能是不在周末(周六或周日)的日期,并且小时时间值将始终为……大于或等于 8(dt2.Hour >= 8)……并且……小于或等于 16 (dt.Hour <= 16)。基本上 Datetime2 将始终是一个工作日(周一至周五),时间为上午 8 点至下午 4 点。
如果 Datetime1 始终是工作日,并且在上午 8 点到下午 4 点之间……那么下面的代码可以简化。但是下面的代码支持第一个假设。
为了解决这个问题,一种特殊的方法可能会派上用场。此方法将采用 DateTime
对象和 return 从给定日期开始的下一个工作日(周一至周五)。注意……如果给定日期已经是工作日,则原始给定日期为 returned。这有什么帮助,因为我们可能会在日期中添加“天数”……我们可能需要多次检查周末。在这一点上这有什么帮助可能并不明显;但是,当您看到它在 main 方法中的使用方式时,它应该会变得更加清晰。基本上,这种方法只是用来减少代码重复。
Private Function GetNextWorkday(Date1 As DateTime) As DateTime
Dim ReturnDate = Date1
While ReturnDate.DayOfWeek.Equals(DayOfWeek.Saturday) Or
ReturnDate.DayOfWeek.Equals(DayOfWeek.Sunday)
ReturnDate = ReturnDate.AddDays(1)
End While
Return ReturnDate
End Function
接下来我们有一个方法,它接受一个 DateTime
对象 Date1
和一个 int32
Duration
。此方法将 return 我们正在寻找的 Datetime2
值。
遍历下面的代码……首先我们假设给定日期 Date1
可能是周末(周六或周日)日期。所以第 1 步是使用我们上面的方法来获取从给定日期开始的下一个工作日日期。我们知道给定日期是否已经是工作日日期,那么我们上面的方法将简单地 return 相同的日期。这是通过以下行完成的...
Date1 = GetNextWorkday(Date1)
接下来我们创建一个名为 HoursLeft
的 Int32
变量并将其设置为给定的 Duration
值。我们将使用此变量“倒计时”到 8 或更小的值。这就是 While
循环正在做的事情。需要注意的是,由于我们可能会添加多天,所以我们需要调用上面的方法来忽略周末。
while 循环结束后,HoursLeft
将是一个等于或小于 8 的值。这是我们需要添加 Date1
日期的小时数。添加这些最后几个小时后,我们需要进行最后一次检查以确保添加这些小时不会发送日期 HOUR 值 PAST 16(下午 4 点)。
如果在添加最后几个小时后,小时值大于 16,那么,我们将知道我们需要再添加一天并将剩余小时数添加到新日期,其中 HOUR 为 8(上午 8 点) ) 加上剩余时间。
示例:如果在添加最后几个小时后日期的 HOUR 值为 18,那么我们就会知道我们需要在日期上添加一 (1) 天,然后将小时设置为 (18-16=2) + 8 = 10。换句话说,18 的值是 16 点后 2 小时,因此我们想在下一个工作日的 8(上午 8 点)开始增加两 (2) 小时。同样,因为我们可能会在日期中添加一天,所以我们需要第三次调用上面的方法。我希望这是有道理的。
Private Function ComputeDate2(Date1 As DateTime, Duration As Int32) As DateTime
Date1 = GetNextWorkday(Date1)
If (Duration < 0) Then
Duration = Math.Abs(Duration)
End If
Dim HoursLeft As Int32 = Duration
While HoursLeft > 8
HoursLeft -= 8
Date1 = Date1.AddDays(1)
Date1 = GetNextWorkday(Date1)
End While
Date1 = Date1.AddHours(HoursLeft)
If Date1.Hour > 16 Then
Dim dif As Int32 = Date1.Hour - 16
Date1 = Date1.AddDays(1)
Date1 = GetNextWorkday(Date1)
Date1 = New DateTime(Date1.Year, Date1.Month, Date1.Day, 8 + dif, 0, 0)
End If
Return Date1
End Function
要对此进行测试并完成示例,请创建一个新的 VB winforms 解决方案,将 DataGridView
和 Button
拖放到表单上。该按钮用于遍历网格中的所有行并设置 Datetime2
单元格值。
Dim GridTable As DataTable
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GridTable = GetData()
DataGridView1.DataSource = GridTable
DataGridView1.Columns("Date1").DefaultCellStyle.Format = "yyyy-MM-dd HH:mm"
DataGridView1.Columns("Date2").DefaultCellStyle.Format = "yyyy-MM-dd HH:mm"
DataGridView1.Columns("Date1").Width = 150
DataGridView1.Columns("Date2").Width = 150
End Sub
Function GetData() As DataTable
Dim dt = New DataTable
dt.Columns.Add("Duration", GetType(Int32))
dt.Columns.Add("Date1", GetType(DateTime))
dt.Columns.Add("Date2", GetType(DateTime))
dt.Rows.Add(12, New DateTime(2021, 8, 10, 8, 0, 0))
dt.Rows.Add(27, New DateTime(2021, 8, 11, 12, 0, 0))
dt.Rows.Add(28, New DateTime(2021, 8, 11, 12, 0, 0))
dt.Rows.Add(29, New DateTime(2021, 8, 11, 12, 0, 0))
dt.Rows.Add(40, New DateTime(2021, 8, 1, 8, 0, 0))
dt.Rows.Add(8, New DateTime(2021, 8, 7, 8, 0, 0))
Return dt
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim drv As DataRowView
Dim Dur As Int32
Dim date1 As DateTime
For Each row As DataGridViewRow In DataGridView1.Rows
If Not row.IsNewRow Then
drv = CType(row.DataBoundItem, DataRowView)
Dur = CType(drv("Duration"), Int32)
date1 = CType(drv("Date1"), DateTime)
If (date1.Hour > 16 Or date1.Hour < 8) Then
date1 = New DateTime(date1.Year, date1.Month, date1.Day, 8, 0, 0)
End If
drv("Date2") = ComputeDate2(date1, Dur)
End If
Next
DataGridView1.Refresh()
End Sub
我希望这是有道理的。