I'm attempting to use CreateTimeSpan() to hold information about how long my system will be down for maintenance given a starting date and time, and I've been running into a few interesting issues. I'd have thought that this would be a simple matter, as adding a timespan to an existing time stamp would be a useful mechanic, but it seems as though there are some hidden gotchas and, perhaps, some outright bugs.
I wanted to store two values in my application that describe when my application will be experiencing a period of down time: the starting datetime value, and the duration of the down time as a timespan. If figure that these values will be the most useful, as I anticipate that the durations of down times will remain consistent, while only the starting date and time will be changed. In order to figure out if the current time is within the window of down time though, I'm going to have to add the timespan to the datetime to arrive at a new datetime that is the date and time at which the down time window ends. I'd think that this would be a simple process, but apparently there isn't a function in CF to accomplish this task.
Undaunted, I decided to just create my own and move on, so I started looking at what was necessary to accomplish this task. First, I'd need to be able to extract a number of values from the timespan so that I can add them each individually to my starting datetime. Given that the four values sent to CreateTimeSpan() are day, hour, minute, and second, I went immediately to Day(), Hour(), Minute(), and Second() where I discovered something interesting:
<cfset x = CreateTimeSpan(0, 0, 0, 0) />
CreateTimeSpan(0, 0, 0, 0)<br />
Second: <cfdump var="#Second(x)#"><br />
Minute: <cfdump var="#Minute(x)#"><br />
Hour: <cfdump var="#Hour(x)#"><br />
Day: <cfdump var="#Day(x)#"><br />
CreateTimeSpan(0, 0, 0, 0)
Really? 30? Weird... so I plugged in some other values for the "day" parameter of CreateTimeSpan() and kept getting weird values... 1 gives 31, 2 yields 1, and 10 gives 9... whats going on here? The truth became more apparent once I tried passing the timespan into DateFormat(): "30-Dec-99".
Ah ha! I'm onto something here: the timespan is actually just a datetime starting on a specific date: hours, minutes, and seconds are fine because the date starts at 0 hours, 0 minutes, and 0 seconds, but days are off because the starting date already has a day value (30).
The simple work around for this is to use DateDiff() to compare the value of the timespan to its starting datetime value like so:
CreateTimeSpan(4, 3, 2, 1)<br />
Second:<cfdump var="#Second(x)#"><br />
Minute:<cfdump var="#Minute(x)#"><br />
Hour:<cfdump var="#Hour(x)#"><br />
Day:<cfdump var="#Day(x)#"><br />
TimeFormat: <cfdump var="#TimeFormat(x)#"><br />
DateFormat: <cfdump var="#DateFormat(x)#"><br />
DateDiff Day: <cfdump var="#DateDiff('d', '30-Dec-99', DateFormat(x))#">
Ends up with:
CreateTimeSpan(4, 3, 2, 1)
TimeFormat: 03:02 AM
DateDiff Day: 4
From there its a simple process to append each date part to a given datetime to find the end of the duration.