1 package DateTime::TimeZone::Local::Win32;
6 use base 'DateTime::TimeZone::Local';
8 use Win32::TieRegistry ( 'KEY_READ', Delimiter => q{/} );
11 sub Methods { return qw( FromEnv FromRegistry ) }
13 sub EnvVars { return 'TZ' }
16 # This list comes (mostly) in the zipball for the Chronos project
17 # - a Smalltalk datetime library. Thanks, Chronos!
19 ( 'Afghanistan' => 'Asia/Kabul',
20 'Afghanistan Standard Time' => 'Asia/Kabul',
21 'Alaskan' => 'America/Anchorage',
22 'Alaskan Standard Time' => 'America/Anchorage',
23 'Arab' => 'Asia/Riyadh',
24 'Arab Standard Time' => 'Asia/Riyadh',
25 'Arabian' => 'Asia/Muscat',
26 'Arabian Standard Time' => 'Asia/Muscat',
27 'Arabic Standard Time' => 'Asia/Baghdad',
28 'Argentina Standard Time' => 'America/Argentina/Buenos_Aires',
29 'Armenian Standard Time' => 'Asia/Yerevan',
30 'Atlantic' => 'America/Halifax',
31 'Atlantic Standard Time' => 'America/Halifax',
32 'AUS Central' => 'Australia/Darwin',
33 'AUS Central Standard Time' => 'Australia/Darwin',
34 'AUS Eastern' => 'Australia/Sydney',
35 'AUS Eastern Standard Time' => 'Australia/Sydney',
36 'Azerbaijan Standard Time' => 'Asia/Baku',
37 'Azores' => 'Atlantic/Azores',
38 'Azores Standard Time' => 'Atlantic/Azores',
39 'Bangkok' => 'Asia/Bangkok',
40 'Bangkok Standard Time' => 'Asia/Bangkok',
41 'Beijing' => 'Asia/Shanghai',
42 'Canada Central' => 'America/Regina',
43 'Canada Central Standard Time' => 'America/Regina',
44 'Cape Verde Standard Time' => 'Atlantic/Cape_Verde',
45 'Caucasus' => 'Asia/Yerevan',
46 'Caucasus Standard Time' => 'Asia/Yerevan',
47 'Cen. Australia' => 'Australia/Adelaide',
48 'Cen. Australia Standard Time' => 'Australia/Adelaide',
49 'Central' => 'America/Chicago',
50 'Central America Standard Time' => 'America/Regina',
51 'Central Asia' => 'Asia/Dhaka',
52 'Central Asia Standard Time' => 'Asia/Dhaka',
53 'Central Brazilian Standard Time' => 'America/Manaus',
54 'Central Europe' => 'Europe/Prague',
55 'Central Europe Standard Time' => 'Europe/Prague',
56 'Central European' => 'Europe/Belgrade',
57 'Central European Standard Time' => 'Europe/Belgrade',
58 'Central Pacific' => 'Pacific/Guadalcanal',
59 'Central Pacific Standard Time' => 'Pacific/Guadalcanal',
60 'Central Standard Time' => 'America/Chicago',
61 'Central Standard Time (Mexico)' => 'America/Mexico_City',
62 'China' => 'Asia/Shanghai',
63 'China Standard Time' => 'Asia/Shanghai',
64 'Dateline' => 'Pacific/Majuro',
65 'Dateline Standard Time' => 'Pacific/Majuro',
66 'E. Africa' => 'Africa/Nairobi',
67 'E. Africa Standard Time' => 'Africa/Nairobi',
68 'E. Australia' => 'Australia/Brisbane',
69 'E. Australia Standard Time' => 'Australia/Brisbane',
70 'E. Europe' => 'Europe/Minsk',
71 'E. Europe Standard Time' => 'Europe/Minsk',
72 'E. South America' => 'America/Sao_Paulo',
73 'E. South America Standard Time' => 'America/Sao_Paulo',
74 'Eastern' => 'America/New_York',
75 'Eastern Standard Time' => 'America/New_York',
76 'Egypt' => 'Africa/Cairo',
77 'Egypt Standard Time' => 'Africa/Cairo',
78 'Ekaterinburg' => 'Asia/Yekaterinburg',
79 'Ekaterinburg Standard Time' => 'Asia/Yekaterinburg',
80 'Fiji' => 'Pacific/Fiji',
81 'Fiji Standard Time' => 'Pacific/Fiji',
82 'FLE' => 'Europe/Helsinki',
83 'FLE Standard Time' => 'Europe/Helsinki',
84 'Georgian Standard Time' => 'Asia/Tbilisi',
85 'GFT' => 'Europe/Athens',
86 'GFT Standard Time' => 'Europe/Athens',
87 'GMT' => 'Europe/London',
88 'GMT Standard Time' => 'Europe/London',
89 'Greenland Standard Time' => 'America/Godthab',
91 'Greenwich Standard Time' => 'GMT',
92 'GTB' => 'Europe/Athens',
93 'GTB Standard Time' => 'Europe/Athens',
94 'Hawaiian' => 'Pacific/Honolulu',
95 'Hawaiian Standard Time' => 'Pacific/Honolulu',
96 'India' => 'Asia/Calcutta',
97 'India Standard Time' => 'Asia/Calcutta',
98 'Iran' => 'Asia/Tehran',
99 'Iran Standard Time' => 'Asia/Tehran',
100 'Israel' => 'Asia/Jerusalem',
101 'Israel Standard Time' => 'Asia/Jerusalem',
102 'Jordan Standard Time' => 'Asia/Amman',
103 'Kamchatka Standard Time' => 'Asia/Kamchatka',
104 'Korea' => 'Asia/Seoul',
105 'Korea Standard Time' => 'Asia/Seoul',
106 'Mauritius Standard Time' => 'Indian/Mauritius',
107 'Mexico' => 'America/Mexico_City',
108 'Mexico Standard Time' => 'America/Mexico_City',
109 'Mexico Standard Time 2' => 'America/Chihuahua',
110 'Mid-Atlantic' => 'Atlantic/South_Georgia',
111 'Mid-Atlantic Standard Time' => 'Atlantic/South_Georgia',
112 'Middle East Standard Time' => 'Asia/Beirut',
113 'Montevideo Standard Time' => 'America/Montevideo',
114 'Morocco Standard Time' => 'Africa/Casablanca',
115 'Mountain' => 'America/Denver',
116 'Mountain Standard Time' => 'America/Denver',
117 'Mountain Standard Time (Mexico)' => 'America/Chihuahua',
118 'Myanmar Standard Time' => 'Asia/Rangoon',
119 'N. Central Asia Standard Time' => 'Asia/Novosibirsk',
120 'Namibia Standard Time' => 'Africa/Windhoek',
121 'Nepal Standard Time' => 'Asia/Katmandu',
122 'New Zealand' => 'Pacific/Auckland',
123 'New Zealand Standard Time' => 'Pacific/Auckland',
124 'Newfoundland' => 'America/St_Johns',
125 'Newfoundland Standard Time' => 'America/St_Johns',
126 'North Asia East Standard Time' => 'Asia/Ulaanbaatar',
127 'North Asia Standard Time' => 'Asia/Krasnoyarsk',
128 'Pacific' => 'America/Los_Angeles',
129 'Pacific SA' => 'America/Santiago',
130 'Pacific SA Standard Time' => 'America/Santiago',
131 'Pacific Standard Time' => 'America/Los_Angeles',
132 'Pacific Standard Time (Mexico)' => 'America/Tijuana',
133 'Pakistan Standard Time' => 'Asia/Karachi',
134 'Paraguay Standard Time' => 'America/Asuncion',
135 'Prague Bratislava' => 'Europe/Prague',
136 'Romance' => 'Europe/Paris',
137 'Romance Standard Time' => 'Europe/Paris',
138 'Russian' => 'Europe/Moscow',
139 'Russian Standard Time' => 'Europe/Moscow',
140 'SA Eastern' => 'America/Buenos_Aires',
141 'SA Eastern Standard Time' => 'America/Buenos_Aires',
142 'SA Pacific' => 'America/Bogota',
143 'SA Pacific Standard Time' => 'America/Bogota',
144 'SA Western' => 'America/Caracas',
145 'SA Western Standard Time' => 'America/Caracas',
146 'Samoa' => 'Pacific/Apia',
147 'Samoa Standard Time' => 'Pacific/Apia',
148 'Saudi Arabia' => 'Asia/Riyadh',
149 'Saudi Arabia Standard Time' => 'Asia/Riyadh',
150 'SE Asia' => 'Asia/Bangkok',
151 'SE Asia Standard Time' => 'Asia/Bangkok',
152 'Singapore' => 'Asia/Singapore',
153 'Singapore Standard Time' => 'Asia/Singapore',
154 'South Africa' => 'Africa/Harare',
155 'South Africa Standard Time' => 'Africa/Harare',
156 'Sri Lanka' => 'Asia/Colombo',
157 'Sri Lanka Standard Time' => 'Asia/Colombo',
158 'Sydney Standard Time' => 'Australia/Sydney',
159 'Taipei' => 'Asia/Taipei',
160 'Taipei Standard Time' => 'Asia/Taipei',
161 'Tasmania' => 'Australia/Hobart',
162 'Tasmania Standard Time' => 'Australia/Hobart',
163 'Tokyo' => 'Asia/Tokyo',
164 'Tokyo Standard Time' => 'Asia/Tokyo',
165 'Tonga Standard Time' => 'Pacific/Tongatapu',
166 'US Eastern' => 'America/Indianapolis',
167 'US Eastern Standard Time' => 'America/Indianapolis',
168 'US Mountain' => 'America/Phoenix',
169 'US Mountain Standard Time' => 'America/Phoenix',
171 'Venezuela Standard Time' => 'America/Caracas',
172 'Vladivostok' => 'Asia/Vladivostok',
173 'Vladivostok Standard Time' => 'Asia/Vladivostok',
174 'W. Australia' => 'Australia/Perth',
175 'W. Australia Standard Time' => 'Australia/Perth',
176 'W. Central Africa Standard Time' => 'Africa/Luanda',
177 'W. Europe' => 'Europe/Berlin',
178 'W. Europe Standard Time' => 'Europe/Berlin',
179 'Warsaw' => 'Europe/Warsaw',
180 'West Asia' => 'Asia/Karachi',
181 'West Asia Standard Time' => 'Asia/Karachi',
182 'West Pacific' => 'Pacific/Guam',
183 'West Pacific Standard Time' => 'Pacific/Guam',
184 'Western Brazilian Standard Time' => 'America/Rio_Branco',
185 'Yakutsk' => 'Asia/Yakutsk',
186 'Yakutsk Standard Time' => 'Asia/Yakutsk',
193 my $win_name = $class->_FindWindowsTZName();
195 # On Windows 2008 Server, there is additional junk after a
197 $win_name =~ s/\0.*$//
198 if defined $win_name;
200 return unless defined $win_name;
202 my $olson = $WinToOlson{$win_name};
204 return unless $olson;
206 return unless $class->_IsValidName($olson);
210 return eval { DateTime::TimeZone->new( name => $olson ) };
214 sub _FindWindowsTZName
218 my $LMachine = $Registry->Open( 'LMachine/', { Access => KEY_READ } );
221 $LMachine->{'SYSTEM/CurrentControlSet/Control/TimeZoneInformation/'};
223 # Windows Vista, Windows 2008 Server
224 if ( defined $TimeZoneInfo->{'/TimeZoneKeyName'} &&
225 $TimeZoneInfo->{'/TimeZoneKeyName'} ne '' )
227 return $TimeZoneInfo->{'/TimeZoneKeyName'};
232 $LMachine->{'SOFTWARE/Microsoft/Windows NT/CurrentVersion/Time Zones/'}
233 # Windows NT, Windows 2000, Windows XP, Windows 2003 Server
234 ? $LMachine->{'SOFTWARE/Microsoft/Windows NT/CurrentVersion/Time Zones/'}
235 # Windows 95, Windows 98, Windows Millenium Edition
236 : $LMachine->{'SOFTWARE/Microsoft/Windows/CurrentVersion/Time Zones/'};
238 foreach my $zone ( $AllTimeZones->SubKeyNames() )
240 if ( $AllTimeZones->{ $zone . '/Std' } eq $TimeZoneInfo->{'/StandardName'} )
257 DateTime::TimeZone::Local::Win32 - Determine the local system's time zone on Windows
261 my $tz = DateTime::TimeZone->new( name => 'local' );
263 my $tz = DateTime::TimeZone::Local->TimeZone();
267 This module provides methods for determining the local time zone on a
270 =head1 HOW THE TIME ZONE IS DETERMINED
272 This class tries the following methods of determining the local time
279 It checks C<< $ENV{TZ} >> for a valid time zone name.
281 =item * Windows Registry
283 When using the registry, we look for the Windows time zone and use a
284 mapping to translate this to an Olson time zone name.
288 =item * Windows Vista and 2008
290 We look in "SYSTEM/CurrentControlSet/Control/TimeZoneInformation/" for
291 a node named "/TimeZoneKeyName". If this exists, we use this key to
292 look up the Olson time zone name in our mapping.
294 =item * Windows NT, Windows 2000, Windows XP, Windows 2003 Server
296 We look in "SOFTWARE/Microsoft/Windows NT/CurrentVersion/Time Zones/"
297 and loop through all of its sub keys.
299 For each sub key, we compare the value of the key with "/Std" appended
300 to the end to the value of
301 "SYSTEM/CurrentControlSet/Control/TimeZoneInformation/StandardName". This
302 gives us the I<English> name of the Windows time zone, which we use to
303 look up the Olson time zone name.
305 =item * Windows 95, Windows 98, Windows Millenium Edition
307 The algorithm is the same as for NT, but we loop through the sub keys
308 of "SOFTWARE/Microsoft/Windows/CurrentVersion/Time Zones/"
316 Dave Rolsky, <autarch@urth.org>
318 =head1 COPYRIGHT & LICENSE
320 Copyright (c) 2003-2008 David Rolsky. All rights reserved. This
321 program is free software; you can redistribute it and/or modify it
322 under the same terms as Perl itself.
324 The full text of the license can be found in the LICENSE file included