DateTime range issue when time passes midnight

2019-07-28 19:07发布

问题:

I'm doing an application for work and I've just ran into a brickwall.

We have 3 shifts, 06:00-13:36, 13:36-23:00 and 23:00-06:00. I have two labels, one to display shift start time and the other shift end time using the following code:

    Dim StartTimeN As Date = DateTime.Now.AddDays(-1).ToShortDateString & " 23:01"
    Dim EndTimeN As Date = DateTime.Now.ToShortDateString & " 06:00"
    Dim StartTimeF As Date = DateTime.Now.ToShortDateString & " 06:01"
    Dim EndTimeF As Date = DateTime.Now.ToShortDateString & " 13:36"
    Dim StartTimeE As Date = DateTime.Now.ToShortDateString & " 13:37"
    Dim EndTimeE As Date = DateTime.Now.ToShortDateString & " 23:00"
    Dim CurrentTime As Date = DateTime.Now


    If (CurrentTime.Ticks >= StartTimeN.Ticks And CurrentTime.Ticks <= EndTimeN.Ticks) Then
        Label1.Text = "23:00"
        Label2.Text = "06:00"
    ElseIf (CurrentTime.Ticks >= StartTimeF.Ticks And CurrentTime.Ticks <= EndTimeF.Ticks) Then
        Label1.Text = "06:00"
        Label2.Text = "13:36"
    ElseIf (CurrentTime.Ticks >= StartTimeE.Ticks And CurrentTime.Ticks <= EndTimeE.Ticks) Then
        Label1.Text = "13:36"
        Label2.Text = "23:00"
    End If

Code works fine, except for the nightshift. I can't have adddays(-1) between 23-00 since that messes up the datacollection from SQL. I have a chart that collects sql data between the shiftours (eg. 06:00-13:36 etc). This creates an issue for the hour between 23:00 and 23:59 since the AddDays(-1) collects the data from the previous day then. Sql select SUM query uses between DateTime.Now.ToShortDateString & " label1data(shiftstart)" and DateTime.Now

I'm not sure how to solve the hour between 23 and 00. Do I need to create a single IF statement for that hour and also a specific SQL function and then add together the results from 23:00-00:00 and 00:00-06:00 or is there an easier way of doing this?

I'm a beginner and I'm sorry if the answer is a simple one, but this issue has almost led me to the point of giving up on the application since I can't get it to work properly.

Other functions also based on shifthours is calculating the TimeSpan between shiftstart and DateTime.Now in order to get amount of hours that has passed during the shift so far. Then multiplying that with maxproducts per hour in order to display how many products that could have been produced if ran at max capacity. The entire application is build upon displaying information for the operators about their production during their shift.

Thankful for any assistance.

回答1:

Your issue is the fact that a night shift falls over two days, so you can't check it in the same way.

here is a solution for you. It may look complicated but it is an improved structure and will be easier to maintain. I have used timespans rather than dates as I think this lends itself better to this solution because you don't have to worry about the date portion

''' <summary>
''' A simple class to hold a shift start and end times
''' </summary>
Public Class Shift
    Public Property StartTime As TimeSpan
    Public Property EndTime As TimeSpan
    Public ReadOnly Property IsnightShift As Boolean
        Get
            Return EndTime < StartTime
        End Get
    End Property
    Public Sub New(startTime As TimeSpan, endTime As TimeSpan)
        Me.StartTime = startTime
        Me.EndTime = endTime
    End Sub
End Class

Then a function to find a shift from a list of shifts:

''' <summary>
''' Finds the shift for a given time
''' </summary>
''' <param name="shifts"></param>
''' <param name="timeNow"></param>
''' <returns></returns>
Public Function FindShiftStartAndEndTimes(shifts As List(Of Shift), timeNow As TimeSpan) As Shift
    Dim endOfDayTime As New TimeSpan(24, 0, 0)
    Dim startOfDay As New TimeSpan(0, 0, 0)

    For Each shift In shifts
        'nigh shift is a special case so check we are after the start time and before midnight OR after midnight on the next day and before the end of shift
        If shift.IsnightShift Then
            If (timeNow >= shift.StartTime AndAlso timeNow < endOfDayTime) OrElse 
               (timeNow >= startOfDay AndAlso timeNow < shift.EndTime) Then
                Return shift
            End If
        Else
            If timeNow >= shift.StartTime AndAlso timeNow < shift.EndTime Then
                Return shift
            End If
        End If
    Next
    Throw New Exception("Could not find a shift for that time")
End Function

Then you can find the current shift like this:

Private Sub Button8_Click(sender As Object, e As EventArgs) Handles Button8.Click
    'create a list of shifts
    Dim shifts As New List(Of Shift)
    'add your shifts to the list
    shifts.Add(New Shift(New TimeSpan(6, 0, 0), New TimeSpan(13, 36, 0)))
    shifts.Add(New Shift(New TimeSpan(13, 36, 0), New TimeSpan(23, 0, 0)))
    shifts.Add(New Shift(New TimeSpan(23, 0, 0), New TimeSpan(6, 0, 0)))

    'find the current shift
    Dim shift = FindShiftStartAndEndTimes(shifts, New TimeSpan(DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second))
    MessageBox.Show("Current Shift is " & shift.StartTime.ToString & "-" & shift.EndTime.ToString)
End Sub


回答2:

Yeah, you'll need to use a condition to determine what times to use depending on when it is:

Dim StartTimeN As Date
Dim EndTimeN As Date

If (DateTime.Now.Hour = 23) Then
    StartTimeN = DateTime.Now.ToShortDateString & " 23:01"
    EndTimeN = DateTime.Now.AddDays(1).ToShortDateString & " 06:00"
Else
    StartTimeN = DateTime.Now.AddDays(-1).ToShortDateString & " 23:01"
    EndTimeN = DateTime.Now.ToShortDateString & " 06:00"
End