File Coverage

blib/lib/Geography/Country/TZ/Zone.pm
Criterion Covered Total %
statement 6 96 6.2
branch 0 58 0.0
condition 0 21 0.0
subroutine 2 9 22.2
pod 0 7 0.0
total 8 191 4.1


line stmt bran cond sub pod time code
1             package Geography::Country::TZ::Zone;
2 3     3   18 use strict 'vars';
  3         5  
  3         132  
3 3     3   18 use vars qw(%loc %rule %map %map2);
  3         5  
  3         6578  
4              
5             my $offset = 0;
6             while () {
7             chomp;
8             s/#.*$//;
9             next unless (/\S/);
10             my @tokens = split(/\s+/);
11             if ($tokens[0] eq 'Zone') {
12             $loc{$tokens[1]} = $offset;
13             }
14             if ($tokens[0] eq 'Link') {
15             $loc{$tokens[2]} = $loc{$tokens[1]};
16             }
17             if ($tokens[0] eq 'Rule') {
18             $rule{$tokens[1]} ||= $offset;
19             }
20             $offset = tell(DATA);
21             }
22              
23             sub getblock {
24 0     0 0   my $zone = shift;
25 0           my $offset = $loc{$zone};
26 0 0         return undef unless (defined($offset));
27 0           seek(DATA, $offset, 0);
28 0           my @ary;
29 0           while () {
30 0           chop;
31 0           s/#.*$//;
32 0 0         next unless (/\S/);
33 0           my @tokens = split(/\s+/, $_);
34 0 0         last if ($tokens[0] eq 'Link');
35 0 0         last if ($tokens[0] eq 'Rule');
36 0 0         if ($tokens[0] eq 'Zone') {
37 0 0         last if @ary;
38 0           shift @tokens;
39 0           shift @tokens;
40             }
41 0   0       while (@tokens && !$tokens[0]) {
42 0           shift @tokens;
43             }
44 0 0         next unless (@tokens);
45 0           @tokens = (@tokens[0 .. 3], join(" ", @tokens[4 .. $#tokens]));
46 0           push(@ary, \@tokens);
47             }
48 0           @ary;
49             }
50             sub conv {
51 0     0 0   my $a = shift;
52 0           $a =~ s/^(-?)//;
53 0           my $neg = $1;
54 0           my @tokens = (split(/:/, $a), 0, 0);
55 0           $neg . ($tokens[0] * 60 + $tokens[1]) * 60 + $tokens[2];
56             }
57              
58             sub getoffset {
59 0     0 0   my $zone = shift;
60 0           my @ary = &getblock($zone);
61 0 0         return undef unless (@ary);
62 0           my @t = localtime;
63 0           conv($ary[-1]->[0]) + &getsave($ary[-1]->[1],
64             $t[3], $t[4] + 1, $t[5] + 1900);
65             }
66              
67             @map{qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)} = (1 .. 12);
68              
69             sub getpastoffset {
70 0     0 0   my ($zone, $d, $m, $y) = @_;
71 0           my @ary = &getblock($zone);
72 0           my $def;
73 0 0         return undef unless (@ary);
74 0           my $policy;
75 0           foreach (@ary) {
76 0           $def = $_->[0];
77 0           $policy = $_->[1];
78 0           my $from = $_->[3];
79 0 0         next unless ($from);
80 0           my @tokens = split(/\s+/, $from);
81 0 0         last if ($tokens[0] > $y);
82 0 0 0       last if ($#tokens && $map{$tokens[1]} > $m);
83 0 0 0       last if ($#tokens > 1 && $tokens[2] > $d);
84             }
85 0           &conv($def) + &getsave($policy, $d, $m, $y);
86             }
87              
88             sub getsave {
89 0     0 0   my ($cn, $d, $m, $y, $t) = @_;
90 0 0         return &conv($cn) if ($cn =~ /^[0-9:]+$/);
91 0           my $offset = $rule{$cn};
92 0 0         return 0 unless ($offset);
93 0           seek(DATA, $offset, 0);
94 0           my $def = 0;
95 0           my $mm;
96 0 0         $t = &conv($t) if ($t);
97 0           while () {
98 0           chop;
99 0           my @tokens = split(/\s+/);
100 0 0 0       last if ($tokens[0] ne 'Rule' || $tokens[1] ne $cn);
101 0 0         last if ($tokens[2] > $y);
102 0 0 0       next if ($tokens[3] =~ /^\d+$/ && $tokens[3]);
103 0 0 0       next if ($tokens[3] eq 'only' && $y != $tokens[2]);
104 0 0         last if (($mm = $map{$tokens[5]}) > $m);
105 0 0 0       next if ($m == $mm && &find($tokens[6], $m, $y) > $d);
106 0           $def = $tokens[8];
107             }
108 0           &conv($def);
109             }
110              
111             @map2{qw(Sun Mon Tue Wed Thu Fri Sat)} = (1 .. 7);
112              
113             sub find {
114 0     0 0   my ($exp, $m, $y) = @_;
115 0 0         return $exp if ($exp =~ /^\d+$/);
116 0           my $d;
117 0 0         if ($exp =~ s/^last//) {
118 0           my $l = $map2{$exp};
119 0           my $t = maketime(1, $m, $y);
120 0           for (;;) {
121 0           my @t = gmtime($t);
122 0 0         last if ($t[4] + 1 != $m);
123 0 0         $d = $t[3] if ($t[6] + 1 == $l);
124 0           $t += 3600 * 24;
125             }
126 0           return $d;
127             }
128             # $exp = "$exp>=1" if ($map2{$exp});
129 0 0         if ($exp =~ s/([<>])\=(\d+)$//) {
130 0           my $val = $2;
131 0 0         my $neg = ($1 eq "<") ? -1 : 1;
132 0           my $l = $map2{$exp};
133 0           my $t = maketime($val, $m, $y);
134 0           for (;;) {
135 0           my @t = gmtime($t);
136 0 0         return $t[3] if ($t[6] + 1 == $l);
137 0           $t += 3600 * 24 * $neg;
138             }
139             }
140 0           die "Unparsable $exp";
141             }
142              
143             sub maketime {
144 0     0 0   require Time::Local;
145 0           Time::Local::timegm(0, 0, 0, $_[0], $_[1] - 1, $_[2] - 1900);
146             }
147              
148             1;
149             __DATA__