Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / DateTime / TimeZone / OlsonDB / Zone.pm
CommitLineData
3fea05b9 1package DateTime::TimeZone::OlsonDB::Zone;
2
3use strict;
4use warnings;
5
6use DateTime::TimeZone;
7use DateTime::TimeZone::OlsonDB;
8use DateTime::TimeZone::OlsonDB::Change;
9use DateTime::TimeZone::OlsonDB::Observance;
10
11use List::Util qw( first );
12use Params::Validate qw( validate SCALAR ARRAYREF );
13
14sub new
15{
16 my $class = shift;
17 my %p = validate( @_, { name => { type => SCALAR },
18 observances => { type => ARRAYREF },
19 olson_db => 1,
20 }
21 );
22
23 my $self = { name => $p{name},
24 observances => $p{observances},
25 changes => [],
26 infinite_rules => {},
27 };
28
29 return bless $self, $class;
30}
31
32sub name { $_[0]->{name} }
33
34sub expand_observances
35{
36 my $self = shift;
37 my $odb = shift;
38 my $max_year = shift;
39
40 my $prev_until;
41 for ( my $x = 0; $x < @{ $self->{observances} }; $x++ )
42 {
43 my %p = %{ $self->{observances}[$x] };
44
45 my $rules_name = delete $p{rules};
46
47 my $last_offset_from_std =
48 $self->last_change ? $self->last_change->offset_from_std : 0;
49 my $last_offset_from_utc =
50 $self->last_change ? $self->last_change->offset_from_utc : 0;
51
52 my $obs =
53 DateTime::TimeZone::OlsonDB::Observance->new
54 ( %p,
55 utc_start_datetime => $prev_until,
56 rules => [ $odb->rules_by_name($rules_name) ],
57 last_offset_from_utc => $last_offset_from_utc,
58 last_offset_from_std => $last_offset_from_std,
59 );
60
61 my $rule = $obs->first_rule;
62 my $letter = $rule ? $rule->letter : '';
63
64 my $change =
65 DateTime::TimeZone::OlsonDB::Change->new
66 ( type => 'observance',
67 utc_start_datetime => $obs->utc_start_datetime,
68 local_start_datetime => $obs->local_start_datetime,
69 short_name => sprintf( $obs->format, $letter ),
70 observance => $obs,
71 $rule ? ( rule => $rule ) : (),
72 );
73
74 if ($DateTime::TimeZone::OlsonDB::DEBUG)
75 {
76 print "Adding observance change ...\n";
77
78 $change->_debug_output;
79 }
80
81 $self->add_change($change);
82
83 if ( $obs->rules )
84 {
85 $obs->expand_from_rules( $self, $max_year );
86 }
87
88 $prev_until =
89 $obs->until( $self->last_change ? $self->last_change->offset_from_std : 0 );
90
91 # last observance
92 if ( $x == $#{ $self->{observances} } )
93 {
94 foreach my $rule ( $obs->rules )
95 {
96 if ( $rule->is_infinite )
97 {
98 $self->add_infinite_rule($rule);
99 }
100 }
101 }
102 }
103}
104
105sub add_change
106{
107 my $self = shift;
108 my $change = shift;
109
110 if ( defined $change->utc_start_datetime )
111 {
112 if ( @{ $self->{changes} }
113 && $self->{changes}[-1]->utc_start_datetime
114 && $self->{changes}[-1]->utc_start_datetime == $change->utc_start_datetime
115 )
116 {
117 if ( $self->{changes}[-1]->rule && $change->observance )
118 {
119 print " Ignoring previous rule change, that starts the same time as current observance change\n\n"
120 if $DateTime::TimeZone::OlsonDB::DEBUG;
121
122 $self->{changes}[-1] = $change;
123
124 return;
125 }
126
127 die "Cannot add two different changes that have the same UTC start datetime!\n";
128 }
129
130 my $last_change = $self->last_change;
131
132 if ( $last_change->short_name eq $change->short_name
133 && $last_change->total_offset == $change->total_offset
134 && $last_change->is_dst == $change->is_dst
135 && $last_change->observance eq $change->observance
136 )
137 {
138 my $last_rule = $last_change->rule || '';
139 my $new_rule = $change->rule || '';
140
141 if ( $last_rule eq $new_rule )
142 {
143 print "Skipping identical change\n" if $DateTime::TimeZone::OlsonDB::DEBUG;
144
145 return;
146 }
147 }
148
149 push @{ $self->{changes} }, $change;
150 }
151 else
152 {
153 if ( $self->{earliest} )
154 {
155 die "There can only be one earliest time zone change!";
156 }
157 else
158 {
159 $self->{earliest} = $change;
160 }
161 }
162}
163
164sub add_infinite_rule
165{
166 $_[0]->{infinite_rules}{ $_[1] } = $_[1];
167}
168
169sub last_change { return unless @{ $_[0]->{changes} } || $_[0]->{earliest};
170 return ( @{ $_[0]->{changes} } ?
171 $_[0]->{changes}[-1] :
172 $_[0]->{earliest} ); }
173
174sub sorted_changes { ( ( defined $_[0]->{earliest} ? $_[0]->{earliest} : () ),
175 sort { $a->utc_start_datetime <=> $b->utc_start_datetime }
176 @{ $_[0]->{changes} } ) }
177
178sub infinite_rules { values %{ $_[0]->{infinite_rules} } }
179
1801;