Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows 7 daylight savings bug?

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:

enter image description here

...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?


EDIT:

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.

like image 594
tjwrona1992 Avatar asked Apr 14 '16 18:04

tjwrona1992


1 Answers

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:

  1. FileTimeToSystemTime
  2. SystemTimeToTzSpecificLocalTime
  3. 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.)

like image 174
Matt Johnson-Pint Avatar answered Sep 28 '22 09:09

Matt Johnson-Pint