DST
Everyone who works professionally with computers or software has at least heard about Daylight Saving Time issues and has likely grappled with them at one time or another. Incorrectly accounting for DST can wreak havoc with date sensitive processes like payroll, logging, and synchronizing systems.
Well, at the J.O. B. there was just such an occurrence relating to the daily time and attendance system software that computes time sheet hours for hourly workers based on a scheduled shift. The software was still using the old rules for DST; specifically the last Sunday of October instead of the first Sunday in November. Since the law changed the rules in 2005 and the rules went into affect this year, 2007, there have been numerous operating system and software patches to reflect the new rules. However, relying on the operating system patches to solve all your company’s DST issues will be a big mistake in almost every case as many programs were written by dumb asses who hard coded the DST rules into each and every application.
On my current job I am just a contractor who basically does whatever I am told, within reason. Even if I had the authority to fix such a problem before it occurred I would not have known where in the dozens and dozens of applications and millions of lines of code to look to even know about the problem. But when the graveyard shift is being paid for 13 hours instead 12 it suddenly becomes my problem and many people down in the cubes are satisfied to believe it is all my fault as well. I love being a contractor. Thick skin is definitely an asset.
Not wanting to go through the unpleasant experience ever again I tried to to come up with a way that the system would be configurable so that if or when the DST rules change again it will be as effortless as possible to make the changes to the code. I wrote the following and pasted it over three pages of existing code to compute whether a DST adjustment was needed. None of this everĀ happens unless there is a Sunday involved.
First, set up some constants to represent the DST rules (yes, I am working in VB for now):
Const SPRING_FORWARD_MONTH = 3
Const SPRING_SUNDAY = 2
Const FALL_BACK_MONTH = 11
Const FALL_SUNDAY = 1
Const TIME_CHANGE_HOUR = 2
The above assumes the change will always be on a Sunday. Set the month, the Sunday (eg, 1st or 2nd etc), and the hour the time changes and the rest is handled computationally.
Private Function DSTFactorMins(ByVal inStartTime As Date, _
ByVal inEndTime As Date) As Integer
Dim vDayOfYear As Integer
Dim vEndingDayOfYear As Integer
Dim vStartingDayOfYear As Integer
Dim vSpringDay As Integer
Dim vFallDay As Integer
Dim vStartTime As Integer
Dim vEndTime As Integer
Dim adjType As String
vStartingDayOfYear = DatePart("y", inStartTime) 'y' parameter returns the day of year
vEndingDayOfYear = DatePart("y", inEndTime)
'DST changes only affect those whose shift starts before the change and
'ends after the change, ie, graveyard shift
If Weekday(inStartTime) = vbSaturday Then
vStartTime = 0
Else
vStartTime = DatePart("h", inStartTime)
End If
vEndTime = DatePart("h", inEndTime)
If (vStartTime < TIME_CHANGE_HOUR And TIME_CHANGE_HOUR <= vEndTime) Then
If springForward(inStartTime) Or springForward(inEndTime) Then
DSTFactorMins = -60 'minutes.
adjType = "SPRING_FORWARD"
ElseIf fallBack(inStartTime) Or fallBack(inEndTime) Then
DSTFactorMins = 60 'minutes.
adjType = "FALL_BACK"
Else
DSTFactorMins = 0
adjType = ""
End If
End If
Debug.Print "DST " & adjType & " adjustment is: " & Str$(DSTFactorMins)
End Function
Private Function springForward(ByVal inDate As Date) As Boolean
wMonth = CInt(Format$(inDate, "mm"))
springForward = False
Dim vToday As Integer
If wMonth = SPRING_FORWARD_MONTH Then
vToday = DatePart("d", inDate)
If vToday >= ((SPRING_SUNDAY - 1) * 7) And vToday <= (SPRING_SUNDAY * 7) Then
springForward = True
End If
End If
End Function
Private Function fallBack(ByVal inDate As Date) As Boolean
wMonth = CInt(Format$(inDate, "mm"))
fallBack = False
Dim vToday As Integer
If wMonth = FALL_BACK_MONTH Then
vToday = DatePart("d", inDate)
If vToday >= ((FALL_SUNDAY - 1) * 7) And vToday <= (FALL_SUNDAY * 7) Then
fallBack = True
End If
End If
End Function
The obsessive compulsive programmer in me wanted to combine the fallBack and springForward functions but the lazy contractor decided not to. To Change back to the old DST rules just change the constants:
Const SPRING_FORWARD_MONTH = 4
Const SPRING_SUNDAY = 1
Const FALL_BACK_MONTH = 10
Const FALL_SUNDAY = 3
Const TIME_CHANGE_HOUR = 2
Unfortunately for this particular application the code is compiled, put on a server and run on a schedule. Ideally, a system profile should be used so that these types of changes can be made without altering the code at all, but I am only a system engineer, not God. I can only do so much. It took these guys well over a decade to get into the mess they are in and it can’t be fixed in a few months.