Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the DateTime-TimeZone CPAN distribution.

Report information
The Basics
Id: 36201
Status: resolved
Priority: 0/
Queue: DateTime-TimeZone

People
Owner: Nobody in particular
Requestors: david.pinkowitz [...] numarasoftware.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.76
Fixed in: 0.79



Subject: Determining local time zone in Windows will fail for non-English Windows and other issues
There are a few issues my attached patch intends to fix: 1) LMachine/SYSTEM/CurrentControlSet/Control/TimeZoneInformation/StandardName simply stores the localized name of the Windows time zone. This name changes in non-English language versions of Windows. In those versions of Windows, you will be unable to select a correct time zone, as those names are not in the list of Windows time zones DateTime-TimeZone maps to the Olson time zones. An example of this can be seen by selecting the time zone for Jerusalem on any English version of Windows. The "StandardName" value is "Jerusalem Standard Time," but the time zone key name is "Israel Standard Time." By using the time zone keys rather than the "StandardName" value, not only is the value in the list already in this module, but the key name is also identical across non-English versions of Windows as well. The patch fixes the problem by looking up the StandardName value, just as before, but then comparing it to the "Std" value located in each time zone subkey under: LMachine/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Time Zones/ It is this value that is copied to the CurrentControlSet when you select a time zone on Windows. I tested this and it works on a Japanese version of Windows Server 2003. The previous DateTime-TimeZone code did not work. I should note that on Vista and Windows Server 2008, the change in the TimeZoneInformation key to use "TimeZoneKeyName" meant that no additional lookup was necessary for those systems. In the patch, I also included the registry keys for Windows 95, Windows 98 and Windows ME, but I based that on Microsoft documentation in various support articles. I did not have a system to test the code on there. I changed the pod documentation slightly to reflect the changes in this patch. 2) The hash converting Windows time zones to Olson time zones contained duplicate keys for 'GMT Standard Time' and 'Tasmania Standard Time.' These are removed in my patch and in the case of 'GMT Standard Time,' which in the current code points to two different Olson time zones and ends up selecting the incorrect zone, now corrects the zone to point to Europe/London. 3) The hash of Windows time zones is missing some recently added time zones. I've added the following Windows time zones to the patch: 'Armenian Standard Time' => 'Asia/Yerevan', 'Montevideo Standard Time' => 'America/Montevideo', 'Venezuela Standard Time' => 'America/Caracas',
Subject: Win32.patch
Index: D:/FootPrints/FPSQL/bin/Perl/site/lib/DateTime/TimeZone/Local/Win32.pm =================================================================== --- C:/Perl/site/lib/DateTime/TimeZone/Local/Win32.pm (revision 4346) +++ C:/Perl/site/lib/DateTime/TimeZone/Local/Win32.pm (revision 4379) @@ -25,6 +25,7 @@ 'Arabian' => 'Asia/Muscat', 'Arabian Standard Time' => 'Asia/Muscat', 'Arabic Standard Time' => 'Asia/Baghdad', + 'Armenian Standard Time' => 'Asia/Yerevan', 'Atlantic' => 'America/Halifax', 'Atlantic Standard Time' => 'America/Halifax', 'AUS Central' => 'Australia/Darwin', @@ -84,7 +85,6 @@ 'GFT Standard Time' => 'Europe/Athens', 'GMT' => 'Europe/London', 'GMT Standard Time' => 'Europe/London', - 'GMT Standard Time' => 'GMT', 'Greenland Standard Time' => 'America/Godthab', 'Greenwich' => 'GMT', 'Greenwich Standard Time' => 'GMT', @@ -107,6 +107,7 @@ 'Mid-Atlantic' => 'Atlantic/South_Georgia', 'Mid-Atlantic Standard Time' => 'Atlantic/South_Georgia', 'Middle East Standard Time' => 'Asia/Beirut', + 'Montevideo Standard Time' => 'America/Montevideo', 'Mountain' => 'America/Denver', 'Mountain Standard Time' => 'America/Denver', 'Mountain Standard Time (Mexico)' => 'America/Chihuahua', @@ -153,7 +154,6 @@ 'Taipei Standard Time' => 'Asia/Taipei', 'Tasmania' => 'Australia/Hobart', 'Tasmania Standard Time' => 'Australia/Hobart', - 'Tasmania Standard Time' => 'Australia/Hobart', 'Tokyo' => 'Asia/Tokyo', 'Tokyo Standard Time' => 'Asia/Tokyo', 'Tonga Standard Time' => 'Pacific/Tongatapu', @@ -161,6 +161,7 @@ 'US Eastern Standard Time' => 'America/Indianapolis', 'US Mountain' => 'America/Phoenix', 'US Mountain Standard Time' => 'America/Phoenix', + 'Venezuela Standard Time' => 'America/Caracas', 'Vladivostok' => 'Asia/Vladivostok', 'Vladivostok Standard Time' => 'Asia/Vladivostok', 'W. Australia' => 'Australia/Perth', @@ -178,19 +179,40 @@ 'Yakutsk Standard Time' => 'Asia/Yakutsk', ); - my $Key = - 'LMachine/SYSTEM/CurrentControlSet/Control/TimeZoneInformation'; - sub FromRegistry { my $class = shift; - my $keyObject = $Registry->Open( $Key, { Access => KEY_READ } ); + my $LMachine = $Registry->Open( 'LMachine/', { Access => KEY_READ } ); + my $TimeZoneInfo = + $LMachine->{'SYSTEM/CurrentControlSet/Control/TimeZoneInformation/'}; - my $win_name = - defined $keyObject->{'/TimeZoneKeyName'} && $keyObject->{'/TimeZoneKeyName'} ne '' - ? $keyObject->{'/TimeZoneKeyName'} - : $keyObject->{'/StandardName'}; + my $win_name; + + # Windows Vista, Windows 2008 Server + if (defined $TimeZoneInfo->{'/TimeZoneKeyName'} && + $TimeZoneInfo->{'/TimeZoneKeyName'} ne '') + { + $win_name = $TimeZoneInfo->{'/TimeZoneKeyName'}; + } + else + { + my $AllTimeZones = + $LMachine->{'SOFTWARE/Microsoft/Windows NT/CurrentVersion/Time Zones/'} + # Windows NT, Windows 2000, Windows XP, Windows 2003 Server + ? $LMachine->{'SOFTWARE/Microsoft/Windows NT/CurrentVersion/Time Zones/'} + # Windows 95, Windows 98, Windows Millenium Edition + : $LMachine->{'SOFTWARE/Microsoft/Windows/CurrentVersion/Time Zones/'}; + + foreach my $zone ($AllTimeZones->SubKeyNames()) + { + if ($AllTimeZones->{"${zone}/Std"} eq $TimeZoneInfo->{'/StandardName'}) + { + $win_name = $zone; + last; + } + } + } # On Windows 2008 Server, there is additional junk after a # null character. @@ -243,10 +265,12 @@ =item * Windows Registry We check for a registry key called -"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\StandardName". +"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation". -If this exists, it contains a Windows name for the time zone. We use a -lookup table to translate this into an equivalent time zone name. +If this exists, we use its values to determine the currently selected time +zone key from the registry. The name of this key is the Windows name for +the time zone. We use a lookup table to translate this into an equivalent +time zone name. This lookup table was borrowed from the Chronos Smalltalk library.