← Index
NYTProf Performance Profile   « line view »
For -e
  Run on Thu Jun 30 16:16:00 2016
Reported on Thu Jun 30 16:16:08 2016

Filename/home/s1/perl5/perlbrew/perls/perl-5.22.1/lib/site_perl/5.22.1/DateTime/TimeZone.pm
StatementsExecuted 34056 statements in 81.7ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
30023233.1ms57.6msDateTime::TimeZone::::newDateTime::TimeZone::new
13000117.14ms7.14msDateTime::TimeZone::::is_floatingDateTime::TimeZone::is_floating
1112.59ms2.71msDateTime::TimeZone::::BEGIN@8DateTime::TimeZone::BEGIN@8
3002111.59ms1.59msDateTime::TimeZone::::CORE:matchDateTime::TimeZone::CORE:match (opcode)
1111.28ms5.63msDateTime::TimeZone::::BEGIN@10DateTime::TimeZone::BEGIN@10
1111.12ms1.24msDateTime::TimeZone::::BEGIN@12DateTime::TimeZone::BEGIN@12
111520µs3.42msDateTime::TimeZone::::BEGIN@9DateTime::TimeZone::BEGIN@9
11122µs22µsDateTime::TimeZone::::BEGIN@3DateTime::TimeZone::BEGIN@3
11122µs95µsDateTime::TimeZone::::BEGIN@15DateTime::TimeZone::BEGIN@15
11112µs60µsDateTime::TimeZone::::BEGIN@28DateTime::TimeZone::BEGIN@28
11111µs11µsDateTime::TimeZone::::BEGIN@11DateTime::TimeZone::BEGIN@11
11111µs14µsDateTime::TimeZone::::BEGIN@5DateTime::TimeZone::BEGIN@5
11111µs53µsDateTime::TimeZone::::BEGIN@16DateTime::TimeZone::BEGIN@16
11111µs67µsDateTime::TimeZone::::BEGIN@18DateTime::TimeZone::BEGIN@18
11110µs10µsDateTime::TimeZone::::BEGIN@13DateTime::TimeZone::BEGIN@13
11110µs55µsDateTime::TimeZone::::BEGIN@19DateTime::TimeZone::BEGIN@19
11110µs72µsDateTime::TimeZone::::BEGIN@27DateTime::TimeZone::BEGIN@27
11110µs28µsDateTime::TimeZone::::BEGIN@14DateTime::TimeZone::BEGIN@14
1119µs55µsDateTime::TimeZone::::BEGIN@22DateTime::TimeZone::BEGIN@22
1119µs16µsDateTime::TimeZone::::BEGIN@6DateTime::TimeZone::BEGIN@6
1119µs50µsDateTime::TimeZone::::BEGIN@23DateTime::TimeZone::BEGIN@23
1119µs50µsDateTime::TimeZone::::BEGIN@24DateTime::TimeZone::BEGIN@24
1118µs47µsDateTime::TimeZone::::BEGIN@25DateTime::TimeZone::BEGIN@25
1118µs49µsDateTime::TimeZone::::BEGIN@26DateTime::TimeZone::BEGIN@26
0000s0sDateTime::TimeZone::::STORABLE_freezeDateTime::TimeZone::STORABLE_freeze
0000s0sDateTime::TimeZone::::STORABLE_thawDateTime::TimeZone::STORABLE_thaw
0000s0sDateTime::TimeZone::::__ANON__[:407]DateTime::TimeZone::__ANON__[:407]
0000s0sDateTime::TimeZone::::__ANON__[:446]DateTime::TimeZone::__ANON__[:446]
0000s0sDateTime::TimeZone::::__ANON__[:481]DateTime::TimeZone::__ANON__[:481]
0000s0sDateTime::TimeZone::::__ANON__[:82]DateTime::TimeZone::__ANON__[:82]
0000s0sDateTime::TimeZone::::__ANON__[:85]DateTime::TimeZone::__ANON__[:85]
0000s0sDateTime::TimeZone::::_generate_next_spanDateTime::TimeZone::_generate_next_span
0000s0sDateTime::TimeZone::::_generate_spans_until_matchDateTime::TimeZone::_generate_spans_until_match
0000s0sDateTime::TimeZone::::_initDateTime::TimeZone::_init
0000s0sDateTime::TimeZone::::_keys_for_typeDateTime::TimeZone::_keys_for_type
0000s0sDateTime::TimeZone::::_span_as_arrayDateTime::TimeZone::_span_as_array
0000s0sDateTime::TimeZone::::_span_for_datetimeDateTime::TimeZone::_span_for_datetime
0000s0sDateTime::TimeZone::::_spans_binary_searchDateTime::TimeZone::_spans_binary_search
0000s0sDateTime::TimeZone::::all_namesDateTime::TimeZone::all_names
0000s0sDateTime::TimeZone::::categoriesDateTime::TimeZone::categories
0000s0sDateTime::TimeZone::::categoryDateTime::TimeZone::category
0000s0sDateTime::TimeZone::::countriesDateTime::TimeZone::countries
0000s0sDateTime::TimeZone::::has_dst_changesDateTime::TimeZone::has_dst_changes
0000s0sDateTime::TimeZone::::is_dst_for_datetimeDateTime::TimeZone::is_dst_for_datetime
0000s0sDateTime::TimeZone::::is_olsonDateTime::TimeZone::is_olson
0000s0sDateTime::TimeZone::::is_utcDateTime::TimeZone::is_utc
0000s0sDateTime::TimeZone::::is_valid_nameDateTime::TimeZone::is_valid_name
0000s0sDateTime::TimeZone::::linksDateTime::TimeZone::links
0000s0sDateTime::TimeZone::::max_spanDateTime::TimeZone::max_span
0000s0sDateTime::TimeZone::::nameDateTime::TimeZone::name
0000s0sDateTime::TimeZone::::names_in_categoryDateTime::TimeZone::names_in_category
0000s0sDateTime::TimeZone::::names_in_countryDateTime::TimeZone::names_in_country
0000s0sDateTime::TimeZone::::offset_as_secondsDateTime::TimeZone::offset_as_seconds
0000s0sDateTime::TimeZone::::offset_as_stringDateTime::TimeZone::offset_as_string
0000s0sDateTime::TimeZone::::offset_for_datetimeDateTime::TimeZone::offset_for_datetime
0000s0sDateTime::TimeZone::::offset_for_local_datetimeDateTime::TimeZone::offset_for_local_datetime
0000s0sDateTime::TimeZone::::short_name_for_datetimeDateTime::TimeZone::short_name_for_datetime
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package DateTime::TimeZone;
211µs$DateTime::TimeZone::VERSION = '1.98';
3254µs122µs
# spent 22µs within DateTime::TimeZone::BEGIN@3 which was called: # once (22µs+0s) by DateTime::BEGIN@15 at line 3
use 5.006;
# spent 22µs making 1 call to DateTime::TimeZone::BEGIN@3
4
5230µs217µs
# spent 14µs (11+3) within DateTime::TimeZone::BEGIN@5 which was called: # once (11µs+3µs) by DateTime::BEGIN@15 at line 5
use strict;
# spent 14µs making 1 call to DateTime::TimeZone::BEGIN@5 # spent 3µs making 1 call to strict::import
6229µs222µs
# spent 16µs (9+6) within DateTime::TimeZone::BEGIN@6 which was called: # once (9µs+6µs) by DateTime::BEGIN@15 at line 6
use warnings;
# spent 16µs making 1 call to DateTime::TimeZone::BEGIN@6 # spent 6µs making 1 call to warnings::import
7
82202µs12.71ms
# spent 2.71ms (2.59+113µs) within DateTime::TimeZone::BEGIN@8 which was called: # once (2.59ms+113µs) by DateTime::BEGIN@15 at line 8
use DateTime::TimeZone::Catalog;
# spent 2.71ms making 1 call to DateTime::TimeZone::BEGIN@8
92290µs13.42ms
# spent 3.42ms (520µs+2.90) within DateTime::TimeZone::BEGIN@9 which was called: # once (520µs+2.90ms) by DateTime::BEGIN@15 at line 9
use DateTime::TimeZone::Floating;
# spent 3.42ms making 1 call to DateTime::TimeZone::BEGIN@9
102300µs15.63ms
# spent 5.63ms (1.28+4.34) within DateTime::TimeZone::BEGIN@10 which was called: # once (1.28ms+4.34ms) by DateTime::BEGIN@15 at line 10
use DateTime::TimeZone::Local;
# spent 5.63ms making 1 call to DateTime::TimeZone::BEGIN@10
11237µs111µs
# spent 11µs within DateTime::TimeZone::BEGIN@11 which was called: # once (11µs+0s) by DateTime::BEGIN@15 at line 11
use DateTime::TimeZone::OffsetOnly;
# spent 11µs making 1 call to DateTime::TimeZone::BEGIN@11
122275µs11.24ms
# spent 1.24ms (1.12+114µs) within DateTime::TimeZone::BEGIN@12 which was called: # once (1.12ms+114µs) by DateTime::BEGIN@15 at line 12
use DateTime::TimeZone::OlsonDB::Change;
# spent 1.24ms making 1 call to DateTime::TimeZone::BEGIN@12
13238µs110µs
# spent 10µs within DateTime::TimeZone::BEGIN@13 which was called: # once (10µs+0s) by DateTime::BEGIN@15 at line 13
use DateTime::TimeZone::UTC;
# spent 10µs making 1 call to DateTime::TimeZone::BEGIN@13
14244µs246µs
# spent 28µs (10+18) within DateTime::TimeZone::BEGIN@14 which was called: # once (10µs+18µs) by DateTime::BEGIN@15 at line 14
use Module::Runtime qw( require_module );
# spent 28µs making 1 call to DateTime::TimeZone::BEGIN@14 # spent 18µs making 1 call to Module::Runtime::import
15364µs3168µs
# spent 95µs (22+73) within DateTime::TimeZone::BEGIN@15 which was called: # once (22µs+73µs) by DateTime::BEGIN@15 at line 15
use Params::Validate 0.72 qw( validate validate_pos SCALAR ARRAYREF BOOLEAN );
# spent 95µs making 1 call to DateTime::TimeZone::BEGIN@15 # spent 59µs making 1 call to Exporter::import # spent 14µs making 1 call to UNIVERSAL::VERSION
16257µs295µs
# spent 53µs (11+42) within DateTime::TimeZone::BEGIN@16 which was called: # once (11µs+42µs) by DateTime::BEGIN@15 at line 16
use Try::Tiny;
# spent 53µs making 1 call to DateTime::TimeZone::BEGIN@16 # spent 42µs making 1 call to Exporter::import
17
18248µs2124µs
# spent 67µs (11+57) within DateTime::TimeZone::BEGIN@18 which was called: # once (11µs+57µs) by DateTime::BEGIN@15 at line 18
use constant INFINITY => 100**1000;
# spent 67µs making 1 call to DateTime::TimeZone::BEGIN@18 # spent 57µs making 1 call to constant::import
19238µs2100µs
# spent 55µs (10+45) within DateTime::TimeZone::BEGIN@19 which was called: # once (10µs+45µs) by DateTime::BEGIN@15 at line 19
use constant NEG_INFINITY => -1 * ( 100**1000 );
# spent 55µs making 1 call to DateTime::TimeZone::BEGIN@19 # spent 45µs making 1 call to constant::import
20
21# the offsets for each span element
22236µs2101µs
# spent 55µs (9+46) within DateTime::TimeZone::BEGIN@22 which was called: # once (9µs+46µs) by DateTime::BEGIN@15 at line 22
use constant UTC_START => 0;
# spent 55µs making 1 call to DateTime::TimeZone::BEGIN@22 # spent 46µs making 1 call to constant::import
23234µs291µs
# spent 50µs (9+41) within DateTime::TimeZone::BEGIN@23 which was called: # once (9µs+41µs) by DateTime::BEGIN@15 at line 23
use constant UTC_END => 1;
# spent 50µs making 1 call to DateTime::TimeZone::BEGIN@23 # spent 41µs making 1 call to constant::import
24233µs291µs
# spent 50µs (9+41) within DateTime::TimeZone::BEGIN@24 which was called: # once (9µs+41µs) by DateTime::BEGIN@15 at line 24
use constant LOCAL_START => 2;
# spent 50µs making 1 call to DateTime::TimeZone::BEGIN@24 # spent 41µs making 1 call to constant::import
25233µs286µs
# spent 47µs (8+39) within DateTime::TimeZone::BEGIN@25 which was called: # once (8µs+39µs) by DateTime::BEGIN@15 at line 25
use constant LOCAL_END => 3;
# spent 47µs making 1 call to DateTime::TimeZone::BEGIN@25 # spent 39µs making 1 call to constant::import
26252µs289µs
# spent 49µs (8+40) within DateTime::TimeZone::BEGIN@26 which was called: # once (8µs+40µs) by DateTime::BEGIN@15 at line 26
use constant OFFSET => 4;
# spent 49µs making 1 call to DateTime::TimeZone::BEGIN@26 # spent 40µs making 1 call to constant::import
27240µs2134µs
# spent 72µs (10+62) within DateTime::TimeZone::BEGIN@27 which was called: # once (10µs+62µs) by DateTime::BEGIN@15 at line 27
use constant IS_DST => 5;
# spent 72µs making 1 call to DateTime::TimeZone::BEGIN@27 # spent 62µs making 1 call to constant::import
2823.78ms2108µs
# spent 60µs (12+48) within DateTime::TimeZone::BEGIN@28 which was called: # once (12µs+48µs) by DateTime::BEGIN@15 at line 28
use constant SHORT_NAME => 6;
# spent 60µs making 1 call to DateTime::TimeZone::BEGIN@28 # spent 48µs making 1 call to constant::import
29
30123µsmy %SpecialName = map { $_ => 1 }
31 qw( EST MST HST CET EET MET WET EST5EDT CST6CDT MST7MDT PST8PDT );
32
33
# spent 57.6ms (33.1+24.5) within DateTime::TimeZone::new which was called 3002 times, avg 19µs/call: # 3000 times (33.0ms+24.5ms) by DateTime::_new at line 235 of DateTime.pm, avg 19µs/call # once (46µs+52µs) by DateTime::Format::Alami::parse_datetime at line 78 of DateTime/Infinite.pm # once (23µs+19µs) by DateTime::Format::Alami::parse_datetime at line 103 of DateTime/Infinite.pm
sub new {
343002740µs my $class = shift;
35300231.7ms300217.7ms my %p = validate(
# spent 17.7ms making 3002 calls to Params::Validate::XS::validate, avg 6µs/call
36 @_,
37 { name => { type => SCALAR } },
38 );
39
4030022.75ms if ( exists $DateTime::TimeZone::Catalog::LINKS{ $p{name} } ) {
41 $p{name} = $DateTime::TimeZone::Catalog::LINKS{ $p{name} };
42 }
43 elsif ( exists $DateTime::TimeZone::Catalog::LINKS{ uc $p{name} } ) {
44 $p{name} = $DateTime::TimeZone::Catalog::LINKS{ uc $p{name} };
45 }
46
4730026.74ms30021.59ms unless ( $p{name} =~ m{/}
# spent 1.59ms making 3002 calls to DateTime::TimeZone::CORE:match, avg 528ns/call
48 || $SpecialName{ $p{name} } ) {
493002802µs222µs if ( $p{name} eq 'floating' ) {
# spent 22µs making 2 calls to Class::Singleton::instance, avg 11µs/call
50 return DateTime::TimeZone::Floating->instance;
51 }
52
533000317µs if ( $p{name} eq 'local' ) {
54 return DateTime::TimeZone::Local->TimeZone();
55 }
56
57300013.0ms30005.22ms if ( $p{name} eq 'UTC' || $p{name} eq 'Z' ) {
# spent 5.22ms making 3000 calls to Class::Singleton::instance, avg 2µs/call
58 return DateTime::TimeZone::UTC->instance;
59 }
60
61 return DateTime::TimeZone::OffsetOnly->new( offset => $p{name} );
62 }
63
64 my $subclass = $p{name};
65 $subclass =~ s{/}{::}g;
66 $subclass =~ s/-(\d)/_Minus$1/;
67 $subclass =~ s/\+/_Plus/;
68 $subclass =~ s/-/_/g;
69
70 my $real_class = "DateTime::TimeZone::$subclass";
71
72 die "The timezone '$p{name}' is an invalid name.\n"
73 unless $real_class =~ /^\w+(::\w+)*$/;
74
75 unless ( $real_class->can('instance') ) {
76 ($real_class) = $real_class =~ m{\A([a-zA-Z0-9_]+(?:::[a-zA-Z0-9_]+)*)\z};
77
78 my $e;
79 try {
80 local $SIG{__DIE__};
81 require_module($real_class);
82 }
83 catch {
84 $e = $_;
85 };
86
87 if ($e) {
88 my $regex = join '.', split /::/, $real_class;
89 $regex .= '\\.pm';
90
91 if ( $e =~ /^Can't locate $regex/i ) {
92 die
93 "The timezone '$p{name}' could not be loaded, or is an invalid name.\n";
94 }
95 else {
96 die $e;
97 }
98 }
99 }
100
101 my $zone = $real_class->instance( name => $p{name}, is_olson => 1 );
102
103 if ( $zone->is_olson() ) {
104 my $object_version
105 = $zone->can('olson_version')
106 ? $zone->olson_version()
107 : 'unknown';
108 my $catalog_version = DateTime::TimeZone::Catalog->OlsonVersion();
109
110 if ( $object_version ne $catalog_version ) {
111 warn
112 "Loaded $real_class, which is from a different version ($object_version) of the Olson database than this installation of DateTime::TimeZone ($catalog_version).\n";
113 }
114 }
115
116 return $zone;
117}
118
119sub _init {
120 my $class = shift;
121 my %p = validate(
122 @_, {
123 name => { type => SCALAR },
124 spans => { type => ARRAYREF },
125 is_olson => { type => BOOLEAN, default => 0 },
126 },
127 );
128
129 my $self = bless {
130 name => $p{name},
131 spans => $p{spans},
132 is_olson => $p{is_olson},
133 }, $class;
134
135 foreach my $k (qw( last_offset last_observance rules max_year )) {
136 my $m = "_$k";
137 $self->{$k} = $self->$m() if $self->can($m);
138 }
139
140 return $self;
141}
142
143sub is_olson { $_[0]->{is_olson} }
144
145sub is_dst_for_datetime {
146 my $self = shift;
147
148 my $span = $self->_span_for_datetime( 'utc', $_[0] );
149
150 return $span->[IS_DST];
151}
152
153sub offset_for_datetime {
154 my $self = shift;
155
156 my $span = $self->_span_for_datetime( 'utc', $_[0] );
157
158 return $span->[OFFSET];
159}
160
161sub offset_for_local_datetime {
162 my $self = shift;
163
164 my $span = $self->_span_for_datetime( 'local', $_[0] );
165
166 return $span->[OFFSET];
167}
168
169sub short_name_for_datetime {
170 my $self = shift;
171
172 my $span = $self->_span_for_datetime( 'utc', $_[0] );
173
174 return $span->[SHORT_NAME];
175}
176
177sub _span_for_datetime {
178 my $self = shift;
179 my $type = shift;
180 my $dt = shift;
181
182 my $method = $type . '_rd_as_seconds';
183
184 my $end = $type eq 'utc' ? UTC_END : LOCAL_END;
185
186 my $span;
187 my $seconds = $dt->$method();
188 if ( $seconds < $self->max_span->[$end] ) {
189 $span = $self->_spans_binary_search( $type, $seconds );
190 }
191 else {
192 my $until_year = $dt->utc_year + 1;
193 $span = $self->_generate_spans_until_match( $until_year, $seconds,
194 $type );
195 }
196
197 # This means someone gave a local time that doesn't exist
198 # (like during a transition into savings time)
199 unless ( defined $span ) {
200 my $err = 'Invalid local time for date';
201 $err .= ' ' . $dt->iso8601 if $type eq 'utc';
202 $err .= ' in time zone: ' . $self->name;
203 $err .= "\n";
204
205 die $err;
206 }
207
208 return $span;
209}
210
211sub _spans_binary_search {
212 my $self = shift;
213 my ( $type, $seconds ) = @_;
214
215 my ( $start, $end ) = _keys_for_type($type);
216
217 my $min = 0;
218 my $max = scalar @{ $self->{spans} } + 1;
219 my $i = int( $max / 2 );
220
221 # special case for when there are only 2 spans
222 $i++ if $max % 2 && $max != 3;
223
224 $i = 0 if @{ $self->{spans} } == 1;
225
226 while (1) {
227 my $current = $self->{spans}[$i];
228
229 if ( $seconds < $current->[$start] ) {
230 $max = $i;
231 my $c = int( ( $i - $min ) / 2 );
232 $c ||= 1;
233
234 $i -= $c;
235
236 return if $i < $min;
237 }
238 elsif ( $seconds >= $current->[$end] ) {
239 $min = $i;
240 my $c = int( ( $max - $i ) / 2 );
241 $c ||= 1;
242
243 $i += $c;
244
245 return if $i >= $max;
246 }
247 else {
248
249 # Special case for overlapping ranges because of DST and
250 # other weirdness (like Alaska's change when bought from
251 # Russia by the US). Always prefer latest span.
252 if ( $current->[IS_DST] && $type eq 'local' ) {
253
254 # Asia/Dhaka in 2009j goes into DST without any known
255 # end-of-DST date (wtf, Bangladesh).
256 return $current if $current->[UTC_END] == INFINITY;
257
258 my $next = $self->{spans}[ $i + 1 ];
259
260 # Sometimes we will get here and the span we're
261 # looking at is the last that's been generated so far.
262 # We need to try to generate one more or else we run
263 # out.
264 $next ||= $self->_generate_next_span;
265
266 die "No next span in $self->{max_year}" unless defined $next;
267
268 if ( ( !$next->[IS_DST] )
269 && $next->[$start] <= $seconds
270 && $seconds <= $next->[$end] ) {
271 return $next;
272 }
273 }
274
275 return $current;
276 }
277 }
278}
279
280sub _generate_next_span {
281 my $self = shift;
282
283 my $last_idx = $#{ $self->{spans} };
284
285 my $max_span = $self->max_span;
286
287 # Kind of a hack, but AFAIK there are no zones where it takes
288 # _more_ than a year for a _future_ time zone change to occur, so
289 # by looking two years out we can ensure that we will find at
290 # least one more span. Of course, I will no doubt be proved wrong
291 # and this will cause errors.
292 $self->_generate_spans_until_match( $self->{max_year} + 2,
293 $max_span->[UTC_END] + ( 366 * 86400 ), 'utc' );
294
295 return $self->{spans}[ $last_idx + 1 ];
296}
297
298sub _generate_spans_until_match {
299 my $self = shift;
300 my $generate_until_year = shift;
301 my $seconds = shift;
302 my $type = shift;
303
304 my @changes;
305 my @rules = @{ $self->_rules };
306 foreach my $year ( $self->{max_year} .. $generate_until_year ) {
307 for ( my $x = 0; $x < @rules; $x++ ) {
308 my $last_offset_from_std;
309
310 if ( @rules == 2 ) {
311 $last_offset_from_std
312 = $x
313 ? $rules[0]->offset_from_std
314 : $rules[1]->offset_from_std;
315 }
316 elsif ( @rules == 1 ) {
317 $last_offset_from_std = $rules[0]->offset_from_std;
318 }
319 else {
320 my $count = scalar @rules;
321 die
322 "Cannot generate future changes for zone with $count infinite rules\n";
323 }
324
325 my $rule = $rules[$x];
326
327 my $next = $rule->utc_start_datetime_for_year( $year,
328 $self->{last_offset}, $last_offset_from_std );
329
330 # don't bother with changes we've seen already
331 next if $next->utc_rd_as_seconds < $self->max_span->[UTC_END];
332
333 push @changes,
334 DateTime::TimeZone::OlsonDB::Change->new(
335 type => 'rule',
336 utc_start_datetime => $next,
337 local_start_datetime => $next + DateTime::Duration->new(
338 seconds => $self->{last_observance}->total_offset
339 + $rule->offset_from_std
340 ),
341 short_name => $self->{last_observance}
342 ->formatted_short_name( $rule->letter ),
343 observance => $self->{last_observance},
344 rule => $rule,
345 );
346 }
347 }
348
349 $self->{max_year} = $generate_until_year;
350
351 my @sorted
352 = sort { $a->utc_start_datetime <=> $b->utc_start_datetime } @changes;
353
354 my ( $start, $end ) = _keys_for_type($type);
355
356 my $match;
357 for ( my $x = 1; $x < @sorted; $x++ ) {
358 my $last_total_offset
359 = $x == 1
360 ? $self->max_span->[OFFSET]
361 : $sorted[ $x - 2 ]->total_offset;
362
363 my $span = DateTime::TimeZone::OlsonDB::Change::two_changes_as_span(
364 @sorted[ $x - 1, $x ], $last_total_offset );
365
366 $span = _span_as_array($span);
367
368 push @{ $self->{spans} }, $span;
369
370 $match = $span
371 if $seconds >= $span->[$start] && $seconds < $span->[$end];
372 }
373
374 return $match;
375}
376
377sub max_span { $_[0]->{spans}[-1] }
378
379sub _keys_for_type {
380 $_[0] eq 'utc' ? ( UTC_START, UTC_END ) : ( LOCAL_START, LOCAL_END );
381}
382
383sub _span_as_array {
384 [
385 @{ $_[0] }{
386 qw( utc_start utc_end local_start local_end offset is_dst short_name )
387 }
388 ];
389}
390
3911300020.1ms
# spent 7.14ms within DateTime::TimeZone::is_floating which was called 13000 times, avg 549ns/call: # 13000 times (7.14ms+0s) by DateTime::_handle_offset_modifier at line 332 of DateTime.pm, avg 549ns/call
sub is_floating {0}
392
393sub is_utc {0}
394
395sub has_dst_changes {0}
396
397sub name { $_[0]->{name} }
398sub category { ( split /\//, $_[0]->{name}, 2 )[0] }
399
400sub is_valid_name {
401 my $class = shift;
402 my $name = shift;
403
404 my $tz = try {
405 local $SIG{__DIE__};
406 $class->new( name => $name );
407 };
408
409 return $tz && $tz->isa('DateTime::TimeZone') ? 1 : 0;
410}
411
412sub STORABLE_freeze {
413 my $self = shift;
414
415 return $self->name;
416}
417
418sub STORABLE_thaw {
419 my $self = shift;
420 my $cloning = shift;
421 my $serialized = shift;
422
423 my $class = ref $self || $self;
424
425 my $obj;
426 if ( $class->isa(__PACKAGE__) ) {
427 $obj = __PACKAGE__->new( name => $serialized );
428 }
429 else {
430 $obj = $class->new( name => $serialized );
431 }
432
433 %$self = %$obj;
434
435 return $self;
436}
437
438#
439# Functions
440#
441sub offset_as_seconds {
442 my $offset = shift;
443 $offset = shift if try {
444 local $SIG{__DIE__};
445 $offset->isa('DateTime::TimeZone');
446 };
447
448 return undef unless defined $offset;
449
450 return 0 if $offset eq '0';
451
452 my ( $sign, $hours, $minutes, $seconds );
453 if ( $offset =~ /^([\+\-])?(\d\d?):(\d\d)(?::(\d\d))?$/ ) {
454 ( $sign, $hours, $minutes, $seconds ) = ( $1, $2, $3, $4 );
455 }
456 elsif ( $offset =~ /^([\+\-])?(\d\d)(\d\d)(\d\d)?$/ ) {
457 ( $sign, $hours, $minutes, $seconds ) = ( $1, $2, $3, $4 );
458 }
459 else {
460 return undef;
461 }
462
463 $sign = '+' unless defined $sign;
464 return undef unless $hours >= 0 && $hours <= 99;
465 return undef unless $minutes >= 0 && $minutes <= 59;
466 return undef
467 unless !defined($seconds) || ( $seconds >= 0 && $seconds <= 59 );
468
469 my $total = $hours * 3600 + $minutes * 60;
470 $total += $seconds if $seconds;
471 $total *= -1 if $sign eq '-';
472
473 return $total;
474}
475
476sub offset_as_string {
477 my $offset = shift;
478 $offset = shift if try {
479 local $SIG{__DIE__};
480 $offset->isa('DateTime::TimeZone');
481 };
482
483 return undef unless defined $offset;
484 return undef unless $offset >= -359999 && $offset <= 359999;
485
486 my $sign = $offset < 0 ? '-' : '+';
487
488 $offset = abs($offset);
489
490 my $hours = int( $offset / 3600 );
491 $offset %= 3600;
492 my $mins = int( $offset / 60 );
493 $offset %= 60;
494 my $secs = int($offset);
495
496 return (
497 $secs
498 ? sprintf( '%s%02d%02d%02d', $sign, $hours, $mins, $secs )
499 : sprintf( '%s%02d%02d', $sign, $hours, $mins )
500 );
501}
502
503# These methods all operate on data contained in the DateTime/TimeZone/Catalog.pm file.
504
505sub all_names {
506 return
507 wantarray
508 ? @DateTime::TimeZone::Catalog::ALL
509 : [@DateTime::TimeZone::Catalog::ALL];
510}
511
512sub categories {
513 return wantarray
514 ? @DateTime::TimeZone::Catalog::CATEGORY_NAMES
515 : [@DateTime::TimeZone::Catalog::CATEGORY_NAMES];
516}
517
518sub links {
519 return
520 wantarray
521 ? %DateTime::TimeZone::Catalog::LINKS
522 : {%DateTime::TimeZone::Catalog::LINKS};
523}
524
525sub names_in_category {
526 shift if $_[0]->isa('DateTime::TimeZone');
527 return unless exists $DateTime::TimeZone::Catalog::CATEGORIES{ $_[0] };
528
529 return wantarray
530 ? @{ $DateTime::TimeZone::Catalog::CATEGORIES{ $_[0] } }
531 : $DateTime::TimeZone::Catalog::CATEGORIES{ $_[0] };
532}
533
534sub countries {
535 wantarray
536 ? ( sort keys %DateTime::TimeZone::Catalog::ZONES_BY_COUNTRY )
537 : [ sort keys %DateTime::TimeZone::Catalog::ZONES_BY_COUNTRY ];
538}
539
540sub names_in_country {
541 shift if $_[0]->isa('DateTime::TimeZone');
542
543 return
544 unless
545 exists $DateTime::TimeZone::Catalog::ZONES_BY_COUNTRY{ lc $_[0] };
546
547 return
548 wantarray
549 ? @{ $DateTime::TimeZone::Catalog::ZONES_BY_COUNTRY{ lc $_[0] } }
550 : $DateTime::TimeZone::Catalog::ZONES_BY_COUNTRY{ lc $_[0] };
551}
552
553117µs1;
554
555# ABSTRACT: Time zone object base class and factory
556
557__END__
 
# spent 1.59ms within DateTime::TimeZone::CORE:match which was called 3002 times, avg 528ns/call: # 3002 times (1.59ms+0s) by DateTime::TimeZone::new at line 47, avg 528ns/call
sub DateTime::TimeZone::CORE:match; # opcode