← Index
NYTProf Performance Profile   « line view »
For svc/members/upsert
  Run on Tue Jan 13 11:50:22 2015
Reported on Tue Jan 13 12:09:48 2015

Filename/usr/lib/x86_64-linux-gnu/perl5/5.20/DateTime/Duration.pm
StatementsExecuted 19 statements in 2.18ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
111724µs759µsDateTime::Duration::::BEGIN@8DateTime::Duration::BEGIN@8
11115µs19µsDateTime::Duration::::BEGIN@4DateTime::Duration::BEGIN@4
11111µs38µsDateTime::Duration::::BEGIN@9DateTime::Duration::BEGIN@9
11111µs21µsDateTime::Duration::::BEGIN@3DateTime::Duration::BEGIN@3
1118µs51µsDateTime::Duration::::BEGIN@11DateTime::Duration::BEGIN@11
1118µs48µsDateTime::Duration::::BEGIN@20DateTime::Duration::BEGIN@20
1117µs7µsDateTime::Duration::::BEGIN@7DateTime::Duration::BEGIN@7
1113µs3µsDateTime::Duration::::BEGIN@6DateTime::Duration::BEGIN@6
0000s0sDateTime::Duration::::_add_overloadDateTime::Duration::_add_overload
0000s0sDateTime::Duration::::_compare_overloadDateTime::Duration::_compare_overload
0000s0sDateTime::Duration::::_has_negativeDateTime::Duration::_has_negative
0000s0sDateTime::Duration::::_has_positiveDateTime::Duration::_has_positive
0000s0sDateTime::Duration::::_multiply_overloadDateTime::Duration::_multiply_overload
0000s0sDateTime::Duration::::_normalize_nanosecondsDateTime::Duration::_normalize_nanoseconds
0000s0sDateTime::Duration::::_subtract_overloadDateTime::Duration::_subtract_overload
0000s0sDateTime::Duration::::addDateTime::Duration::add
0000s0sDateTime::Duration::::add_durationDateTime::Duration::add_duration
0000s0sDateTime::Duration::::calendar_durationDateTime::Duration::calendar_duration
0000s0sDateTime::Duration::::clock_durationDateTime::Duration::clock_duration
0000s0sDateTime::Duration::::cloneDateTime::Duration::clone
0000s0sDateTime::Duration::::compareDateTime::Duration::compare
0000s0sDateTime::Duration::::daysDateTime::Duration::days
0000s0sDateTime::Duration::::delta_daysDateTime::Duration::delta_days
0000s0sDateTime::Duration::::delta_minutesDateTime::Duration::delta_minutes
0000s0sDateTime::Duration::::delta_monthsDateTime::Duration::delta_months
0000s0sDateTime::Duration::::delta_nanosecondsDateTime::Duration::delta_nanoseconds
0000s0sDateTime::Duration::::delta_secondsDateTime::Duration::delta_seconds
0000s0sDateTime::Duration::::deltasDateTime::Duration::deltas
0000s0sDateTime::Duration::::end_of_month_modeDateTime::Duration::end_of_month_mode
0000s0sDateTime::Duration::::hoursDateTime::Duration::hours
0000s0sDateTime::Duration::::in_unitsDateTime::Duration::in_units
0000s0sDateTime::Duration::::inverseDateTime::Duration::inverse
0000s0sDateTime::Duration::::is_limit_modeDateTime::Duration::is_limit_mode
0000s0sDateTime::Duration::::is_negativeDateTime::Duration::is_negative
0000s0sDateTime::Duration::::is_positiveDateTime::Duration::is_positive
0000s0sDateTime::Duration::::is_preserve_modeDateTime::Duration::is_preserve_mode
0000s0sDateTime::Duration::::is_wrap_modeDateTime::Duration::is_wrap_mode
0000s0sDateTime::Duration::::is_zeroDateTime::Duration::is_zero
0000s0sDateTime::Duration::::minutesDateTime::Duration::minutes
0000s0sDateTime::Duration::::monthsDateTime::Duration::months
0000s0sDateTime::Duration::::multiplyDateTime::Duration::multiply
0000s0sDateTime::Duration::::nanosecondsDateTime::Duration::nanoseconds
0000s0sDateTime::Duration::::newDateTime::Duration::new
0000s0sDateTime::Duration::::secondsDateTime::Duration::seconds
0000s0sDateTime::Duration::::subtractDateTime::Duration::subtract
0000s0sDateTime::Duration::::subtract_durationDateTime::Duration::subtract_duration
0000s0sDateTime::Duration::::weeksDateTime::Duration::weeks
0000s0sDateTime::Duration::::yearsDateTime::Duration::years
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package DateTime::Duration;
21400ns$DateTime::Duration::VERSION = '1.12';
3221µs232µs
# spent 21µs (11+11) within DateTime::Duration::BEGIN@3 which was called: # once (11µs+11µs) by DateTime::BEGIN@12 at line 3
use strict;
# spent 21µs making 1 call to DateTime::Duration::BEGIN@3 # spent 11µs making 1 call to strict::import
4219µs224µs
# spent 19µs (15+4) within DateTime::Duration::BEGIN@4 which was called: # once (15µs+4µs) by DateTime::BEGIN@12 at line 4
use warnings;
# spent 19µs making 1 call to DateTime::Duration::BEGIN@4 # spent 4µs making 1 call to warnings::import
5
6217µs13µs
# spent 3µs within DateTime::Duration::BEGIN@6 which was called: # once (3µs+0s) by DateTime::BEGIN@12 at line 6
use Carp ();
# spent 3µs making 1 call to DateTime::Duration::BEGIN@6
7221µs17µs
# spent 7µs within DateTime::Duration::BEGIN@7 which was called: # once (7µs+0s) by DateTime::BEGIN@12 at line 7
use DateTime;
# spent 7µs making 1 call to DateTime::Duration::BEGIN@7
82635µs1759µs
# spent 759µs (724+35) within DateTime::Duration::BEGIN@8 which was called: # once (724µs+35µs) by DateTime::BEGIN@12 at line 8
use DateTime::Helpers;
# spent 759µs making 1 call to DateTime::Duration::BEGIN@8
9239µs265µs
# spent 38µs (11+27) within DateTime::Duration::BEGIN@9 which was called: # once (11µs+27µs) by DateTime::BEGIN@12 at line 9
use Params::Validate qw( validate SCALAR );
# spent 38µs making 1 call to DateTime::Duration::BEGIN@9 # spent 27µs making 1 call to Exporter::import
10
11
# spent 51µs (8+42) within DateTime::Duration::BEGIN@11 which was called: # once (8µs+42µs) by DateTime::BEGIN@12 at line 18
use overload (
1216µs142µs fallback => 1,
# spent 42µs making 1 call to overload::import
13 '+' => '_add_overload',
14 '-' => '_subtract_overload',
15 '*' => '_multiply_overload',
16 '<=>' => '_compare_overload',
17 'cmp' => '_compare_overload',
18120µs151µs);
# spent 51µs making 1 call to DateTime::Duration::BEGIN@11
19
2021.39ms288µs
# spent 48µs (8+40) within DateTime::Duration::BEGIN@20 which was called: # once (8µs+40µs) by DateTime::BEGIN@12 at line 20
use constant MAX_NANOSECONDS => 1_000_000_000; # 1E9 = almost 32 bits
# spent 48µs making 1 call to DateTime::Duration::BEGIN@20 # spent 40µs making 1 call to constant::import
21
22114µsmy @all_units = qw( months days minutes seconds nanoseconds );
23
24# XXX - need to reject non-integers but accept infinity, NaN, &
25# 1.56e+18
26sub new {
27 my $class = shift;
28 my %p = validate(
29 @_, {
30 years => { type => SCALAR, default => 0 },
31 months => { type => SCALAR, default => 0 },
32 weeks => { type => SCALAR, default => 0 },
33 days => { type => SCALAR, default => 0 },
34 hours => { type => SCALAR, default => 0 },
35 minutes => { type => SCALAR, default => 0 },
36 seconds => { type => SCALAR, default => 0 },
37 nanoseconds => { type => SCALAR, default => 0 },
38 end_of_month => {
39 type => SCALAR, default => undef,
40 regex => qr/^(?:wrap|limit|preserve)$/
41 },
42 }
43 );
44
45 my $self = bless {}, $class;
46
47 $self->{months} = ( $p{years} * 12 ) + $p{months};
48
49 $self->{days} = ( $p{weeks} * 7 ) + $p{days};
50
51 $self->{minutes} = ( $p{hours} * 60 ) + $p{minutes};
52
53 $self->{seconds} = $p{seconds};
54
55 if ( $p{nanoseconds} ) {
56 $self->{nanoseconds} = $p{nanoseconds};
57 $self->_normalize_nanoseconds;
58 }
59 else {
60
61 # shortcut - if they don't need nanoseconds
62 $self->{nanoseconds} = 0;
63 }
64
65 $self->{end_of_month} = (
66 defined $p{end_of_month} ? $p{end_of_month}
67 : $self->{months} < 0 ? 'preserve'
68 : 'wrap'
69 );
70
71 return $self;
72}
73
74# make the signs of seconds, nanos the same; 0 < abs(nanos) < MAX_NANOS
75# NB this requires nanoseconds != 0 (callers check this already)
76sub _normalize_nanoseconds {
77 my $self = shift;
78
79 return
80 if ( $self->{nanoseconds} == DateTime::INFINITY()
81 || $self->{nanoseconds} == DateTime::NEG_INFINITY()
82 || $self->{nanoseconds} eq DateTime::NAN() );
83
84 my $seconds = $self->{seconds} + $self->{nanoseconds} / MAX_NANOSECONDS;
85 $self->{seconds} = int($seconds);
86 $self->{nanoseconds} = $self->{nanoseconds} % MAX_NANOSECONDS;
87 $self->{nanoseconds} -= MAX_NANOSECONDS if $seconds < 0;
88}
89
90sub clone { bless { %{ $_[0] } }, ref $_[0] }
91
92sub years { abs( $_[0]->in_units('years') ) }
93sub months { abs( $_[0]->in_units( 'months', 'years' ) ) }
94sub weeks { abs( $_[0]->in_units('weeks') ) }
95sub days { abs( $_[0]->in_units( 'days', 'weeks' ) ) }
96sub hours { abs( $_[0]->in_units('hours') ) }
97sub minutes { abs( $_[0]->in_units( 'minutes', 'hours' ) ) }
98sub seconds { abs( $_[0]->in_units('seconds') ) }
99sub nanoseconds { abs( $_[0]->in_units( 'nanoseconds', 'seconds' ) ) }
100
101sub is_positive { $_[0]->_has_positive && !$_[0]->_has_negative }
102sub is_negative { !$_[0]->_has_positive && $_[0]->_has_negative }
103
104sub _has_positive {
105 ( grep { $_ > 0 } @{ $_[0] }{@all_units} ) ? 1 : 0;
106}
107
108sub _has_negative {
109 ( grep { $_ < 0 } @{ $_[0] }{@all_units} ) ? 1 : 0;
110}
111
112sub is_zero {
113 return 0 if grep { $_ != 0 } @{ $_[0] }{@all_units};
114 return 1;
115}
116
117sub delta_months { $_[0]->{months} }
118sub delta_days { $_[0]->{days} }
119sub delta_minutes { $_[0]->{minutes} }
120sub delta_seconds { $_[0]->{seconds} }
121sub delta_nanoseconds { $_[0]->{nanoseconds} }
122
123sub deltas {
124 map { $_ => $_[0]->{$_} } @all_units;
125}
126
127sub in_units {
128 my $self = shift;
129 my @units = @_;
130
131 my %units = map { $_ => 1 } @units;
132
133 my %ret;
134
135 my ( $months, $days, $minutes, $seconds )
136 = @{$self}{qw( months days minutes seconds )};
137
138 if ( $units{years} ) {
139 $ret{years} = int( $months / 12 );
140 $months -= $ret{years} * 12;
141 }
142
143 if ( $units{months} ) {
144 $ret{months} = $months;
145 }
146
147 if ( $units{weeks} ) {
148 $ret{weeks} = int( $days / 7 );
149 $days -= $ret{weeks} * 7;
150 }
151
152 if ( $units{days} ) {
153 $ret{days} = $days;
154 }
155
156 if ( $units{hours} ) {
157 $ret{hours} = int( $minutes / 60 );
158 $minutes -= $ret{hours} * 60;
159 }
160
161 if ( $units{minutes} ) {
162 $ret{minutes} = $minutes;
163 }
164
165 if ( $units{seconds} ) {
166 $ret{seconds} = $seconds;
167 $seconds = 0;
168 }
169
170 if ( $units{nanoseconds} ) {
171 $ret{nanoseconds} = $seconds * MAX_NANOSECONDS + $self->{nanoseconds};
172 }
173
174 wantarray ? @ret{@units} : $ret{ $units[0] };
175}
176
177sub is_wrap_mode { $_[0]->{end_of_month} eq 'wrap' ? 1 : 0 }
178sub is_limit_mode { $_[0]->{end_of_month} eq 'limit' ? 1 : 0 }
179sub is_preserve_mode { $_[0]->{end_of_month} eq 'preserve' ? 1 : 0 }
180
181sub end_of_month_mode { $_[0]->{end_of_month} }
182
183sub calendar_duration {
184 my $self = shift;
185
186 return ( ref $self )
187 ->new( map { $_ => $self->{$_} } qw( months days end_of_month ) );
188}
189
190sub clock_duration {
191 my $self = shift;
192
193 return ( ref $self )
194 ->new( map { $_ => $self->{$_} }
195 qw( minutes seconds nanoseconds end_of_month ) );
196}
197
198sub inverse {
199 my $self = shift;
200 my %p = @_;
201
202 my %new;
203 foreach my $u (@all_units) {
204 $new{$u} = $self->{$u};
205
206 # avoid -0 bug
207 $new{$u} *= -1 if $new{$u};
208 }
209
210 $new{end_of_month} = $p{end_of_month}
211 if exists $p{end_of_month};
212
213 return ( ref $self )->new(%new);
214}
215
216sub add_duration {
217 my ( $self, $dur ) = @_;
218
219 foreach my $u (@all_units) {
220 $self->{$u} += $dur->{$u};
221 }
222
223 $self->_normalize_nanoseconds if $self->{nanoseconds};
224
225 return $self;
226}
227
228sub add {
229 my $self = shift;
230
231 return $self->add_duration( ( ref $self )->new(@_) );
232}
233
234sub subtract_duration { return $_[0]->add_duration( $_[1]->inverse ) }
235
236sub subtract {
237 my $self = shift;
238
239 return $self->subtract_duration( ( ref $self )->new(@_) );
240}
241
242sub multiply {
243 my $self = shift;
244 my $multiplier = shift;
245
246 foreach my $u (@all_units) {
247 $self->{$u} *= $multiplier;
248 }
249
250 $self->_normalize_nanoseconds if $self->{nanoseconds};
251
252 return $self;
253}
254
255sub compare {
256 my ( $class, $dur1, $dur2, $dt ) = @_;
257
258 $dt ||= DateTime->now;
259
260 return DateTime->compare( $dt->clone->add_duration($dur1),
261 $dt->clone->add_duration($dur2) );
262}
263
264sub _add_overload {
265 my ( $d1, $d2, $rev ) = @_;
266
267 ( $d1, $d2 ) = ( $d2, $d1 ) if $rev;
268
269 if ( DateTime::Helpers::isa( $d2, 'DateTime' ) ) {
270 $d2->add_duration($d1);
271 return;
272 }
273
274 # will also work if $d1 is a DateTime.pm object
275 return $d1->clone->add_duration($d2);
276}
277
278sub _subtract_overload {
279 my ( $d1, $d2, $rev ) = @_;
280
281 ( $d1, $d2 ) = ( $d2, $d1 ) if $rev;
282
283 Carp::croak(
284 "Cannot subtract a DateTime object from a DateTime::Duration object")
285 if DateTime::Helpers::isa( $d2, 'DateTime' );
286
287 return $d1->clone->subtract_duration($d2);
288}
289
290sub _multiply_overload {
291 my $self = shift;
292
293 my $new = $self->clone;
294
295 return $new->multiply(@_);
296}
297
298sub _compare_overload {
299 Carp::croak( 'DateTime::Duration does not overload comparison.'
300 . ' See the documentation on the compare() method for details.'
301 );
302}
303
30413µs1;
305
306# ABSTRACT: Duration objects for date math
307
308__END__