← Index
NYTProf Performance Profile   « block view • line view • sub view »
For mongo_pain.pl
  Run on Fri Mar 25 17:00:29 2011
Reported on Fri Mar 25 17:07:06 2011

Filename/usr/local/share/perl/5.10.1/DateTime/TimeZone.pm
StatementsExecuted 67 statements in 4.72ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1114.51ms4.64msDateTime::TimeZone::::BEGIN@11DateTime::TimeZone::BEGIN@11
111713µs4.77msDateTime::TimeZone::::BEGIN@13DateTime::TimeZone::BEGIN@13
111473µs2.33msDateTime::TimeZone::::BEGIN@12DateTime::TimeZone::BEGIN@12
22155µs176µsDateTime::TimeZone::::newDateTime::TimeZone::new
11122µs22µsDateTime::TimeZone::::BEGIN@6DateTime::TimeZone::BEGIN@6
11113µs71µsDateTime::TimeZone::::BEGIN@18DateTime::TimeZone::BEGIN@18
11112µs12µsDateTime::TimeZone::::BEGIN@2DateTime::TimeZone::BEGIN@2
11112µs82µsDateTime::TimeZone::::BEGIN@16DateTime::TimeZone::BEGIN@16
11111µs11µsDateTime::TimeZone::::BEGIN@14DateTime::TimeZone::BEGIN@14
11111µs29µsDateTime::TimeZone::::BEGIN@9DateTime::TimeZone::BEGIN@9
11111µs17µsDateTime::TimeZone::::BEGIN@8DateTime::TimeZone::BEGIN@8
11110µs47µsDateTime::TimeZone::::BEGIN@26DateTime::TimeZone::BEGIN@26
11110µs48µsDateTime::TimeZone::::BEGIN@19DateTime::TimeZone::BEGIN@19
1119µs9µsDateTime::TimeZone::::BEGIN@15DateTime::TimeZone::BEGIN@15
1119µs46µsDateTime::TimeZone::::BEGIN@22DateTime::TimeZone::BEGIN@22
1119µs53µsDateTime::TimeZone::::BEGIN@25DateTime::TimeZone::BEGIN@25
1119µs45µsDateTime::TimeZone::::BEGIN@24DateTime::TimeZone::BEGIN@24
1119µs53µsDateTime::TimeZone::::BEGIN@23DateTime::TimeZone::BEGIN@23
1119µs45µsDateTime::TimeZone::::BEGIN@28DateTime::TimeZone::BEGIN@28
1119µs45µsDateTime::TimeZone::::BEGIN@27DateTime::TimeZone::BEGIN@27
2113µs3µsDateTime::TimeZone::::CORE:matchDateTime::TimeZone::CORE:match (opcode)
0000s0sDateTime::TimeZone::::STORABLE_freezeDateTime::TimeZone::STORABLE_freeze
0000s0sDateTime::TimeZone::::STORABLE_thawDateTime::TimeZone::STORABLE_thaw
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_floatingDateTime::TimeZone::is_floating
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;
2
# spent 12µs within DateTime::TimeZone::BEGIN@2 which was called: # once (12µs+0s) by DateTime::BEGIN@46 at line 4
BEGIN {
316µs $DateTime::TimeZone::VERSION = '1.31';
4126µs112µs}
# spent 12µs making 1 call to DateTime::TimeZone::BEGIN@2
5
6349µs122µs
# spent 22µs within DateTime::TimeZone::BEGIN@6 which was called: # once (22µs+0s) by DateTime::BEGIN@46 at line 6
use 5.006;
# spent 22µs making 1 call to DateTime::TimeZone::BEGIN@6
7
8332µs223µs
# spent 17µs (11+6) within DateTime::TimeZone::BEGIN@8 which was called: # once (11µs+6µs) by DateTime::BEGIN@46 at line 8
use strict;
# spent 17µs making 1 call to DateTime::TimeZone::BEGIN@8 # spent 6µs making 1 call to strict::import
9335µs246µs
# spent 29µs (11+18) within DateTime::TimeZone::BEGIN@9 which was called: # once (11µs+18µs) by DateTime::BEGIN@46 at line 9
use warnings;
# spent 29µs making 1 call to DateTime::TimeZone::BEGIN@9 # spent 18µs making 1 call to warnings::import
10
113143µs14.64ms
# spent 4.64ms (4.51+136µs) within DateTime::TimeZone::BEGIN@11 which was called: # once (4.51ms+136µs) by DateTime::BEGIN@46 at line 11
use DateTime::TimeZone::Catalog;
# spent 4.64ms making 1 call to DateTime::TimeZone::BEGIN@11
123211µs12.33ms
# spent 2.33ms (473µs+1.86) within DateTime::TimeZone::BEGIN@12 which was called: # once (473µs+1.86ms) by DateTime::BEGIN@46 at line 12
use DateTime::TimeZone::Floating;
# spent 2.33ms making 1 call to DateTime::TimeZone::BEGIN@12
133129µs14.77ms
# spent 4.77ms (713µs+4.06) within DateTime::TimeZone::BEGIN@13 which was called: # once (713µs+4.06ms) by DateTime::BEGIN@46 at line 13
use DateTime::TimeZone::Local;
# spent 4.77ms making 1 call to DateTime::TimeZone::BEGIN@13
14340µs111µs
# spent 11µs within DateTime::TimeZone::BEGIN@14 which was called: # once (11µs+0s) by DateTime::BEGIN@46 at line 14
use DateTime::TimeZone::OffsetOnly;
# spent 11µs making 1 call to DateTime::TimeZone::BEGIN@14
15342µs19µs
# spent 9µs within DateTime::TimeZone::BEGIN@15 which was called: # once (9µs+0s) by DateTime::BEGIN@46 at line 15
use DateTime::TimeZone::UTC;
# spent 9µs making 1 call to DateTime::TimeZone::BEGIN@15
16370µs2153µs
# spent 82µs (12+71) within DateTime::TimeZone::BEGIN@16 which was called: # once (12µs+71µs) by DateTime::BEGIN@46 at line 16
use Params::Validate qw( validate validate_pos SCALAR ARRAYREF BOOLEAN );
# spent 82µs making 1 call to DateTime::TimeZone::BEGIN@16 # spent 71µs making 1 call to Exporter::import
17
18351µs2130µs
# spent 71µs (13+59) within DateTime::TimeZone::BEGIN@18 which was called: # once (13µs+59µs) by DateTime::BEGIN@46 at line 18
use constant INFINITY => 100**1000;
# spent 71µs making 1 call to DateTime::TimeZone::BEGIN@18 # spent 59µs making 1 call to constant::import
19340µs286µs
# spent 48µs (10+38) within DateTime::TimeZone::BEGIN@19 which was called: # once (10µs+38µs) by DateTime::BEGIN@46 at line 19
use constant NEG_INFINITY => -1 * ( 100**1000 );
# spent 48µs making 1 call to DateTime::TimeZone::BEGIN@19 # spent 38µs making 1 call to constant::import
20
21# the offsets for each span element
22341µs282µs
# spent 46µs (9+36) within DateTime::TimeZone::BEGIN@22 which was called: # once (9µs+36µs) by DateTime::BEGIN@46 at line 22
use constant UTC_START => 0;
# spent 46µs making 1 call to DateTime::TimeZone::BEGIN@22 # spent 36µs making 1 call to constant::import
23338µs296µs
# spent 53µs (9+44) within DateTime::TimeZone::BEGIN@23 which was called: # once (9µs+44µs) by DateTime::BEGIN@46 at line 23
use constant UTC_END => 1;
# spent 53µs making 1 call to DateTime::TimeZone::BEGIN@23 # spent 44µs making 1 call to constant::import
24337µs281µs
# spent 45µs (9+36) within DateTime::TimeZone::BEGIN@24 which was called: # once (9µs+36µs) by DateTime::BEGIN@46 at line 24
use constant LOCAL_START => 2;
# spent 45µs making 1 call to DateTime::TimeZone::BEGIN@24 # spent 36µs making 1 call to constant::import
25339µs296µs
# spent 53µs (9+44) within DateTime::TimeZone::BEGIN@25 which was called: # once (9µs+44µs) by DateTime::BEGIN@46 at line 25
use constant LOCAL_END => 3;
# spent 53µs making 1 call to DateTime::TimeZone::BEGIN@25 # spent 44µs making 1 call to constant::import
26338µs283µs
# spent 47µs (10+37) within DateTime::TimeZone::BEGIN@26 which was called: # once (10µs+37µs) by DateTime::BEGIN@46 at line 26
use constant OFFSET => 4;
# spent 47µs making 1 call to DateTime::TimeZone::BEGIN@26 # spent 37µs making 1 call to constant::import
27337µs280µs
# spent 45µs (9+36) within DateTime::TimeZone::BEGIN@27 which was called: # once (9µs+36µs) by DateTime::BEGIN@46 at line 27
use constant IS_DST => 5;
# spent 45µs making 1 call to DateTime::TimeZone::BEGIN@27 # spent 36µs making 1 call to constant::import
2833.46ms281µs
# spent 45µs (9+36) within DateTime::TimeZone::BEGIN@28 which was called: # once (9µs+36µs) by DateTime::BEGIN@46 at line 28
use constant SHORT_NAME => 6;
# spent 45µs making 1 call to DateTime::TimeZone::BEGIN@28 # spent 36µs making 1 call to constant::import
29
30111µsmy %SpecialName = map { $_ => 1 }
31 qw( EST MST HST CET EET MET WET EST5EDT CST6CDT MST7MDT PST8PDT );
32
33
# spent 176µs (55+120) within DateTime::TimeZone::new which was called 2 times, avg 88µs/call: # once (35µs+68µs) by MongoDB::GridFS::BEGIN@24 at line 47 of DateTime/Infinite.pm # once (20µs+53µs) by MongoDB::GridFS::BEGIN@24 at line 71 of DateTime/Infinite.pm
sub new {
3410101µs my $class = shift;
35142µs294µs my %p = validate(
# spent 94µs making 2 calls to Params::Validate::_validate, avg 47µs/call
# spent 9µs executing statements in 2 string evals (merged)
36 @_,
37 { name => { type => SCALAR } },
38 );
39
40 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
4723µs unless ( $p{name} =~ m,/,
# spent 3µs making 2 calls to DateTime::TimeZone::CORE:match, avg 1µs/call
48 || $SpecialName{ $p{name} } ) {
49223µs if ( $p{name} eq 'floating' ) {
# spent 23µs making 2 calls to DateTime::TimeZone::Floating::new, avg 12µs/call
50 return DateTime::TimeZone::Floating->new;
51 }
52
53 if ( $p{name} eq 'local' ) {
54 return DateTime::TimeZone::Local->TimeZone();
55 }
56
57 if ( $p{name} eq 'UTC' || $p{name} eq 'Z' ) {
58 return DateTime::TimeZone::UTC->new;
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{/}{::}g;
67 my $real_class = "DateTime::TimeZone::$subclass";
68
69 die "The timezone '$p{name}' in an invalid name.\n"
70 unless $real_class =~ /^\w+(::\w+)*$/;
71
72 unless ( $real_class->can('instance') ) {
73 my $e = do {
74 local $@;
75 local $SIG{__DIE__};
76 eval "require $real_class";
77 $@;
78 };
79
80 if ($e) {
81 my $regex = join '.', split /::/, $real_class;
82 $regex .= '\\.pm';
83
84 if ( $e =~ /^Can't locate $regex/i ) {
85 die
86 "The timezone '$p{name}' could not be loaded, or is an invalid name.\n";
87 }
88 else {
89 die $e;
90 }
91 }
92 }
93
94 my $zone = $real_class->instance( name => $p{name}, is_olson => 1 );
95
96 if ( $zone->is_olson() ) {
97 my $object_version
98 = $zone->can('olson_version')
99 ? $zone->olson_version()
100 : 'unknown';
101 my $catalog_version = DateTime::TimeZone::Catalog->OlsonVersion();
102
103 if ( $object_version ne $catalog_version ) {
104 warn
105 "Loaded $real_class, which is from an older version ($object_version) of the Olson database than this installation of DateTime::TimeZone ($catalog_version).\n";
106 }
107 }
108
109 return $zone;
110}
111
112sub _init {
113 my $class = shift;
114 my %p = validate(
115 @_, {
116 name => { type => SCALAR },
117 spans => { type => ARRAYREF },
118 is_olson => { type => BOOLEAN, default => 0 },
119 },
120 );
121
122 my $self = bless {
123 name => $p{name},
124 spans => $p{spans},
125 is_olson => $p{is_olson},
126 }, $class;
127
128 foreach my $k (qw( last_offset last_observance rules max_year )) {
129 my $m = "_$k";
130 $self->{$k} = $self->$m() if $self->can($m);
131 }
132
133 return $self;
134}
135
136sub is_olson { $_[0]->{is_olson} }
137
138sub is_dst_for_datetime {
139 my $self = shift;
140
141 my $span = $self->_span_for_datetime( 'utc', $_[0] );
142
143 return $span->[IS_DST];
144}
145
146sub offset_for_datetime {
147 my $self = shift;
148
149 my $span = $self->_span_for_datetime( 'utc', $_[0] );
150
151 return $span->[OFFSET];
152}
153
154sub offset_for_local_datetime {
155 my $self = shift;
156
157 my $span = $self->_span_for_datetime( 'local', $_[0] );
158
159 return $span->[OFFSET];
160}
161
162sub short_name_for_datetime {
163 my $self = shift;
164
165 my $span = $self->_span_for_datetime( 'utc', $_[0] );
166
167 return $span->[SHORT_NAME];
168}
169
170sub _span_for_datetime {
171 my $self = shift;
172 my $type = shift;
173 my $dt = shift;
174
175 my $method = $type . '_rd_as_seconds';
176
177 my $end = $type eq 'utc' ? UTC_END : LOCAL_END;
178
179 my $span;
180 my $seconds = $dt->$method();
181 if ( $seconds < $self->max_span->[$end] ) {
182 $span = $self->_spans_binary_search( $type, $seconds );
183 }
184 else {
185 my $until_year = $dt->utc_year + 1;
186 $span = $self->_generate_spans_until_match( $until_year, $seconds,
187 $type );
188 }
189
190 # This means someone gave a local time that doesn't exist
191 # (like during a transition into savings time)
192 unless ( defined $span ) {
193 my $err = 'Invalid local time for date';
194 $err .= ' ' . $dt->iso8601 if $type eq 'utc';
195 $err .= " in time zone: " . $self->name;
196 $err .= "\n";
197
198 die $err;
199 }
200
201 return $span;
202}
203
204sub _spans_binary_search {
205 my $self = shift;
206 my ( $type, $seconds ) = @_;
207
208 my ( $start, $end ) = _keys_for_type($type);
209
210 my $min = 0;
211 my $max = scalar @{ $self->{spans} } + 1;
212 my $i = int( $max / 2 );
213
214 # special case for when there are only 2 spans
215 $i++ if $max % 2 && $max != 3;
216
217 $i = 0 if @{ $self->{spans} } == 1;
218
219 while (1) {
220 my $current = $self->{spans}[$i];
221
222 if ( $seconds < $current->[$start] ) {
223 $max = $i;
224 my $c = int( ( $i - $min ) / 2 );
225 $c ||= 1;
226
227 $i -= $c;
228
229 return if $i < $min;
230 }
231 elsif ( $seconds >= $current->[$end] ) {
232 $min = $i;
233 my $c = int( ( $max - $i ) / 2 );
234 $c ||= 1;
235
236 $i += $c;
237
238 return if $i >= $max;
239 }
240 else {
241
242 # Special case for overlapping ranges because of DST and
243 # other weirdness (like Alaska's change when bought from
244 # Russia by the US). Always prefer latest span.
245 if ( $current->[IS_DST] && $type eq 'local' ) {
246
247 # Asia/Dhaka in 2009j goes into DST without any known
248 # end-of-DST date (wtf, Bangladesh).
249 return $current if $current->[UTC_END] == INFINITY;
250
251 my $next = $self->{spans}[ $i + 1 ];
252
253 # Sometimes we will get here and the span we're
254 # looking at is the last that's been generated so far.
255 # We need to try to generate one more or else we run
256 # out.
257 $next ||= $self->_generate_next_span;
258
259 die "No next span in $self->{max_year}" unless defined $next;
260
261 if ( ( !$next->[IS_DST] )
262 && $next->[$start] <= $seconds
263 && $seconds <= $next->[$end] ) {
264 return $next;
265 }
266 }
267
268 return $current;
269 }
270 }
271}
272
273sub _generate_next_span {
274 my $self = shift;
275
276 my $last_idx = $#{ $self->{spans} };
277
278 my $max_span = $self->max_span;
279
280 # Kind of a hack, but AFAIK there are no zones where it takes
281 # _more_ than a year for a _future_ time zone change to occur, so
282 # by looking two years out we can ensure that we will find at
283 # least one more span. Of course, I will no doubt be proved wrong
284 # and this will cause errors.
285 $self->_generate_spans_until_match( $self->{max_year} + 2,
286 $max_span->[UTC_END] + ( 366 * 86400 ), 'utc' );
287
288 return $self->{spans}[ $last_idx + 1 ];
289}
290
291sub _generate_spans_until_match {
292 my $self = shift;
293 my $generate_until_year = shift;
294 my $seconds = shift;
295 my $type = shift;
296
297 my @changes;
298 my @rules = @{ $self->_rules };
299 foreach my $year ( $self->{max_year} .. $generate_until_year ) {
300 for ( my $x = 0; $x < @rules; $x++ ) {
301 my $last_offset_from_std;
302
303 if ( @rules == 2 ) {
304 $last_offset_from_std
305 = $x
306 ? $rules[0]->offset_from_std
307 : $rules[1]->offset_from_std;
308 }
309 elsif ( @rules == 1 ) {
310 $last_offset_from_std = $rules[0]->offset_from_std;
311 }
312 else {
313 my $count = scalar @rules;
314 die
315 "Cannot generate future changes for zone with $count infinite rules\n";
316 }
317
318 my $rule = $rules[$x];
319
320 my $next = $rule->utc_start_datetime_for_year( $year,
321 $self->{last_offset}, $last_offset_from_std );
322
323 # don't bother with changes we've seen already
324 next if $next->utc_rd_as_seconds < $self->max_span->[UTC_END];
325
326 push @changes,
327 DateTime::TimeZone::OlsonDB::Change->new(
328 type => 'rule',
329 utc_start_datetime => $next,
330 local_start_datetime => $next + DateTime::Duration->new(
331 seconds => $self->{last_observance}->total_offset
332 + $rule->offset_from_std
333 ),
334 short_name => sprintf(
335 $self->{last_observance}->format, $rule->letter
336 ),
337 observance => $self->{last_observance},
338 rule => $rule,
339 );
340 }
341 }
342
343 $self->{max_year} = $generate_until_year;
344
345 my @sorted
346 = sort { $a->utc_start_datetime <=> $b->utc_start_datetime } @changes;
347
348 my ( $start, $end ) = _keys_for_type($type);
349
350 my $match;
351 for ( my $x = 1; $x < @sorted; $x++ ) {
352 my $last_total_offset
353 = $x == 1
354 ? $self->max_span->[OFFSET]
355 : $sorted[ $x - 2 ]->total_offset;
356
357 my $span = DateTime::TimeZone::OlsonDB::Change::two_changes_as_span(
358 @sorted[ $x - 1, $x ], $last_total_offset );
359
360 $span = _span_as_array($span);
361
362 push @{ $self->{spans} }, $span;
363
364 $match = $span
365 if $seconds >= $span->[$start] && $seconds < $span->[$end];
366 }
367
368 return $match;
369}
370
371sub max_span { $_[0]->{spans}[-1] }
372
373sub _keys_for_type {
374 $_[0] eq 'utc' ? ( UTC_START, UTC_END ) : ( LOCAL_START, LOCAL_END );
375}
376
377sub _span_as_array {
378 [
379 @{ $_[0] }{
380 qw( utc_start utc_end local_start local_end offset is_dst short_name )
381 }
382 ];
383}
384
385sub is_floating {0}
386
387sub is_utc {0}
388
389sub has_dst_changes {0}
390
391sub name { $_[0]->{name} }
392sub category { ( split /\//, $_[0]->{name}, 2 )[0] }
393
394sub is_valid_name {
395 my $tz;
396 {
397 local $@;
398 local $SIG{__DIE__};
399 $tz = eval { $_[0]->new( name => $_[1] ) };
400 }
401
402 return $tz && $tz->isa('DateTime::TimeZone') ? 1 : 0;
403}
404
405sub STORABLE_freeze {
406 my $self = shift;
407
408 return $self->name;
409}
410
411sub STORABLE_thaw {
412 my $self = shift;
413 my $cloning = shift;
414 my $serialized = shift;
415
416 my $class = ref $self || $self;
417
418 my $obj;
419 if ( $class->isa(__PACKAGE__) ) {
420 $obj = __PACKAGE__->new( name => $serialized );
421 }
422 else {
423 $obj = $class->new( name => $serialized );
424 }
425
426 %$self = %$obj;
427
428 return $self;
429}
430
431#
432# Functions
433#
434sub offset_as_seconds {
435 {
436 local $@;
437 local $SIG{__DIE__};
438 shift if eval { $_[0]->isa('DateTime::TimeZone') };
439 }
440
441 my $offset = shift;
442
443 return undef unless defined $offset;
444
445 return 0 if $offset eq '0';
446
447 my ( $sign, $hours, $minutes, $seconds );
448 if ( $offset =~ /^([\+\-])?(\d\d?):(\d\d)(?::(\d\d))?$/ ) {
449 ( $sign, $hours, $minutes, $seconds ) = ( $1, $2, $3, $4 );
450 }
451 elsif ( $offset =~ /^([\+\-])?(\d\d)(\d\d)(\d\d)?$/ ) {
452 ( $sign, $hours, $minutes, $seconds ) = ( $1, $2, $3, $4 );
453 }
454 else {
455 return undef;
456 }
457
458 $sign = '+' unless defined $sign;
459 return undef unless $hours >= 0 && $hours <= 99;
460 return undef unless $minutes >= 0 && $minutes <= 59;
461 return undef
462 unless !defined($seconds) || ( $seconds >= 0 && $seconds <= 59 );
463
464 my $total = $hours * 3600 + $minutes * 60;
465 $total += $seconds if $seconds;
466 $total *= -1 if $sign eq '-';
467
468 return $total;
469}
470
471sub offset_as_string {
472 {
473 local $@;
474 local $SIG{__DIE__};
475 shift if eval { $_[0]->isa('DateTime::TimeZone') };
476 }
477
478 my $offset = shift;
479
480 return undef unless defined $offset;
481 return undef unless $offset >= -359999 && $offset <= 359999;
482
483 my $sign = $offset < 0 ? '-' : '+';
484
485 $offset = abs($offset);
486
487 my $hours = int( $offset / 3600 );
488 $offset %= 3600;
489 my $mins = int( $offset / 60 );
490 $offset %= 60;
491 my $secs = int($offset);
492
493 return (
494 $secs
495 ? sprintf( '%s%02d%02d%02d', $sign, $hours, $mins, $secs )
496 : sprintf( '%s%02d%02d', $sign, $hours, $mins )
497 );
498}
499
500# These methods all operate on data contained in the DateTime/TimeZone/Catalog.pm file.
501
502sub all_names {
503 return
504 wantarray
505 ? @DateTime::TimeZone::Catalog::ALL
506 : [@DateTime::TimeZone::Catalog::ALL];
507}
508
509sub categories {
510 return wantarray
511 ? @DateTime::TimeZone::Catalog::CATEGORY_NAMES
512 : [@DateTime::TimeZone::Catalog::CATEGORY_NAMES];
513}
514
515sub links {
516 return
517 wantarray
518 ? %DateTime::TimeZone::Catalog::LINKS
519 : {%DateTime::TimeZone::Catalog::LINKS};
520}
521
522sub names_in_category {
523 shift if $_[0]->isa('DateTime::TimeZone');
524 return unless exists $DateTime::TimeZone::Catalog::CATEGORIES{ $_[0] };
525
526 return wantarray
527 ? @{ $DateTime::TimeZone::Catalog::CATEGORIES{ $_[0] } }
528 : [ $DateTime::TimeZone::Catalog::CATEGORIES{ $_[0] } ];
529}
530
531sub countries {
532 wantarray
533 ? ( sort keys %DateTime::TimeZone::Catalog::ZONES_BY_COUNTRY )
534 : [ sort keys %DateTime::TimeZone::Catalog::ZONES_BY_COUNTRY ];
535}
536
537sub names_in_country {
538 shift if $_[0]->isa('DateTime::TimeZone');
539
540 return
541 unless
542 exists $DateTime::TimeZone::Catalog::ZONES_BY_COUNTRY{ lc $_[0] };
543
544 return
545 wantarray
546 ? @{ $DateTime::TimeZone::Catalog::ZONES_BY_COUNTRY{ lc $_[0] } }
547 : $DateTime::TimeZone::Catalog::ZONES_BY_COUNTRY{ lc $_[0] };
548}
549
55016µs1;
551
552# ABSTRACT: Time zone object base class and factory
553
- -
556=pod
557
- -
848__END__
 
# spent 3µs within DateTime::TimeZone::CORE:match which was called 2 times, avg 1µs/call: # 2 times (3µs+0s) by DateTime::TimeZone::new at line 47, avg 1µs/call
sub DateTime::TimeZone::CORE:match; # opcode