← Index
NYTProf Performance Profile   « block view • line view • sub view »
For mentat.storage.mongo.pl
  Run on Tue Jun 24 09:58:41 2014
Reported on Tue Jun 24 09:59:29 2014

Filename/usr/local/share/perl/5.14.2/DateTime/TimeZone.pm
StatementsExecuted 298 statements in 8.27ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1116.01ms6.20msDateTime::TimeZone::::BEGIN@14DateTime::TimeZone::BEGIN@14
6544.07ms121msDateTime::TimeZone::::newDateTime::TimeZone::new (recurses: max depth 1, inclusive time 18.3ms)
1111.07ms18.6msDateTime::TimeZone::::BEGIN@16DateTime::TimeZone::BEGIN@16
111805µs4.48msDateTime::TimeZone::::BEGIN@15DateTime::TimeZone::BEGIN@15
111109µs158µsDateTime::TimeZone::::_initDateTime::TimeZone::_init
31195µs103µsDateTime::TimeZone::::_spans_binary_searchDateTime::TimeZone::_spans_binary_search
31181µs204µsDateTime::TimeZone::::_span_for_datetimeDateTime::TimeZone::_span_for_datetime
11136µs46µsDateTime::TimeZone::::offset_as_secondsDateTime::TimeZone::offset_as_seconds
11132µs176µsDateTime::TimeZone::::BEGIN@19DateTime::TimeZone::BEGIN@19
11131µs46µsDateTime::TimeZone::::BEGIN@12DateTime::TimeZone::BEGIN@12
31128µs232µsDateTime::TimeZone::::offset_for_datetimeDateTime::TimeZone::offset_for_datetime
11127µs27µsDateTime::TimeZone::::BEGIN@9DateTime::TimeZone::BEGIN@9
93125µs25µsDateTime::TimeZone::::CORE:matchDateTime::TimeZone::CORE:match (opcode)
11120µs20µsDateTime::TimeZone::::BEGIN@17DateTime::TimeZone::BEGIN@17
11118µs18µsDateTime::TimeZone::::BEGIN@5DateTime::TimeZone::BEGIN@5
11118µs94µsDateTime::TimeZone::::BEGIN@21DateTime::TimeZone::BEGIN@21
11116µs23µsDateTime::TimeZone::::BEGIN@11DateTime::TimeZone::BEGIN@11
11114µs77µsDateTime::TimeZone::::BEGIN@25DateTime::TimeZone::BEGIN@25
11114µs14µsDateTime::TimeZone::::BEGIN@18DateTime::TimeZone::BEGIN@18
11114µs78µsDateTime::TimeZone::::BEGIN@22DateTime::TimeZone::BEGIN@22
11113µs73µsDateTime::TimeZone::::BEGIN@26DateTime::TimeZone::BEGIN@26
11113µs73µsDateTime::TimeZone::::BEGIN@31DateTime::TimeZone::BEGIN@31
11113µs71µsDateTime::TimeZone::::BEGIN@30DateTime::TimeZone::BEGIN@30
11113µs71µsDateTime::TimeZone::::BEGIN@28DateTime::TimeZone::BEGIN@28
11112µs71µsDateTime::TimeZone::::BEGIN@27DateTime::TimeZone::BEGIN@27
11112µs70µsDateTime::TimeZone::::BEGIN@29DateTime::TimeZone::BEGIN@29
5419µs9µsDateTime::TimeZone::::is_floatingDateTime::TimeZone::is_floating
3119µs9µsDateTime::TimeZone::::max_spanDateTime::TimeZone::max_span
3118µs8µsDateTime::TimeZone::::_keys_for_typeDateTime::TimeZone::_keys_for_type
2217µs7µsDateTime::TimeZone::::CORE:substDateTime::TimeZone::CORE:subst (opcode)
1114µs4µsDateTime::TimeZone::::is_olsonDateTime::TimeZone::is_olson
1112µs2µsDateTime::TimeZone::::is_utcDateTime::TimeZone::is_utc
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::::_span_as_arrayDateTime::TimeZone::_span_as_array
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_valid_nameDateTime::TimeZone::is_valid_name
0000s0sDateTime::TimeZone::::linksDateTime::TimeZone::links
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_stringDateTime::TimeZone::offset_as_string
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{
323µs $DateTime::TimeZone::VERSION = '1.63';
4}
5
# spent 18µs within DateTime::TimeZone::BEGIN@5 which was called: # once (18µs+0s) by DateTime::BEGIN@46 at line 7
BEGIN {
6111µs $DateTime::TimeZone::AUTHORITY = 'cpan:DROLSKY';
7142µs118µs}
# spent 18µs making 1 call to DateTime::TimeZone::BEGIN@5
8
9289µs127µs
# spent 27µs within DateTime::TimeZone::BEGIN@9 which was called: # once (27µs+0s) by DateTime::BEGIN@46 at line 9
use 5.006;
# spent 27µs making 1 call to DateTime::TimeZone::BEGIN@9
10
11265µs230µs
# spent 23µs (16+7) within DateTime::TimeZone::BEGIN@11 which was called: # once (16µs+7µs) by DateTime::BEGIN@46 at line 11
use strict;
# spent 23µs making 1 call to DateTime::TimeZone::BEGIN@11 # spent 7µs making 1 call to strict::import
12255µs260µs
# spent 46µs (31+15) within DateTime::TimeZone::BEGIN@12 which was called: # once (31µs+15µs) by DateTime::BEGIN@46 at line 12
use warnings;
# spent 46µs making 1 call to DateTime::TimeZone::BEGIN@12 # spent 15µs making 1 call to warnings::import
13
142263µs16.20ms
# spent 6.20ms (6.01+187µs) within DateTime::TimeZone::BEGIN@14 which was called: # once (6.01ms+187µs) by DateTime::BEGIN@46 at line 14
use DateTime::TimeZone::Catalog;
# spent 6.20ms making 1 call to DateTime::TimeZone::BEGIN@14
152433µs14.48ms
# spent 4.48ms (805µs+3.67) within DateTime::TimeZone::BEGIN@15 which was called: # once (805µs+3.67ms) by DateTime::BEGIN@46 at line 15
use DateTime::TimeZone::Floating;
# spent 4.48ms making 1 call to DateTime::TimeZone::BEGIN@15
162232µs118.6ms
# spent 18.6ms (1.07+17.5) within DateTime::TimeZone::BEGIN@16 which was called: # once (1.07ms+17.5ms) by DateTime::BEGIN@46 at line 16
use DateTime::TimeZone::Local;
# spent 18.6ms making 1 call to DateTime::TimeZone::BEGIN@16
17261µs120µs
# spent 20µs within DateTime::TimeZone::BEGIN@17 which was called: # once (20µs+0s) by DateTime::BEGIN@46 at line 17
use DateTime::TimeZone::OffsetOnly;
# spent 20µs making 1 call to DateTime::TimeZone::BEGIN@17
18275µs114µs
# spent 14µs within DateTime::TimeZone::BEGIN@18 which was called: # once (14µs+0s) by DateTime::BEGIN@46 at line 18
use DateTime::TimeZone::UTC;
# spent 14µs making 1 call to DateTime::TimeZone::BEGIN@18
193162µs3320µs
# spent 176µs (32+144) within DateTime::TimeZone::BEGIN@19 which was called: # once (32µs+144µs) by DateTime::BEGIN@46 at line 19
use Params::Validate 0.72 qw( validate validate_pos SCALAR ARRAYREF BOOLEAN );
# spent 176µs making 1 call to DateTime::TimeZone::BEGIN@19 # spent 115µs making 1 call to Exporter::import # spent 29µs making 1 call to UNIVERSAL::VERSION
20
21278µs2170µs
# spent 94µs (18+76) within DateTime::TimeZone::BEGIN@21 which was called: # once (18µs+76µs) by DateTime::BEGIN@46 at line 21
use constant INFINITY => 100**1000;
# spent 94µs making 1 call to DateTime::TimeZone::BEGIN@21 # spent 76µs making 1 call to constant::import
22260µs2142µs
# spent 78µs (14+64) within DateTime::TimeZone::BEGIN@22 which was called: # once (14µs+64µs) by DateTime::BEGIN@46 at line 22
use constant NEG_INFINITY => -1 * ( 100**1000 );
# spent 78µs making 1 call to DateTime::TimeZone::BEGIN@22 # spent 64µs making 1 call to constant::import
23
24# the offsets for each span element
25257µs2139µs
# spent 77µs (14+63) within DateTime::TimeZone::BEGIN@25 which was called: # once (14µs+63µs) by DateTime::BEGIN@46 at line 25
use constant UTC_START => 0;
# spent 77µs making 1 call to DateTime::TimeZone::BEGIN@25 # spent 63µs making 1 call to constant::import
26256µs2133µs
# spent 73µs (13+60) within DateTime::TimeZone::BEGIN@26 which was called: # once (13µs+60µs) by DateTime::BEGIN@46 at line 26
use constant UTC_END => 1;
# spent 73µs making 1 call to DateTime::TimeZone::BEGIN@26 # spent 60µs making 1 call to constant::import
27254µs2130µs
# spent 71µs (12+59) within DateTime::TimeZone::BEGIN@27 which was called: # once (12µs+59µs) by DateTime::BEGIN@46 at line 27
use constant LOCAL_START => 2;
# spent 71µs making 1 call to DateTime::TimeZone::BEGIN@27 # spent 59µs making 1 call to constant::import
28255µs2130µs
# spent 71µs (13+59) within DateTime::TimeZone::BEGIN@28 which was called: # once (13µs+59µs) by DateTime::BEGIN@46 at line 28
use constant LOCAL_END => 3;
# spent 71µs making 1 call to DateTime::TimeZone::BEGIN@28 # spent 59µs making 1 call to constant::import
29260µs2128µs
# spent 70µs (12+58) within DateTime::TimeZone::BEGIN@29 which was called: # once (12µs+58µs) by DateTime::BEGIN@46 at line 29
use constant OFFSET => 4;
# spent 70µs making 1 call to DateTime::TimeZone::BEGIN@29 # spent 58µs making 1 call to constant::import
30269µs2130µs
# spent 71µs (13+59) within DateTime::TimeZone::BEGIN@30 which was called: # once (13µs+59µs) by DateTime::BEGIN@46 at line 30
use constant IS_DST => 5;
# spent 71µs making 1 call to DateTime::TimeZone::BEGIN@30 # spent 59µs making 1 call to constant::import
3125.28ms2133µs
# spent 73µs (13+60) within DateTime::TimeZone::BEGIN@31 which was called: # once (13µs+60µs) by DateTime::BEGIN@46 at line 31
use constant SHORT_NAME => 6;
# spent 73µs making 1 call to DateTime::TimeZone::BEGIN@31 # spent 60µs making 1 call to constant::import
32
331223µsmy %SpecialName = map { $_ => 1 }
34 qw( EST MST HST CET EET MET WET EST5EDT CST6CDT MST7MDT PST8PDT );
35
36
# spent 121ms (4.07+117) within DateTime::TimeZone::new which was called 6 times, avg 20.2ms/call: # 2 times (3.89ms+-3.89ms) by DateTime::TimeZone::Local::Unix::FromEtcLocaltime at line 61 of DateTime/TimeZone/Local/Unix.pm, avg 0s/call # once (47µs+121ms) by Value::Convertor::BEGIN@153 at line 159 of Value/Convertor.pm # once (58µs+68µs) by Value::Convertor::BEGIN@61 at line 50 of DateTime/Infinite.pm # once (39µs+55µs) by DateTime::_new at line 232 of DateTime.pm # once (33µs+33µs) by Value::Convertor::BEGIN@61 at line 78 of DateTime/Infinite.pm
sub new {
3766µs my $class = shift;
386237µs6130µs my %p = validate(
# spent 130µs making 6 calls to Params::Validate::XS::validate, avg 22µs/call
39 @_,
40 { name => { type => SCALAR } },
41 );
42
43616µs if ( exists $DateTime::TimeZone::Catalog::LINKS{ $p{name} } ) {
4412µs $p{name} = $DateTime::TimeZone::Catalog::LINKS{ $p{name} };
45 }
46 elsif ( exists $DateTime::TimeZone::Catalog::LINKS{ uc $p{name} } ) {
47 $p{name} = $DateTime::TimeZone::Catalog::LINKS{ uc $p{name} };
48 }
49
50646µs612µs unless ( $p{name} =~ m,/,
# spent 12µs making 6 calls to DateTime::TimeZone::CORE:match, avg 2µs/call
51 || $SpecialName{ $p{name} } ) {
5254µs if ( $p{name} eq 'floating' ) {
53229µs254µs return DateTime::TimeZone::Floating->instance;
# spent 54µs making 2 calls to Class::Singleton::instance, avg 27µs/call
54 }
55
5631µs if ( $p{name} eq 'local' ) {
57110µs1121ms return DateTime::TimeZone::Local->TimeZone();
# spent 121ms making 1 call to DateTime::TimeZone::Local::TimeZone
58 }
59
6022µs if ( $p{name} eq 'UTC' || $p{name} eq 'Z' ) {
61117µs136µs return DateTime::TimeZone::UTC->instance;
# spent 36µs making 1 call to Class::Singleton::instance
62 }
63
6417µs194µs return DateTime::TimeZone::OffsetOnly->new( offset => $p{name} );
# spent 94µs making 1 call to DateTime::TimeZone::OffsetOnly::new
65 }
66
6711µs my $subclass = $p{name};
68110µs11µs $subclass =~ s/-/_/g;
# spent 1µs making 1 call to DateTime::TimeZone::CORE:subst
69111µs16µs $subclass =~ s{/}{::}g;
# spent 6µs making 1 call to DateTime::TimeZone::CORE:subst
7012µs my $real_class = "DateTime::TimeZone::$subclass";
71
72110µs16µs die "The timezone '$p{name}' in an invalid name.\n"
# spent 6µs making 1 call to DateTime::TimeZone::CORE:match
73 unless $real_class =~ /^\w+(::\w+)*$/;
74
75112µs13µs unless ( $real_class->can('instance') ) {
# spent 3µs making 1 call to UNIVERSAL::can
7612µs my $e = do {
771600ns local $@;
7815µs local $SIG{__DIE__};
79152µs eval "require $real_class";
# spent 193µs executing statements in string eval
8015µs $@;
81 };
82
831600ns if ($e) {
84 my $regex = join '.', split /::/, $real_class;
85 $regex .= '\\.pm';
86
87 if ( $e =~ /^Can't locate $regex/i ) {
88 die
89 "The timezone '$p{name}' could not be loaded, or is an invalid name.\n";
90 }
91 else {
92 die $e;
93 }
94 }
95 }
96
97116µs1194µs my $zone = $real_class->instance( name => $p{name}, is_olson => 1 );
# spent 194µs making 1 call to Class::Singleton::instance
98
9918µs14µs if ( $zone->is_olson() ) {
# spent 4µs making 1 call to DateTime::TimeZone::is_olson
100110µs24µs my $object_version
# spent 2µs making 1 call to DateTime::TimeZone::Europe::Prague::olson_version # spent 2µs making 1 call to UNIVERSAL::can
101 = $zone->can('olson_version')
102 ? $zone->olson_version()
103 : 'unknown';
10416µs12µs my $catalog_version = DateTime::TimeZone::Catalog->OlsonVersion();
# spent 2µs making 1 call to DateTime::TimeZone::Catalog::OlsonVersion
105
10611µs if ( $object_version ne $catalog_version ) {
107 warn
108 "Loaded $real_class, which is from an older version ($object_version) of the Olson database than this installation of DateTime::TimeZone ($catalog_version).\n";
109 }
110 }
111
11217µs return $zone;
113}
114
115
# spent 158µs (109+49) within DateTime::TimeZone::_init which was called: # once (109µs+49µs) by DateTime::TimeZone::Europe::Prague::_new_instance at line 1091 of DateTime/TimeZone/Europe/Prague.pm
sub _init {
11611µs my $class = shift;
117159µs134µs my %p = validate(
# spent 34µs making 1 call to Params::Validate::XS::validate
118 @_, {
119 name => { type => SCALAR },
120 spans => { type => ARRAYREF },
121 is_olson => { type => BOOLEAN, default => 0 },
122 },
123 );
124
125118µs my $self = bless {
126 name => $p{name},
127 spans => $p{spans},
128 is_olson => $p{is_olson},
129 }, $class;
130
13112µs foreach my $k (qw( last_offset last_observance rules max_year )) {
13245µs my $m = "_$k";
133447µs816µs $self->{$k} = $self->$m() if $self->can($m);
# spent 8µs making 4 calls to UNIVERSAL::can, avg 2µs/call # spent 2µs making 1 call to DateTime::TimeZone::Europe::Prague::_last_offset # spent 2µs making 1 call to DateTime::TimeZone::Europe::Prague::_last_observance # spent 2µs making 1 call to DateTime::TimeZone::Europe::Prague::_rules # spent 2µs making 1 call to DateTime::TimeZone::Europe::Prague::_max_year
134 }
135
13619µs return $self;
137}
138
13917µs
# spent 4µs within DateTime::TimeZone::is_olson which was called: # once (4µs+0s) by DateTime::TimeZone::new at line 99
sub is_olson { $_[0]->{is_olson} }
140
141sub is_dst_for_datetime {
142 my $self = shift;
143
144 my $span = $self->_span_for_datetime( 'utc', $_[0] );
145
146 return $span->[IS_DST];
147}
148
149
# spent 232µs (28+204) within DateTime::TimeZone::offset_for_datetime which was called 3 times, avg 77µs/call: # 3 times (28µs+204µs) by DateTime::offset at line 943 of DateTime.pm, avg 77µs/call
sub offset_for_datetime {
15032µs my $self = shift;
151
152312µs3204µs my $span = $self->_span_for_datetime( 'utc', $_[0] );
# spent 204µs making 3 calls to DateTime::TimeZone::_span_for_datetime, avg 68µs/call
153
154313µs return $span->[OFFSET];
155}
156
157sub offset_for_local_datetime {
158 my $self = shift;
159
160 my $span = $self->_span_for_datetime( 'local', $_[0] );
161
162 return $span->[OFFSET];
163}
164
165sub short_name_for_datetime {
166 my $self = shift;
167
168 my $span = $self->_span_for_datetime( 'utc', $_[0] );
169
170 return $span->[SHORT_NAME];
171}
172
173
# spent 204µs (81+123) within DateTime::TimeZone::_span_for_datetime which was called 3 times, avg 68µs/call: # 3 times (81µs+123µs) by DateTime::TimeZone::offset_for_datetime at line 152, avg 68µs/call
sub _span_for_datetime {
17431µs my $self = shift;
17532µs my $type = shift;
17631µs my $dt = shift;
177
17834µs my $method = $type . '_rd_as_seconds';
179
18033µs my $end = $type eq 'utc' ? UTC_END : LOCAL_END;
181
1823600ns my $span;
183310µs312µs my $seconds = $dt->$method();
# spent 12µs making 3 calls to DateTime::utc_rd_as_seconds, avg 4µs/call
184314µs39µs if ( $seconds < $self->max_span->[$end] ) {
# spent 9µs making 3 calls to DateTime::TimeZone::max_span, avg 3µs/call
185314µs3103µs $span = $self->_spans_binary_search( $type, $seconds );
# spent 103µs making 3 calls to DateTime::TimeZone::_spans_binary_search, avg 34µs/call
186 }
187 else {
188 my $until_year = $dt->utc_year + 1;
189 $span = $self->_generate_spans_until_match( $until_year, $seconds,
190 $type );
191 }
192
193 # This means someone gave a local time that doesn't exist
194 # (like during a transition into savings time)
19532µs unless ( defined $span ) {
196 my $err = 'Invalid local time for date';
197 $err .= ' ' . $dt->iso8601 if $type eq 'utc';
198 $err .= " in time zone: " . $self->name;
199 $err .= "\n";
200
201 die $err;
202 }
203
204313µs return $span;
205}
206
207
# spent 103µs (95+8) within DateTime::TimeZone::_spans_binary_search which was called 3 times, avg 34µs/call: # 3 times (95µs+8µs) by DateTime::TimeZone::_span_for_datetime at line 185, avg 34µs/call
sub _spans_binary_search {
20832µs my $self = shift;
20934µs my ( $type, $seconds ) = @_;
210
21138µs38µs my ( $start, $end ) = _keys_for_type($type);
# spent 8µs making 3 calls to DateTime::TimeZone::_keys_for_type, avg 3µs/call
212
21331µs my $min = 0;
21467µs my $max = scalar @{ $self->{spans} } + 1;
21536µs my $i = int( $max / 2 );
216
217 # special case for when there are only 2 spans
21832µs $i++ if $max % 2 && $max != 3;
219
22064µs $i = 0 if @{ $self->{spans} } == 1;
221
22231µs while (1) {
223128µs my $current = $self->{spans}[$i];
224
2251214µs if ( $seconds < $current->[$start] ) {
2263500ns $max = $i;
22732µs my $c = int( ( $i - $min ) / 2 );
2283500ns $c ||= 1;
229
23031µs $i -= $c;
231
23231µs return if $i < $min;
233 }
234 elsif ( $seconds >= $current->[$end] ) {
23562µs $min = $i;
23667µs my $c = int( ( $max - $i ) / 2 );
23761µs $c ||= 1;
238
23962µs $i += $c;
240
24163µs return if $i >= $max;
242 }
243 else {
244
245 # Special case for overlapping ranges because of DST and
246 # other weirdness (like Alaska's change when bought from
247 # Russia by the US). Always prefer latest span.
24832µs if ( $current->[IS_DST] && $type eq 'local' ) {
249
250 # Asia/Dhaka in 2009j goes into DST without any known
251 # end-of-DST date (wtf, Bangladesh).
252 return $current if $current->[UTC_END] == INFINITY;
253
254 my $next = $self->{spans}[ $i + 1 ];
255
256 # Sometimes we will get here and the span we're
257 # looking at is the last that's been generated so far.
258 # We need to try to generate one more or else we run
259 # out.
260 $next ||= $self->_generate_next_span;
261
262 die "No next span in $self->{max_year}" unless defined $next;
263
264 if ( ( !$next->[IS_DST] )
265 && $next->[$start] <= $seconds
266 && $seconds <= $next->[$end] ) {
267 return $next;
268 }
269 }
270
271317µs return $current;
272 }
273 }
274}
275
276sub _generate_next_span {
277 my $self = shift;
278
279 my $last_idx = $#{ $self->{spans} };
280
281 my $max_span = $self->max_span;
282
283 # Kind of a hack, but AFAIK there are no zones where it takes
284 # _more_ than a year for a _future_ time zone change to occur, so
285 # by looking two years out we can ensure that we will find at
286 # least one more span. Of course, I will no doubt be proved wrong
287 # and this will cause errors.
288 $self->_generate_spans_until_match( $self->{max_year} + 2,
289 $max_span->[UTC_END] + ( 366 * 86400 ), 'utc' );
290
291 return $self->{spans}[ $last_idx + 1 ];
292}
293
294sub _generate_spans_until_match {
295 my $self = shift;
296 my $generate_until_year = shift;
297 my $seconds = shift;
298 my $type = shift;
299
300 my @changes;
301 my @rules = @{ $self->_rules };
302 foreach my $year ( $self->{max_year} .. $generate_until_year ) {
303 for ( my $x = 0; $x < @rules; $x++ ) {
304 my $last_offset_from_std;
305
306 if ( @rules == 2 ) {
307 $last_offset_from_std
308 = $x
309 ? $rules[0]->offset_from_std
310 : $rules[1]->offset_from_std;
311 }
312 elsif ( @rules == 1 ) {
313 $last_offset_from_std = $rules[0]->offset_from_std;
314 }
315 else {
316 my $count = scalar @rules;
317 die
318 "Cannot generate future changes for zone with $count infinite rules\n";
319 }
320
321 my $rule = $rules[$x];
322
323 my $next = $rule->utc_start_datetime_for_year( $year,
324 $self->{last_offset}, $last_offset_from_std );
325
326 # don't bother with changes we've seen already
327 next if $next->utc_rd_as_seconds < $self->max_span->[UTC_END];
328
329 push @changes,
330 DateTime::TimeZone::OlsonDB::Change->new(
331 type => 'rule',
332 utc_start_datetime => $next,
333 local_start_datetime => $next + DateTime::Duration->new(
334 seconds => $self->{last_observance}->total_offset
335 + $rule->offset_from_std
336 ),
337 short_name => sprintf(
338 $self->{last_observance}->format, $rule->letter
339 ),
340 observance => $self->{last_observance},
341 rule => $rule,
342 );
343 }
344 }
345
346 $self->{max_year} = $generate_until_year;
347
348 my @sorted
349 = sort { $a->utc_start_datetime <=> $b->utc_start_datetime } @changes;
350
351 my ( $start, $end ) = _keys_for_type($type);
352
353 my $match;
354 for ( my $x = 1; $x < @sorted; $x++ ) {
355 my $last_total_offset
356 = $x == 1
357 ? $self->max_span->[OFFSET]
358 : $sorted[ $x - 2 ]->total_offset;
359
360 my $span = DateTime::TimeZone::OlsonDB::Change::two_changes_as_span(
361 @sorted[ $x - 1, $x ], $last_total_offset );
362
363 $span = _span_as_array($span);
364
365 push @{ $self->{spans} }, $span;
366
367 $match = $span
368 if $seconds >= $span->[$start] && $seconds < $span->[$end];
369 }
370
371 return $match;
372}
373
374316µs
# spent 9µs within DateTime::TimeZone::max_span which was called 3 times, avg 3µs/call: # 3 times (9µs+0s) by DateTime::TimeZone::_span_for_datetime at line 184, avg 3µs/call
sub max_span { $_[0]->{spans}[-1] }
375
376
# spent 8µs within DateTime::TimeZone::_keys_for_type which was called 3 times, avg 3µs/call: # 3 times (8µs+0s) by DateTime::TimeZone::_spans_binary_search at line 211, avg 3µs/call
sub _keys_for_type {
377316µs $_[0] eq 'utc' ? ( UTC_START, UTC_END ) : ( LOCAL_START, LOCAL_END );
378}
379
380sub _span_as_array {
381 [
382 @{ $_[0] }{
383 qw( utc_start utc_end local_start local_end offset is_dst short_name )
384 }
385 ];
386}
387
388526µs
# spent 9µs within DateTime::TimeZone::is_floating which was called 5 times, avg 2µs/call: # 2 times (4µs+0s) by DateTime::_handle_offset_modifier at line 323 of DateTime.pm, avg 2µs/call # once (2µs+0s) by DateTime::try {...} at line 2008 of DateTime.pm # once (2µs+0s) by DateTime::set_time_zone at line 1998 of DateTime.pm # once (2µs+0s) by DateTime::_calc_local_rd at line 427 of DateTime.pm
sub is_floating {0}
389
39016µs
# spent 2µs within DateTime::TimeZone::is_utc which was called: # once (2µs+0s) by DateTime::_calc_local_rd at line 427 of DateTime.pm
sub is_utc {0}
391
392sub has_dst_changes {0}
393
394sub name { $_[0]->{name} }
395sub category { ( split /\//, $_[0]->{name}, 2 )[0] }
396
397sub is_valid_name {
398 my $tz;
399 {
400 local $@;
401 local $SIG{__DIE__};
402 $tz = eval { $_[0]->new( name => $_[1] ) };
403 }
404
405 return $tz && $tz->isa('DateTime::TimeZone') ? 1 : 0;
406}
407
408sub STORABLE_freeze {
409 my $self = shift;
410
411 return $self->name;
412}
413
414sub STORABLE_thaw {
415 my $self = shift;
416 my $cloning = shift;
417 my $serialized = shift;
418
419 my $class = ref $self || $self;
420
421 my $obj;
422 if ( $class->isa(__PACKAGE__) ) {
423 $obj = __PACKAGE__->new( name => $serialized );
424 }
425 else {
426 $obj = $class->new( name => $serialized );
427 }
428
429 %$self = %$obj;
430
431 return $self;
432}
433
434#
435# Functions
436#
437
# spent 46µs (36+10) within DateTime::TimeZone::offset_as_seconds which was called: # once (36µs+10µs) by DateTime::TimeZone::OffsetOnly::new at line 25 of DateTime/TimeZone/OffsetOnly.pm
sub offset_as_seconds {
438 {
43922µs local $@;
44016µs local $SIG{__DIE__};
441217µs12µs shift if eval { $_[0]->isa('DateTime::TimeZone') };
# spent 2µs making 1 call to UNIVERSAL::isa
442 }
443
4441900ns my $offset = shift;
445
4461500ns return undef unless defined $offset;
447
4481500ns return 0 if $offset eq '0';
449
4501500ns my ( $sign, $hours, $minutes, $seconds );
451115µs27µs if ( $offset =~ /^([\+\-])?(\d\d?):(\d\d)(?::(\d\d))?$/ ) {
# spent 7µs making 2 calls to DateTime::TimeZone::CORE:match, avg 4µs/call
452 ( $sign, $hours, $minutes, $seconds ) = ( $1, $2, $3, $4 );
453 }
454 elsif ( $offset =~ /^([\+\-])?(\d\d)(\d\d)(\d\d)?$/ ) {
455 ( $sign, $hours, $minutes, $seconds ) = ( $1, $2, $3, $4 );
456 }
457 else {
45817µs return undef;
459 }
460
461 $sign = '+' unless defined $sign;
462 return undef unless $hours >= 0 && $hours <= 99;
463 return undef unless $minutes >= 0 && $minutes <= 59;
464 return undef
465 unless !defined($seconds) || ( $seconds >= 0 && $seconds <= 59 );
466
467 my $total = $hours * 3600 + $minutes * 60;
468 $total += $seconds if $seconds;
469 $total *= -1 if $sign eq '-';
470
471 return $total;
472}
473
474sub offset_as_string {
475 {
476 local $@;
477 local $SIG{__DIE__};
478 shift if eval { $_[0]->isa('DateTime::TimeZone') };
479 }
480
481 my $offset = shift;
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
553112µs1;
554
555# ABSTRACT: Time zone object base class and factory
556
557__END__
 
# spent 25µs within DateTime::TimeZone::CORE:match which was called 9 times, avg 3µs/call: # 6 times (12µs+0s) by DateTime::TimeZone::new at line 50, avg 2µs/call # 2 times (7µs+0s) by DateTime::TimeZone::offset_as_seconds at line 451, avg 4µs/call # once (6µs+0s) by DateTime::TimeZone::new at line 72
sub DateTime::TimeZone::CORE:match; # opcode
# spent 7µs within DateTime::TimeZone::CORE:subst which was called 2 times, avg 4µs/call: # once (6µs+0s) by DateTime::TimeZone::new at line 69 # once (1µs+0s) by DateTime::TimeZone::new at line 68
sub DateTime::TimeZone::CORE:subst; # opcode