File Coverage

blib/lib/Time/Zone.pm
Criterion Covered Total %
statement 38 58 65.5
branch 18 48 37.5
condition 6 12 50.0
subroutine 6 7 85.7
pod 0 5 0.0
total 68 130 52.3


line stmt bran cond sub pod time code
1              
2             package Time::Zone;
3              
4              
5             require 5.006;
6              
7             require Exporter;
8 8     8   77684 use Carp;
  8         15  
  8         516  
9 8     8   55 use strict;
  8         12  
  8         9947  
10              
11             our $VERSION = '2.34'; # VERSION: generated
12             # ABSTRACT: miscellaneous timezone manipulations routines
13             our @ISA = qw(Exporter);
14             our @EXPORT = qw(tz2zone tz_local_offset tz_offset tz_name);
15              
16             # Parts stolen from code by Paul Foley
17              
18             my %tzn_cache;
19             sub tz2zone (;$$$)
20             {
21 0     0 0 0 my($TZ, $time, $isdst) = @_;
22              
23 0 0       0 $TZ = defined($ENV{'TZ'}) ? ( $ENV{'TZ'} ? $ENV{'TZ'} : 'GMT' ) : ''
    0          
    0          
24             unless $TZ;
25              
26             # Hack to deal with 'PST8PDT' format of TZ
27             # Note that this can't deal with all the esoteric forms, but it
28             # does recognize the most common: [:]STDoff[DST[off][,rule]]
29              
30 0 0       0 if (! defined $isdst) {
31 0         0 my $j;
32 0 0       0 $time = time() unless $time;
33 0         0 ($j, $j, $j, $j, $j, $j, $j, $j, $isdst) = localtime($time);
34             }
35              
36 0 0       0 if (defined $tzn_cache{$TZ}->[$isdst]) {
37 0         0 return $tzn_cache{$TZ}->[$isdst];
38             }
39              
40 0 0       0 if ($TZ =~ /^
41             ( [^:\d+\-,] {3,} )
42             ( [+-] ?
43             \d {1,2}
44             ( : \d {1,2} ) {0,2}
45             )
46             ( [^\d+\-,] {3,} )?
47             /x
48             ) {
49 0 0       0 my $dsttz = defined($4) ? $4 : $1;
50 0 0       0 $TZ = $isdst ? $dsttz : $1;
51 0         0 $tzn_cache{$TZ} = [ $1, $dsttz ];
52             } else {
53 0         0 $tzn_cache{$TZ} = [ $TZ, $TZ ];
54             }
55 0         0 return $TZ;
56             }
57              
58             my @tz_local;
59             sub tz_local_offset (;$)
60             {
61 160     160 0 12276 my ($time) = @_;
62              
63 160 100       414 $time = time() unless $time;
64 160         1960 my (@l) = localtime($time);
65 160         386 my $isdst = $l[8];
66              
67 160 100       512 if (defined($tz_local[$isdst])) {
68 156         514 return $tz_local[$isdst];
69             }
70              
71 4         15 $tz_local[$isdst] = &calc_off($time);
72              
73 4         13 return $tz_local[$isdst];
74             }
75              
76             sub calc_off
77             {
78 4     4 0 11 my ($time) = @_;
79              
80 4         38 my (@l) = localtime($time);
81 4         16 my (@g) = gmtime($time);
82              
83 4         8 my $off;
84              
85 4         16 $off = $l[0] - $g[0]
86             + ($l[1] - $g[1]) * 60
87             + ($l[2] - $g[2]) * 3600;
88              
89             # subscript 7 is yday.
90              
91 4 50       16 if ($l[7] == $g[7]) {
    0          
    0          
    0          
92             # done
93             } elsif ($l[7] == $g[7] + 1) {
94 0         0 $off += 86400;
95             } elsif ($l[7] == $g[7] - 1) {
96 0         0 $off -= 86400;
97             } elsif ($l[7] < $g[7]) {
98             # crossed over a year boundary!
99             # localtime is beginning of year, gmt is end
100             # therefore local is ahead
101 0         0 $off += 86400;
102             } else {
103 0         0 $off -= 86400;
104             }
105              
106 4         15 return $off;
107             }
108              
109             # constants
110              
111             my (%dstZone, %zoneOff, %dstZoneOff, %Zone);
112              
113             CONFIG: {
114             my @dstZone = (
115             # "ndt" => -2*3600-1800, # Newfoundland Daylight
116             "brst" => -2*3600, # Brazil Summer Time (East Daylight)
117             "adt" => -3*3600, # Atlantic Daylight
118             "edt" => -4*3600, # Eastern Daylight
119             "cdt" => -5*3600, # Central Daylight
120             "mdt" => -6*3600, # Mountain Daylight
121             "pdt" => -7*3600, # Pacific Daylight
122             "akdt" => -8*3600, # Alaska Daylight
123             "ydt" => -8*3600, # Yukon Daylight
124             "hdt" => -9*3600, # Hawaii Daylight
125             "bst" => +1*3600, # British Summer
126             "mest" => +2*3600, # Middle European Summer
127             "metdst" => +2*3600, # Middle European DST
128             "sst" => +2*3600, # Swedish Summer
129             "fst" => +2*3600, # French Summer
130             "cest" => +2*3600, # Central European Daylight
131             "eest" => +3*3600, # Eastern European Summer
132             "msd" => +4*3600, # Moscow Daylight
133             "wadt" => +8*3600, # West Australian Daylight
134             "kdt" => +10*3600, # Korean Daylight
135             # "cadt" => +10*3600+1800, # Central Australian Daylight
136             "aedt" => +11*3600, # Eastern Australian Daylight
137             "eadt" => +11*3600, # Eastern Australian Daylight
138             "nzd" => +13*3600, # New Zealand Daylight
139             "nzdt" => +13*3600, # New Zealand Daylight
140             );
141              
142             my @Zone = (
143             "gmt" => 0, # Greenwich Mean
144             "ut" => 0, # Universal (Coordinated)
145             "utc" => 0,
146             "wet" => 0, # Western European
147             "wat" => -1*3600, # West Africa
148             "at" => -2*3600, # Azores
149             "fnt" => -2*3600, # Brazil Time (Extreme East - Fernando Noronha)
150             "brt" => -3*3600, # Brazil Time (East Standard - Brasilia)
151             # For completeness. BST is also British Summer, and GST is also Guam Standard.
152             # "bst" => -3*3600, # Brazil Standard
153             # "gst" => -3*3600, # Greenland Standard
154             # "nft" => -3*3600-1800,# Newfoundland
155             # "nst" => -3*3600-1800,# Newfoundland Standard
156             "mnt" => -4*3600, # Brazil Time (West Standard - Manaus)
157             "ewt" => -4*3600, # U.S. Eastern War Time
158             "ast" => -4*3600, # Atlantic Standard
159             "est" => -5*3600, # Eastern Standard
160             "act" => -5*3600, # Brazil Time (Extreme West - Acre)
161             "cst" => -6*3600, # Central Standard
162             "mst" => -7*3600, # Mountain Standard
163             "pst" => -8*3600, # Pacific Standard
164             "akst" => -9*3600, # Alaska Standard
165             "yst" => -9*3600, # Yukon Standard
166             "hst" => -10*3600, # Hawaii Standard
167             "cat" => -10*3600, # Central Alaska
168             "ahst" => -10*3600, # Alaska-Hawaii Standard
169             "nt" => -11*3600, # Nome
170             "idlw" => -12*3600, # International Date Line West
171             "cet" => +1*3600, # Central European
172             "mez" => +1*3600, # Central European (German)
173             "ect" => +1*3600, # Central European (French)
174             "met" => +1*3600, # Middle European
175             "mewt" => +1*3600, # Middle European Winter
176             "swt" => +1*3600, # Swedish Winter
177             "set" => +1*3600, # Seychelles
178             "fwt" => +1*3600, # French Winter
179             "eet" => +2*3600, # Eastern Europe, USSR Zone 1
180             "ukr" => +2*3600, # Ukraine
181             "bt" => +3*3600, # Baghdad, USSR Zone 2
182             "msk" => +3*3600, # Moscow
183             # "it" => +3*3600+1800,# Iran
184             "zp4" => +4*3600, # USSR Zone 3
185             "zp5" => +5*3600, # USSR Zone 4
186             "ist" => +5*3600+1800,# Indian Standard
187             "zp6" => +6*3600, # USSR Zone 5
188             # For completeness. NST is also Newfoundland Stanard, and SST is also Swedish Summer.
189             # "nst" => +6*3600+1800,# North Sumatra
190             # "sst" => +7*3600, # South Sumatra, USSR Zone 6
191             # "jt" => +7*3600+1800,# Java (3pm in Cronusland!)
192             "wst" => +8*3600, # West Australian Standard
193             "hkt" => +8*3600, # Hong Kong
194             "cct" => +8*3600, # China Coast, USSR Zone 7
195             "jst" => +9*3600, # Japan Standard, USSR Zone 8
196             "kst" => +9*3600, # Korean Standard
197             # "cast" => +9*3600+1800,# Central Australian Standard
198             "aest" => +10*3600, # Eastern Australian Standard
199             "east" => +10*3600, # Eastern Australian Standard
200             "gst" => +10*3600, # Guam Standard, USSR Zone 9
201             "nzt" => +12*3600, # New Zealand
202             "nzst" => +12*3600, # New Zealand Standard
203             "idle" => +12*3600, # International Date Line East
204             );
205              
206             %Zone = @Zone;
207             %dstZone = @dstZone;
208             %zoneOff = reverse(@Zone);
209             %dstZoneOff = reverse(@dstZone);
210              
211             }
212              
213             sub tz_offset (;$$)
214             {
215 814     814 0 352993 my ($zone, $time) = @_;
216              
217 814 50       1966 return &tz_local_offset($time) unless($zone);
218              
219 814 100       1708 $time = time() unless $time;
220 814         20606 my(@l) = localtime($time);
221 814         1920 my $dst = $l[8];
222              
223 814         1755 $zone = lc $zone;
224              
225 814 100 33     5266 if($zone =~ /^(([\-\+])\d\d?)(\d\d)$/) {
    100 66        
    100          
226 9         37 my $v = $2 . $3;
227 9         84 return $1 * 3600 + $v * 60;
228             } elsif (exists $dstZone{$zone} && ($dst || !exists $Zone{$zone})) {
229 9         145 return $dstZone{$zone};
230             } elsif(exists $Zone{$zone}) {
231 794         11893 return $Zone{$zone};
232             }
233 2         22 undef;
234             }
235              
236             sub tz_name (;$$)
237             {
238 2     2 0 4 my ($off, $dst) = @_;
239              
240 2 50       7 $off = tz_offset()
241             unless(defined $off);
242              
243 2 50       39 $dst = (localtime(time))[8]
244             unless(defined $dst);
245              
246 2 50 33     14 if (exists $dstZoneOff{$off} && ($dst || !exists $zoneOff{$off})) {
    50 66        
247 0         0 return $dstZoneOff{$off};
248             } elsif (exists $zoneOff{$off}) {
249 2         13 return $zoneOff{$off};
250             }
251 0           sprintf("%+05d", int($off / 60) * 100 + $off % 60);
252             }
253              
254             1;
255              
256             __END__