Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / DateTime / TimeZone / Local / Win32.pm
1 package DateTime::TimeZone::Local::Win32;
2
3 use strict;
4 use warnings;
5
6 use base 'DateTime::TimeZone::Local';
7
8 use Win32::TieRegistry ( 'KEY_READ', Delimiter => q{/} );
9
10
11 sub Methods { return qw( FromEnv FromRegistry ) }
12
13 sub EnvVars { return 'TZ' }
14
15 {
16     # This list comes (mostly) in the zipball for the Chronos project
17     # - a Smalltalk datetime library. Thanks, Chronos!
18     my %WinToOlson =
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',
90           'Greenwich'                       => 'GMT',
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',
170           'UTC'                             => 'UTC',
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',
187         );
188
189     sub FromRegistry
190     {
191         my $class = shift;
192
193         my $win_name = $class->_FindWindowsTZName();
194
195         # On Windows 2008 Server, there is additional junk after a
196         # null character.
197         $win_name =~ s/\0.*$//
198             if defined $win_name;
199
200         return unless defined $win_name;
201
202         my $olson = $WinToOlson{$win_name};
203
204         return unless $olson;
205
206         return unless $class->_IsValidName($olson);
207
208         local $@;
209         local $SIG{__DIE__};
210         return eval { DateTime::TimeZone->new( name => $olson ) };
211     }
212 }
213
214 sub _FindWindowsTZName
215 {
216     my $class = shift;
217
218     my $LMachine = $Registry->Open( 'LMachine/', { Access => KEY_READ } );
219
220     my $TimeZoneInfo =
221         $LMachine->{'SYSTEM/CurrentControlSet/Control/TimeZoneInformation/'};
222
223     # Windows Vista, Windows 2008 Server
224     if ( defined $TimeZoneInfo->{'/TimeZoneKeyName'} &&
225          $TimeZoneInfo->{'/TimeZoneKeyName'} ne '' )
226     {
227         return $TimeZoneInfo->{'/TimeZoneKeyName'};
228     }
229     else
230     {
231         my $AllTimeZones =
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/'};
237
238         foreach my $zone ( $AllTimeZones->SubKeyNames() )
239         {
240             if ( $AllTimeZones->{ $zone . '/Std' } eq $TimeZoneInfo->{'/StandardName'} )
241             {
242                 return $zone;
243             }
244         }
245     }
246
247     return;
248 }
249
250
251 1;
252
253 __END__
254
255 =head1 NAME
256
257 DateTime::TimeZone::Local::Win32 - Determine the local system's time zone on Windows
258
259 =head1 SYNOPSIS
260
261   my $tz = DateTime::TimeZone->new( name => 'local' );
262
263   my $tz = DateTime::TimeZone::Local->TimeZone();
264
265 =head1 DESCRIPTION
266
267 This module provides methods for determining the local time zone on a
268 Windows platform.
269
270 =head1 HOW THE TIME ZONE IS DETERMINED
271
272 This class tries the following methods of determining the local time
273 zone:
274
275 =over 4
276
277 =item * $ENV{TZ}
278
279 It checks C<< $ENV{TZ} >> for a valid time zone name.
280
281 =item * Windows Registry
282
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.
285
286 =over 8
287
288 =item * Windows Vista and 2008
289
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.
293
294 =item * Windows NT, Windows 2000, Windows XP, Windows 2003 Server
295
296 We look in "SOFTWARE/Microsoft/Windows NT/CurrentVersion/Time Zones/"
297 and loop through all of its sub keys.
298
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.
304
305 =item * Windows 95, Windows 98, Windows Millenium Edition
306
307 The algorithm is the same as for NT, but we loop through the sub keys
308 of "SOFTWARE/Microsoft/Windows/CurrentVersion/Time Zones/"
309
310 =back
311
312 =back
313
314 =head1 AUTHOR
315
316 Dave Rolsky, <autarch@urth.org>
317
318 =head1 COPYRIGHT & LICENSE
319
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.
323
324 The full text of the license can be found in the LICENSE file included
325 with this module.
326
327 =cut