← Index
NYTProf Performance Profile   « block view • line view • sub view »
For mentat.storage.mongo.pl
  Run on Tue Jun 24 10:04:38 2014
Reported on Tue Jun 24 10:05:25 2014

Filename/usr/local/share/perl/5.14.2/DateTime/TimeZone.pm
StatementsExecuted 298 statements in 3.74ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1112.75ms2.83msDateTime::TimeZone::::BEGIN@14DateTime::TimeZone::BEGIN@14
6541.83ms57.7msDateTime::TimeZone::::newDateTime::TimeZone::new (recurses: max depth 1, inclusive time 8.23ms)
111473µs8.20msDateTime::TimeZone::::BEGIN@16DateTime::TimeZone::BEGIN@16
111410µs2.05msDateTime::TimeZone::::BEGIN@15DateTime::TimeZone::BEGIN@15
11149µs71µsDateTime::TimeZone::::_initDateTime::TimeZone::_init
31140µs43µsDateTime::TimeZone::::_spans_binary_searchDateTime::TimeZone::_spans_binary_search
31137µs89µsDateTime::TimeZone::::_span_for_datetimeDateTime::TimeZone::_span_for_datetime
11119µs23µsDateTime::TimeZone::::BEGIN@11DateTime::TimeZone::BEGIN@11
11117µs22µsDateTime::TimeZone::::offset_as_secondsDateTime::TimeZone::offset_as_seconds
11114µs76µsDateTime::TimeZone::::BEGIN@19DateTime::TimeZone::BEGIN@19
31112µs101µsDateTime::TimeZone::::offset_for_datetimeDateTime::TimeZone::offset_for_datetime
11112µs12µsDateTime::TimeZone::::BEGIN@9DateTime::TimeZone::BEGIN@9
93111µs11µsDateTime::TimeZone::::CORE:matchDateTime::TimeZone::CORE:match (opcode)
1119µs9µsDateTime::TimeZone::::BEGIN@5DateTime::TimeZone::BEGIN@5
1118µs8µsDateTime::TimeZone::::BEGIN@17DateTime::TimeZone::BEGIN@17
1118µs40µsDateTime::TimeZone::::BEGIN@21DateTime::TimeZone::BEGIN@21
1117µs17µsDateTime::TimeZone::::BEGIN@12DateTime::TimeZone::BEGIN@12
1116µs41µsDateTime::TimeZone::::BEGIN@25DateTime::TimeZone::BEGIN@25
1116µs33µsDateTime::TimeZone::::BEGIN@22DateTime::TimeZone::BEGIN@22
1116µs6µsDateTime::TimeZone::::BEGIN@18DateTime::TimeZone::BEGIN@18
1116µs31µsDateTime::TimeZone::::BEGIN@27DateTime::TimeZone::BEGIN@27
1116µs32µsDateTime::TimeZone::::BEGIN@26DateTime::TimeZone::BEGIN@26
1116µs31µsDateTime::TimeZone::::BEGIN@30DateTime::TimeZone::BEGIN@30
1115µs31µsDateTime::TimeZone::::BEGIN@31DateTime::TimeZone::BEGIN@31
1115µs30µsDateTime::TimeZone::::BEGIN@28DateTime::TimeZone::BEGIN@28
1115µs30µsDateTime::TimeZone::::BEGIN@29DateTime::TimeZone::BEGIN@29
5414µs4µsDateTime::TimeZone::::is_floatingDateTime::TimeZone::is_floating
3114µs4µsDateTime::TimeZone::::max_spanDateTime::TimeZone::max_span
3113µs3µsDateTime::TimeZone::::_keys_for_typeDateTime::TimeZone::_keys_for_type
2213µs3µsDateTime::TimeZone::::CORE:substDateTime::TimeZone::CORE:subst (opcode)
1112µs2µsDateTime::TimeZone::::is_olsonDateTime::TimeZone::is_olson
1111µs1µ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{
321µs $DateTime::TimeZone::VERSION = '1.63';
4}
5
# spent 9µs within DateTime::TimeZone::BEGIN@5 which was called: # once (9µs+0s) by DateTime::BEGIN@46 at line 7
BEGIN {
615µs $DateTime::TimeZone::AUTHORITY = 'cpan:DROLSKY';
7131µs19µs}
# spent 9µs making 1 call to DateTime::TimeZone::BEGIN@5
8
9251µs112µs
# spent 12µs within DateTime::TimeZone::BEGIN@9 which was called: # once (12µs+0s) by DateTime::BEGIN@46 at line 9
use 5.006;
# spent 12µs making 1 call to DateTime::TimeZone::BEGIN@9
10
11221µs226µs
# spent 23µs (19+4) within DateTime::TimeZone::BEGIN@11 which was called: # once (19µs+4µs) by DateTime::BEGIN@46 at line 11
use strict;
# spent 23µs making 1 call to DateTime::TimeZone::BEGIN@11 # spent 4µs making 1 call to strict::import
12223µs226µs
# spent 17µs (7+10) within DateTime::TimeZone::BEGIN@12 which was called: # once (7µs+10µs) by DateTime::BEGIN@46 at line 12
use warnings;
# spent 17µs making 1 call to DateTime::TimeZone::BEGIN@12 # spent 10µs making 1 call to warnings::import
13
142120µs12.83ms
# spent 2.83ms (2.75+82µs) within DateTime::TimeZone::BEGIN@14 which was called: # once (2.75ms+82µs) by DateTime::BEGIN@46 at line 14
use DateTime::TimeZone::Catalog;
# spent 2.83ms making 1 call to DateTime::TimeZone::BEGIN@14
152240µs12.05ms
# spent 2.05ms (410µs+1.64) within DateTime::TimeZone::BEGIN@15 which was called: # once (410µs+1.64ms) by DateTime::BEGIN@46 at line 15
use DateTime::TimeZone::Floating;
# spent 2.05ms making 1 call to DateTime::TimeZone::BEGIN@15
162110µs18.20ms
# spent 8.20ms (473µs+7.73) within DateTime::TimeZone::BEGIN@16 which was called: # once (473µs+7.73ms) by DateTime::BEGIN@46 at line 16
use DateTime::TimeZone::Local;
# spent 8.20ms making 1 call to DateTime::TimeZone::BEGIN@16
17226µs18µs
# spent 8µs within DateTime::TimeZone::BEGIN@17 which was called: # once (8µs+0s) by DateTime::BEGIN@46 at line 17
use DateTime::TimeZone::OffsetOnly;
# spent 8µs making 1 call to DateTime::TimeZone::BEGIN@17
18232µs16µs
# spent 6µs within DateTime::TimeZone::BEGIN@18 which was called: # once (6µs+0s) by DateTime::BEGIN@46 at line 18
use DateTime::TimeZone::UTC;
# spent 6µs making 1 call to DateTime::TimeZone::BEGIN@18
19376µs3137µs
# spent 76µs (14+61) within DateTime::TimeZone::BEGIN@19 which was called: # once (14µs+61µs) by DateTime::BEGIN@46 at line 19
use Params::Validate 0.72 qw( validate validate_pos SCALAR ARRAYREF BOOLEAN );
# spent 76µs making 1 call to DateTime::TimeZone::BEGIN@19 # spent 49µs making 1 call to Exporter::import # spent 12µs making 1 call to UNIVERSAL::VERSION
20
21233µs272µs
# spent 40µs (8+32) within DateTime::TimeZone::BEGIN@21 which was called: # once (8µs+32µs) by DateTime::BEGIN@46 at line 21
use constant INFINITY => 100**1000;
# spent 40µs making 1 call to DateTime::TimeZone::BEGIN@21 # spent 32µs making 1 call to constant::import
22226µs260µs
# spent 33µs (6+27) within DateTime::TimeZone::BEGIN@22 which was called: # once (6µs+27µs) by DateTime::BEGIN@46 at line 22
use constant NEG_INFINITY => -1 * ( 100**1000 );
# spent 33µs making 1 call to DateTime::TimeZone::BEGIN@22 # spent 27µs making 1 call to constant::import
23
24# the offsets for each span element
25226µs277µs
# spent 41µs (6+35) within DateTime::TimeZone::BEGIN@25 which was called: # once (6µs+35µs) by DateTime::BEGIN@46 at line 25
use constant UTC_START => 0;
# spent 41µs making 1 call to DateTime::TimeZone::BEGIN@25 # spent 35µs making 1 call to constant::import
26224µs258µs
# spent 32µs (6+26) within DateTime::TimeZone::BEGIN@26 which was called: # once (6µs+26µs) by DateTime::BEGIN@46 at line 26
use constant UTC_END => 1;
# spent 32µs making 1 call to DateTime::TimeZone::BEGIN@26 # spent 26µs making 1 call to constant::import
27224µs257µs
# spent 31µs (6+25) within DateTime::TimeZone::BEGIN@27 which was called: # once (6µs+25µs) by DateTime::BEGIN@46 at line 27
use constant LOCAL_START => 2;
# spent 31µs making 1 call to DateTime::TimeZone::BEGIN@27 # spent 25µs making 1 call to constant::import
28223µs256µs
# spent 30µs (5+25) within DateTime::TimeZone::BEGIN@28 which was called: # once (5µs+25µs) by DateTime::BEGIN@46 at line 28
use constant LOCAL_END => 3;
# spent 30µs making 1 call to DateTime::TimeZone::BEGIN@28 # spent 25µs making 1 call to constant::import
29226µs256µs
# spent 30µs (5+25) within DateTime::TimeZone::BEGIN@29 which was called: # once (5µs+25µs) by DateTime::BEGIN@46 at line 29
use constant OFFSET => 4;
# spent 30µs making 1 call to DateTime::TimeZone::BEGIN@29 # spent 25µs making 1 call to constant::import
30230µs257µs
# spent 31µs (6+25) within DateTime::TimeZone::BEGIN@30 which was called: # once (6µs+25µs) by DateTime::BEGIN@46 at line 30
use constant IS_DST => 5;
# spent 31µs making 1 call to DateTime::TimeZone::BEGIN@30 # spent 26µs making 1 call to constant::import
3122.33ms257µs
# spent 31µs (5+26) within DateTime::TimeZone::BEGIN@31 which was called: # once (5µs+26µs) by DateTime::BEGIN@46 at line 31
use constant SHORT_NAME => 6;
# spent 31µs making 1 call to DateTime::TimeZone::BEGIN@31 # spent 26µs making 1 call to constant::import
32
331210µsmy %SpecialName = map { $_ => 1 }
34 qw( EST MST HST CET EET MET WET EST5EDT CST6CDT MST7MDT PST8PDT );
35
36
# spent 57.7ms (1.83+55.9) within DateTime::TimeZone::new which was called 6 times, avg 9.61ms/call: # 2 times (1.75ms+-1.75ms) by DateTime::TimeZone::Local::Unix::FromEtcLocaltime at line 61 of DateTime/TimeZone/Local/Unix.pm, avg 0s/call # once (20µs+57.5ms) by Value::Convertor::BEGIN@153 at line 159 of Value/Convertor.pm # once (26µs+29µs) by Value::Convertor::BEGIN@61 at line 50 of DateTime/Infinite.pm # once (17µs+26µs) by DateTime::_new at line 232 of DateTime.pm # once (14µs+15µs) by Value::Convertor::BEGIN@61 at line 78 of DateTime/Infinite.pm
sub new {
3762µs my $class = shift;
386104µs657µs my %p = validate(
# spent 57µs making 6 calls to Params::Validate::XS::validate, avg 10µs/call
39 @_,
40 { name => { type => SCALAR } },
41 );
42
4367µs if ( exists $DateTime::TimeZone::Catalog::LINKS{ $p{name} } ) {
4411µ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
50620µs66µs unless ( $p{name} =~ m,/,
# spent 6µs making 6 calls to DateTime::TimeZone::CORE:match, avg 917ns/call
51 || $SpecialName{ $p{name} } ) {
5252µs if ( $p{name} eq 'floating' ) {
53213µs224µs return DateTime::TimeZone::Floating->instance;
# spent 24µs making 2 calls to Class::Singleton::instance, avg 12µs/call
54 }
55
563800ns if ( $p{name} eq 'local' ) {
5714µs157.5ms return DateTime::TimeZone::Local->TimeZone();
# spent 57.5ms making 1 call to DateTime::TimeZone::Local::TimeZone
58 }
59
602500ns if ( $p{name} eq 'UTC' || $p{name} eq 'Z' ) {
6117µs118µs return DateTime::TimeZone::UTC->instance;
# spent 18µs making 1 call to Class::Singleton::instance
62 }
63
6414µs145µs return DateTime::TimeZone::OffsetOnly->new( offset => $p{name} );
# spent 45µs making 1 call to DateTime::TimeZone::OffsetOnly::new
65 }
66
671500ns my $subclass = $p{name};
6814µs1400ns $subclass =~ s/-/_/g;
# spent 400ns making 1 call to DateTime::TimeZone::CORE:subst
6915µs13µs $subclass =~ s{/}{::}g;
# spent 3µs making 1 call to DateTime::TimeZone::CORE:subst
701700ns my $real_class = "DateTime::TimeZone::$subclass";
71
7214µs12µs die "The timezone '$p{name}' in an invalid name.\n"
# spent 2µs making 1 call to DateTime::TimeZone::CORE:match
73 unless $real_class =~ /^\w+(::\w+)*$/;
74
7516µs11µs unless ( $real_class->can('instance') ) {
# spent 1µs making 1 call to UNIVERSAL::can
761500ns my $e = do {
771100ns local $@;
7812µs local $SIG{__DIE__};
79126µs eval "require $real_class";
# spent 96µs executing statements in string eval
8012µs $@;
81 };
82
831300ns 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
9718µs187µs my $zone = $real_class->instance( name => $p{name}, is_olson => 1 );
# spent 87µs making 1 call to Class::Singleton::instance
98
9914µs12µs if ( $zone->is_olson() ) {
# spent 2µs making 1 call to DateTime::TimeZone::is_olson
10014µs22µs my $object_version
# spent 800ns making 1 call to DateTime::TimeZone::Europe::Prague::olson_version # spent 800ns making 1 call to UNIVERSAL::can
101 = $zone->can('olson_version')
102 ? $zone->olson_version()
103 : 'unknown';
10413µs11µs my $catalog_version = DateTime::TimeZone::Catalog->OlsonVersion();
# spent 1µs making 1 call to DateTime::TimeZone::Catalog::OlsonVersion
105
1061600ns 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
11213µs return $zone;
113}
114
115
# spent 71µs (49+22) within DateTime::TimeZone::_init which was called: # once (49µs+22µs) by DateTime::TimeZone::Europe::Prague::_new_instance at line 1091 of DateTime/TimeZone/Europe/Prague.pm
sub _init {
1161400ns my $class = shift;
117127µs115µs my %p = validate(
# spent 15µ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
12518µs my $self = bless {
126 name => $p{name},
127 spans => $p{spans},
128 is_olson => $p{is_olson},
129 }, $class;
130
13111µs foreach my $k (qw( last_offset last_observance rules max_year )) {
13242µs my $m = "_$k";
133421µs87µs $self->{$k} = $self->$m() if $self->can($m);
# spent 4µs making 4 calls to UNIVERSAL::can, avg 875ns/call # spent 1µs making 1 call to DateTime::TimeZone::Europe::Prague::_last_offset # spent 800ns making 1 call to DateTime::TimeZone::Europe::Prague::_last_observance # spent 800ns making 1 call to DateTime::TimeZone::Europe::Prague::_max_year # spent 700ns making 1 call to DateTime::TimeZone::Europe::Prague::_rules
134 }
135
13614µs return $self;
137}
138
13913µs
# spent 2µs within DateTime::TimeZone::is_olson which was called: # once (2µ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 101µs (12+89) within DateTime::TimeZone::offset_for_datetime which was called 3 times, avg 34µs/call: # 3 times (12µs+89µs) by DateTime::offset at line 943 of DateTime.pm, avg 34µs/call
sub offset_for_datetime {
1503800ns my $self = shift;
151
15236µs389µs my $span = $self->_span_for_datetime( 'utc', $_[0] );
# spent 89µs making 3 calls to DateTime::TimeZone::_span_for_datetime, avg 30µs/call
153
15436µ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 89µs (37+52) within DateTime::TimeZone::_span_for_datetime which was called 3 times, avg 30µs/call: # 3 times (37µs+52µs) by DateTime::TimeZone::offset_for_datetime at line 152, avg 30µs/call
sub _span_for_datetime {
17432µs my $self = shift;
1753700ns my $type = shift;
1763400ns my $dt = shift;
177
17832µs my $method = $type . '_rd_as_seconds';
179
18031µs my $end = $type eq 'utc' ? UTC_END : LOCAL_END;
181
1823300ns my $span;
18334µs35µs my $seconds = $dt->$method();
# spent 5µs making 3 calls to DateTime::utc_rd_as_seconds, avg 2µs/call
18436µs34µs if ( $seconds < $self->max_span->[$end] ) {
# spent 4µs making 3 calls to DateTime::TimeZone::max_span, avg 1µs/call
18536µs343µs $span = $self->_spans_binary_search( $type, $seconds );
# spent 43µs making 3 calls to DateTime::TimeZone::_spans_binary_search, avg 14µ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)
1953500ns 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
20436µs return $span;
205}
206
207
# spent 43µs (40+3) within DateTime::TimeZone::_spans_binary_search which was called 3 times, avg 14µs/call: # 3 times (40µs+3µs) by DateTime::TimeZone::_span_for_datetime at line 185, avg 14µs/call
sub _spans_binary_search {
2083700ns my $self = shift;
20932µs my ( $type, $seconds ) = @_;
210
21133µs33µs my ( $start, $end ) = _keys_for_type($type);
# spent 3µs making 3 calls to DateTime::TimeZone::_keys_for_type, avg 1µs/call
212
2133400ns my $min = 0;
21463µs my $max = scalar @{ $self->{spans} } + 1;
21532µs my $i = int( $max / 2 );
216
217 # special case for when there are only 2 spans
2183900ns $i++ if $max % 2 && $max != 3;
219
22062µs $i = 0 if @{ $self->{spans} } == 1;
221
2223400ns while (1) {
223123µs my $current = $self->{spans}[$i];
224
225125µs if ( $seconds < $current->[$start] ) {
2263300ns $max = $i;
22731µs my $c = int( ( $i - $min ) / 2 );
2283200ns $c ||= 1;
229
2303400ns $i -= $c;
231
2323400ns return if $i < $min;
233 }
234 elsif ( $seconds >= $current->[$end] ) {
2356800ns $min = $i;
23663µs my $c = int( ( $max - $i ) / 2 );
2376500ns $c ||= 1;
238
2396700ns $i += $c;
240
24161µ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.
2483900ns 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
27137µ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
37437µs
# spent 4µs within DateTime::TimeZone::max_span which was called 3 times, avg 1µs/call: # 3 times (4µs+0s) by DateTime::TimeZone::_span_for_datetime at line 184, avg 1µs/call
sub max_span { $_[0]->{spans}[-1] }
375
376
# spent 3µs within DateTime::TimeZone::_keys_for_type which was called 3 times, avg 1µs/call: # 3 times (3µs+0s) by DateTime::TimeZone::_spans_binary_search at line 211, avg 1µs/call
sub _keys_for_type {
37737µ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
388511µs
# spent 4µs within DateTime::TimeZone::is_floating which was called 5 times, avg 840ns/call: # 2 times (2µs+0s) by DateTime::_handle_offset_modifier at line 323 of DateTime.pm, avg 1µs/call # once (800ns+0s) by DateTime::try {...} at line 2008 of DateTime.pm # once (700ns+0s) by DateTime::set_time_zone at line 1998 of DateTime.pm # once (700ns+0s) by DateTime::_calc_local_rd at line 427 of DateTime.pm
sub is_floating {0}
389
39013µs
# spent 1µs within DateTime::TimeZone::is_utc which was called: # once (1µ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 22µs (17+4) within DateTime::TimeZone::offset_as_seconds which was called: # once (17µs+4µs) by DateTime::TimeZone::OffsetOnly::new at line 25 of DateTime/TimeZone/OffsetOnly.pm
sub offset_as_seconds {
438 {
4392500ns local $@;
44013µs local $SIG{__DIE__};
44128µs1900ns shift if eval { $_[0]->isa('DateTime::TimeZone') };
# spent 900ns making 1 call to UNIVERSAL::isa
442 }
443
4441400ns my $offset = shift;
445
4461400ns return undef unless defined $offset;
447
4481200ns return 0 if $offset eq '0';
449
4501300ns my ( $sign, $hours, $minutes, $seconds );
45118µs24µs if ( $offset =~ /^([\+\-])?(\d\d?):(\d\d)(?::(\d\d))?$/ ) {
# spent 4µs making 2 calls to DateTime::TimeZone::CORE:match, avg 2µ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 {
45813µ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
55315µs1;
554
555# ABSTRACT: Time zone object base class and factory
556
557__END__
 
# spent 11µs within DateTime::TimeZone::CORE:match which was called 9 times, avg 1µs/call: # 6 times (6µs+0s) by DateTime::TimeZone::new at line 50, avg 917ns/call # 2 times (4µs+0s) by DateTime::TimeZone::offset_as_seconds at line 451, avg 2µs/call # once (2µs+0s) by DateTime::TimeZone::new at line 72
sub DateTime::TimeZone::CORE:match; # opcode
# spent 3µs within DateTime::TimeZone::CORE:subst which was called 2 times, avg 2µs/call: # once (3µs+0s) by DateTime::TimeZone::new at line 69 # once (400ns+0s) by DateTime::TimeZone::new at line 68
sub DateTime::TimeZone::CORE:subst; # opcode