I am trying to determine exactly when a daylight savings transition occurs in a Perl script using Perl's localtime
function and printing the time zone using strftime
.
The strange thing is this seems to work fine for this year and other more recent years, but if I try and go back to the year 2000 for example, Perl seems to think the transition occurs on the wrong day!
According to Google, daylight savings started on April 2nd in the year 2000:
...but for some reason, the Perl code below seems to disagree:
use POSIX qw(strftime);
use Time::Local;
# 03/12/2000 01:59:59
($year, $month, $day, $hour, $minute, $second) = (2000, 3, 12, 1, 59, 59);
$epoch = timelocal($second, $minute, $hour, $day, $month - 1, $year);
# Print the time
print strftime "%m/%d/%Y %H:%M:%S - %Z\n", localtime($epoch);
# 03/12/2000 02:00:00
($year, $month, $day, $hour, $minute, $second) = (2000, 3, 12, 2, 0, 0);
$epoch = timelocal($second, $minute, $hour, $day, $month - 1, $year);
# Print the time
print strftime "%m/%d/%Y %H:%M:%S - %Z\n", localtime($epoch);
Output:
03/12/2000 01:59:59 - Eastern Standard Time
03/12/2000 03:00:00 - Eastern Daylight Time
Why does Perl think that daylight savings time in the year 2000 started on March 12th when clearly this is incorrect?
After reading the comments below it looks like this may be an issue with the operating system and not Perl. It looks like this may be a bug in Windows 7.
I don't know the specifics of the Perl internals (nor do I feel like scouring through the source code), but bugs like this usually happen on Windows when using the FileTimeToLocalFileTime
and LocalFileTimeToFileTime
Win32 functions. These functions don't take the history of time zones into account, only the current rules. The documentation explains what to do instead:
To account for daylight saving time when converting a file time to a local time, use the following sequence of functions in place of using
FileTimeToLocalFileTime
:
- FileTimeToSystemTime
- SystemTimeToTzSpecificLocalTime
- SystemTimeToFileTime
A similar sequence should be done for the inverse function, using TzSpecificLocalTimeToSystemTime
for the middle step.
It's likely that the version of Perl you're running is calling these functions as part of the Win32 implementation of the localtime
and timelocal
functions. Based on the comments in the question that some couldn't reproduce your results, I'd guess that newer versions of Perl probably have been patched as described above. If not, they should be. (I'm sure someone more familiar with Perl internals could point out the specific code and bug report.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With