Profile of /usr/local/lib/perl5/site_perl/5.10.1/darwin-2level/DateTime/Duration.pm

← Index
NYTProf Performance Profile «block view•line view•sub view»
For 05.Domain_and_Item.t
Run on Tue May 4 17:21:41 2010
Reported on Tue May 4 17:22:27 2010

File | /usr/local/lib/perl5/site_perl/5.10.1/darwin-2level/DateTime/Duration.pm
Statements Executed | 27
Statement Execution Time | 1.37ms

Subroutines — ordered by exclusive time
Calls | P | F | Exclusive Time | Inclusive Time | Subroutine
--- | --- | --- | --- | --- | ---
1 | 1 | 1 | 15µs | 18µs | DateTime::Duration::::BEGIN@3DateTime::Duration::BEGIN@3
1 | 1 | 1 | 11µs | 43µs | DateTime::Duration::::BEGIN@11DateTime::Duration::BEGIN@11
1 | 1 | 1 | 8µs | 74µs | DateTime::Duration::::BEGIN@13DateTime::Duration::BEGIN@13
1 | 1 | 1 | 7µs | 16µs | DateTime::Duration::::BEGIN@4DateTime::Duration::BEGIN@4
1 | 1 | 1 | 7µs | 37µs | DateTime::Duration::::BEGIN@22DateTime::Duration::BEGIN@22
1 | 1 | 1 | 6µs | 6µs | DateTime::Duration::::BEGIN@9DateTime::Duration::BEGIN@9
1 | 1 | 1 | 4µs | 4µs | DateTime::Duration::::BEGIN@10DateTime::Duration::BEGIN@10
1 | 1 | 1 | 3µs | 3µs | DateTime::Duration::::BEGIN@8DateTime::Duration::BEGIN@8
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::_add_overloadDateTime::Duration::_add_overload
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::_compare_overloadDateTime::Duration::_compare_overload
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::_has_negativeDateTime::Duration::_has_negative
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::_has_positiveDateTime::Duration::_has_positive
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::_multiply_overloadDateTime::Duration::_multiply_overload
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::_normalize_nanosecondsDateTime::Duration::_normalize_nanoseconds
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::_subtract_overloadDateTime::Duration::_subtract_overload
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::addDateTime::Duration::add
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::add_durationDateTime::Duration::add_duration
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::calendar_durationDateTime::Duration::calendar_duration
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::clock_durationDateTime::Duration::clock_duration
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::cloneDateTime::Duration::clone
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::compareDateTime::Duration::compare
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::daysDateTime::Duration::days
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::delta_daysDateTime::Duration::delta_days
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::delta_minutesDateTime::Duration::delta_minutes
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::delta_monthsDateTime::Duration::delta_months
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::delta_nanosecondsDateTime::Duration::delta_nanoseconds
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::delta_secondsDateTime::Duration::delta_seconds
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::deltasDateTime::Duration::deltas
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::end_of_month_modeDateTime::Duration::end_of_month_mode
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::hoursDateTime::Duration::hours
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::in_unitsDateTime::Duration::in_units
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::inverseDateTime::Duration::inverse
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::is_limit_modeDateTime::Duration::is_limit_mode
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::is_negativeDateTime::Duration::is_negative
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::is_positiveDateTime::Duration::is_positive
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::is_preserve_modeDateTime::Duration::is_preserve_mode
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::is_wrap_modeDateTime::Duration::is_wrap_mode
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::is_zeroDateTime::Duration::is_zero
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::minutesDateTime::Duration::minutes
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::monthsDateTime::Duration::months
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::multiplyDateTime::Duration::multiply
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::nanosecondsDateTime::Duration::nanoseconds
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::newDateTime::Duration::new
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::secondsDateTime::Duration::seconds
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::subtractDateTime::Duration::subtract
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::subtract_durationDateTime::Duration::subtract_duration
0 | 0 | 0 | 0s | 0s | DateTime::Duration::::weeksDateTime::Duration::weeks
0 | 0 | 0 | 0s | 0s | DateTime::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
--- | --- | --- | --- | --- | ---
1 |  |  |  |  | package DateTime::Duration;
2 |  |  |  |  |
3 | 3 | 21µs | 2 | 21µs | # spent 18µs (15+3) within DateTime::Duration::BEGIN@3 which was called # once (15µs+3µs) by DateTime::BEGIN@40 at line 3 use strict; # spent 18µs making 1 call to DateTime::Duration::BEGIN@3 # spent 3µs making 1 call to strict::import
4 | 3 | 27µs | 2 | 25µs | # spent 16µs (7+9) within DateTime::Duration::BEGIN@4 which was called # once (7µs+9µs) by DateTime::BEGIN@40 at line 4 use warnings; # spent 16µs making 1 call to DateTime::Duration::BEGIN@4 # spent 9µs making 1 call to warnings::import
5 |  |  |  |  |
6 | 1 | 800ns |  |  | our $VERSION = '0.55';
7 |  |  |  |  |
8 | 3 | 17µs | 1 | 3µs | # spent 3µs within DateTime::Duration::BEGIN@8 which was called # once (3µs+0s) by DateTime::BEGIN@40 at line 8 use Carp (); # spent 3µs making 1 call to DateTime::Duration::BEGIN@8
9 | 3 | 21µs | 1 | 6µs | # spent 6µs within DateTime::Duration::BEGIN@9 which was called # once (6µs+0s) by DateTime::BEGIN@40 at line 9 use DateTime; # spent 6µs making 1 call to DateTime::Duration::BEGIN@9
10 | 3 | 20µs | 1 | 4µs | # spent 4µs within DateTime::Duration::BEGIN@10 which was called # once (4µs+0s) by DateTime::BEGIN@40 at line 10 use DateTime::Helpers; # spent 4µs making 1 call to DateTime::Duration::BEGIN@10
11 | 3 | 36µs | 2 | 76µs | # spent 43µs (11+32) within DateTime::Duration::BEGIN@11 which was called # once (11µs+32µs) by DateTime::BEGIN@40 at line 11 use Params::Validate qw( validate SCALAR ); # spent 43µs making 1 call to DateTime::Duration::BEGIN@11 # spent 32µs making 1 call to Exporter::import
12 |  |  |  |  |
13 |  |  |  |  | # spent 74µs (8+66) within DateTime::Duration::BEGIN@13 which was called # once (8µs+66µs) by DateTime::BEGIN@40 at line 20 use overload (
14 |  |  |  |  | fallback => 1, # spent 66µs making 1 call to overload::import
15 |  |  |  |  | '+' => '_add_overload',
16 |  |  |  |  | '-' => '_subtract_overload',
17 |  |  |  |  | '*' => '_multiply_overload',
18 |  |  |  |  | '<=>' => '_compare_overload',
19 |  |  |  |  | 'cmp' => '_compare_overload',
20 | 3 | 27µs | 1 | 74µs | ); # spent 74µs making 1 call to DateTime::Duration::BEGIN@13
21 |  |  |  |  |
22 | 3 | 1.19ms | 2 | 67µs | # spent 37µs (7+30) within DateTime::Duration::BEGIN@22 which was called # once (7µs+30µs) by DateTime::BEGIN@40 at line 22 use constant MAX_NANOSECONDS => 1_000_000_000; # 1E9 = almost 32 bits # spent 37µs making 1 call to DateTime::Duration::BEGIN@22 # spent 30µs making 1 call to constant::import
23 |  |  |  |  |
24 | 1 | 2µs |  |  | my @all_units = qw( months days minutes seconds nanoseconds );
25 |  |  |  |  |
26 |  |  |  |  | # XXX - need to reject non-integers but accept infinity, NaN, &
27 |  |  |  |  | # 1.56e+18
28 |  |  |  |  | sub new {
29 |  |  |  |  | my $class = shift;
30 |  |  |  |  | my %p = validate(
31 |  |  |  |  | @_, {
32 |  |  |  |  | years => { type => SCALAR, default => 0 },
33 |  |  |  |  | months => { type => SCALAR, default => 0 },
34 |  |  |  |  | weeks => { type => SCALAR, default => 0 },
35 |  |  |  |  | days => { type => SCALAR, default => 0 },
36 |  |  |  |  | hours => { type => SCALAR, default => 0 },
37 |  |  |  |  | minutes => { type => SCALAR, default => 0 },
38 |  |  |  |  | seconds => { type => SCALAR, default => 0 },
39 |  |  |  |  | nanoseconds => { type => SCALAR, default => 0 },
40 |  |  |  |  | end_of_month => {
41 |  |  |  |  | type => SCALAR, default => undef,
42 |  |  |  |  | regex => qr/^(?:wrap|limit|preserve)$/
43 |  |  |  |  | },
44 |  |  |  |  | }
45 |  |  |  |  | );
46 |  |  |  |  |
47 |  |  |  |  | my $self = bless {}, $class;
48 |  |  |  |  |
49 |  |  |  |  | $self->{months} = ( $p{years} * 12 ) + $p{months};
50 |  |  |  |  |
51 |  |  |  |  | $self->{days} = ( $p{weeks} * 7 ) + $p{days};
52 |  |  |  |  |
53 |  |  |  |  | $self->{minutes} = ( $p{hours} * 60 ) + $p{minutes};
54 |  |  |  |  |
55 |  |  |  |  | $self->{seconds} = $p{seconds};
56 |  |  |  |  |
57 |  |  |  |  | if ( $p{nanoseconds} ) {
58 |  |  |  |  | $self->{nanoseconds} = $p{nanoseconds};
59 |  |  |  |  | $self->_normalize_nanoseconds;
60 |  |  |  |  | }
61 |  |  |  |  | else {
62 |  |  |  |  |
63 |  |  |  |  | # shortcut - if they don't need nanoseconds
64 |  |  |  |  | $self->{nanoseconds} = 0;
65 |  |  |  |  | }
66 |  |  |  |  |
67 |  |  |  |  | $self->{end_of_month} = (
68 |  |  |  |  | defined $p{end_of_month} ? $p{end_of_month}
69 |  |  |  |  | : $self->{months} < 0 ? 'preserve'
70 |  |  |  |  | : 'wrap'
71 |  |  |  |  | );
72 |  |  |  |  |
73 |  |  |  |  | return $self;
74 |  |  |  |  | }
75 |  |  |  |  |
76 |  |  |  |  | # make the signs of seconds, nanos the same; 0 < abs(nanos) < MAX_NANOS
77 |  |  |  |  | # NB this requires nanoseconds != 0 (callers check this already)
78 |  |  |  |  | sub _normalize_nanoseconds {
79 |  |  |  |  | my $self = shift;
80 |  |  |  |  |
81 |  |  |  |  | return
82 |  |  |  |  | if ( $self->{nanoseconds} == DateTime::INFINITY()
83 |  |  |  |  | || $self->{nanoseconds} == DateTime::NEG_INFINITY()
84 |  |  |  |  | || $self->{nanoseconds} eq DateTime::NAN() );
85 |  |  |  |  |
86 |  |  |  |  | my $seconds = $self->{seconds} + $self->{nanoseconds} / MAX_NANOSECONDS;
87 |  |  |  |  | $self->{seconds} = int($seconds);
88 |  |  |  |  | $self->{nanoseconds} = $self->{nanoseconds} % MAX_NANOSECONDS;
89 |  |  |  |  | $self->{nanoseconds} -= MAX_NANOSECONDS if $seconds < 0;
90 |  |  |  |  | }
91 |  |  |  |  |
92 |  |  |  |  | sub clone { bless { %{ $_[0] } }, ref $_[0] }
93 |  |  |  |  |
94 |  |  |  |  | sub years { abs( $_[0]->in_units('years') ) }
95 |  |  |  |  | sub months { abs( $_[0]->in_units( 'months', 'years' ) ) }
96 |  |  |  |  | sub weeks { abs( $_[0]->in_units('weeks') ) }
97 |  |  |  |  | sub days { abs( $_[0]->in_units( 'days', 'weeks' ) ) }
98 |  |  |  |  | sub hours { abs( $_[0]->in_units('hours') ) }
99 |  |  |  |  | sub minutes { abs( $_[0]->in_units( 'minutes', 'hours' ) ) }
100 |  |  |  |  | sub seconds { abs( $_[0]->in_units('seconds') ) }
101 |  |  |  |  | sub nanoseconds { abs( $_[0]->in_units( 'nanoseconds', 'seconds' ) ) }
102 |  |  |  |  |
103 |  |  |  |  | sub is_positive { $_[0]->_has_positive && !$_[0]->_has_negative }
104 |  |  |  |  | sub is_negative { !$_[0]->_has_positive && $_[0]->_has_negative }
105 |  |  |  |  |
106 |  |  |  |  | sub _has_positive {
107 |  |  |  |  | ( grep { $_ > 0 } @{ $_[0] }{@all_units} ) ? 1 : 0;
108 |  |  |  |  | }
109 |  |  |  |  |
110 |  |  |  |  | sub _has_negative {
111 |  |  |  |  | ( grep { $_ < 0 } @{ $_[0] }{@all_units} ) ? 1 : 0;
112 |  |  |  |  | }
113 |  |  |  |  |
114 |  |  |  |  | sub is_zero {
115 |  |  |  |  | return 0 if grep { $_ != 0 } @{ $_[0] }{@all_units};
116 |  |  |  |  | return 1;
117 |  |  |  |  | }
118 |  |  |  |  |
119 |  |  |  |  | sub delta_months { $_[0]->{months} }
120 |  |  |  |  | sub delta_days { $_[0]->{days} }
121 |  |  |  |  | sub delta_minutes { $_[0]->{minutes} }
122 |  |  |  |  | sub delta_seconds { $_[0]->{seconds} }
123 |  |  |  |  | sub delta_nanoseconds { $_[0]->{nanoseconds} }
124 |  |  |  |  |
125 |  |  |  |  | sub deltas {
126 |  |  |  |  | map { $_ => $_[0]->{$_} } @all_units;
127 |  |  |  |  | }
128 |  |  |  |  |
129 |  |  |  |  | sub in_units {
130 |  |  |  |  | my $self = shift;
131 |  |  |  |  | my @units = @_;
132 |  |  |  |  |
133 |  |  |  |  | my %units = map { $_ => 1 } @units;
134 |  |  |  |  |
135 |  |  |  |  | my %ret;
136 |  |  |  |  |
137 |  |  |  |  | my ( $months, $days, $minutes, $seconds )
138 |  |  |  |  | = @{$self}{qw( months days minutes seconds )};
139 |  |  |  |  |
140 |  |  |  |  | if ( $units{years} ) {
141 |  |  |  |  | $ret{years} = int( $months / 12 );
142 |  |  |  |  | $months -= $ret{years} * 12;
143 |  |  |  |  | }
144 |  |  |  |  |
145 |  |  |  |  | if ( $units{months} ) {
146 |  |  |  |  | $ret{months} = $months;
147 |  |  |  |  | }
148 |  |  |  |  |
149 |  |  |  |  | if ( $units{weeks} ) {
150 |  |  |  |  | $ret{weeks} = int( $days / 7 );
151 |  |  |  |  | $days -= $ret{weeks} * 7;
152 |  |  |  |  | }
153 |  |  |  |  |
154 |  |  |  |  | if ( $units{days} ) {
155 |  |  |  |  | $ret{days} = $days;
156 |  |  |  |  | }
157 |  |  |  |  |
158 |  |  |  |  | if ( $units{hours} ) {
159 |  |  |  |  | $ret{hours} = int( $minutes / 60 );
160 |  |  |  |  | $minutes -= $ret{hours} * 60;
161 |  |  |  |  | }
162 |  |  |  |  |
163 |  |  |  |  | if ( $units{minutes} ) {
164 |  |  |  |  | $ret{minutes} = $minutes;
165 |  |  |  |  | }
166 |  |  |  |  |
167 |  |  |  |  | if ( $units{seconds} ) {
168 |  |  |  |  | $ret{seconds} = $seconds;
169 |  |  |  |  | $seconds = 0;
170 |  |  |  |  | }
171 |  |  |  |  |
172 |  |  |  |  | if ( $units{nanoseconds} ) {
173 |  |  |  |  | $ret{nanoseconds} = $seconds * MAX_NANOSECONDS + $self->{nanoseconds};
174 |  |  |  |  | }
175 |  |  |  |  |
176 |  |  |  |  | wantarray ? @ret{@units} : $ret{ $units[0] };
177 |  |  |  |  | }
178 |  |  |  |  |
179 |  |  |  |  | sub is_wrap_mode { $_[0]->{end_of_month} eq 'wrap' ? 1 : 0 }
180 |  |  |  |  | sub is_limit_mode { $_[0]->{end_of_month} eq 'limit' ? 1 : 0 }
181 |  |  |  |  | sub is_preserve_mode { $_[0]->{end_of_month} eq 'preserve' ? 1 : 0 }
182 |  |  |  |  |
183 |  |  |  |  | sub end_of_month_mode { $_[0]->{end_of_month} }
184 |  |  |  |  |
185 |  |  |  |  | sub calendar_duration {
186 |  |  |  |  | my $self = shift;
187 |  |  |  |  |
188 |  |  |  |  | return ( ref $self )
189 |  |  |  |  | ->new( map { $_ => $self->{$_} } qw( months days end_of_month ) );
190 |  |  |  |  | }
191 |  |  |  |  |
192 |  |  |  |  | sub clock_duration {
193 |  |  |  |  | my $self = shift;
194 |  |  |  |  |
195 |  |  |  |  | return ( ref $self )
196 |  |  |  |  | ->new( map { $_ => $self->{$_} }
197 |  |  |  |  | qw( minutes seconds nanoseconds end_of_month ) );
198 |  |  |  |  | }
199 |  |  |  |  |
200 |  |  |  |  | sub inverse {
201 |  |  |  |  | my $self = shift;
202 |  |  |  |  | my %p = @_;
203 |  |  |  |  |
204 |  |  |  |  | my %new;
205 |  |  |  |  | foreach my $u (@all_units) {
206 |  |  |  |  | $new{$u} = $self->{$u};
207 |  |  |  |  |
208 |  |  |  |  | # avoid -0 bug
209 |  |  |  |  | $new{$u} *= -1 if $new{$u};
210 |  |  |  |  | }
211 |  |  |  |  |
212 |  |  |  |  | $new{end_of_month} = $p{end_of_month}
213 |  |  |  |  | if exists $p{end_of_month};
214 |  |  |  |  |
215 |  |  |  |  | return ( ref $self )->new(%new);
216 |  |  |  |  | }
217 |  |  |  |  |
218 |  |  |  |  | sub add_duration {
219 |  |  |  |  | my ( $self, $dur ) = @_;
220 |  |  |  |  |
221 |  |  |  |  | foreach my $u (@all_units) {
222 |  |  |  |  | $self->{$u} += $dur->{$u};
223 |  |  |  |  | }
224 |  |  |  |  |
225 |  |  |  |  | $self->_normalize_nanoseconds if $self->{nanoseconds};
226 |  |  |  |  |
227 |  |  |  |  | return $self;
228 |  |  |  |  | }
229 |  |  |  |  |
230 |  |  |  |  | sub add {
231 |  |  |  |  | my $self = shift;
232 |  |  |  |  |
233 |  |  |  |  | return $self->add_duration( ( ref $self )->new(@_) );
234 |  |  |  |  | }
235 |  |  |  |  |
236 |  |  |  |  | sub subtract_duration { return $_[0]->add_duration( $_[1]->inverse ) }
237 |  |  |  |  |
238 |  |  |  |  | sub subtract {
239 |  |  |  |  | my $self = shift;
240 |  |  |  |  |
241 |  |  |  |  | return $self->subtract_duration( ( ref $self )->new(@_) );
242 |  |  |  |  | }
243 |  |  |  |  |
244 |  |  |  |  | sub multiply {
245 |  |  |  |  | my $self = shift;
246 |  |  |  |  | my $multiplier = shift;
247 |  |  |  |  |
248 |  |  |  |  | foreach my $u (@all_units) {
249 |  |  |  |  | $self->{$u} *= $multiplier;
250 |  |  |  |  | }
251 |  |  |  |  |
252 |  |  |  |  | $self->_normalize_nanoseconds if $self->{nanoseconds};
253 |  |  |  |  |
254 |  |  |  |  | return $self;
255 |  |  |  |  | }
256 |  |  |  |  |
257 |  |  |  |  | sub compare {
258 |  |  |  |  | my ( $class, $dur1, $dur2, $dt ) = @_;
259 |  |  |  |  |
260 |  |  |  |  | $dt ||= DateTime->now;
261 |  |  |  |  |
262 |  |  |  |  | return DateTime->compare( $dt->clone->add_duration($dur1),
263 |  |  |  |  | $dt->clone->add_duration($dur2) );
264 |  |  |  |  | }
265 |  |  |  |  |
266 |  |  |  |  | sub _add_overload {
267 |  |  |  |  | my ( $d1, $d2, $rev ) = @_;
268 |  |  |  |  |
269 |  |  |  |  | ( $d1, $d2 ) = ( $d2, $d1 ) if $rev;
270 |  |  |  |  |
271 |  |  |  |  | if ( DateTime::Helpers::isa( $d2, 'DateTime' ) ) {
272 |  |  |  |  | $d2->add_duration($d1);
273 |  |  |  |  | return;
274 |  |  |  |  | }
275 |  |  |  |  |
276 |  |  |  |  | # will also work if $d1 is a DateTime.pm object
277 |  |  |  |  | return $d1->clone->add_duration($d2);
278 |  |  |  |  | }
279 |  |  |  |  |
280 |  |  |  |  | sub _subtract_overload {
281 |  |  |  |  | my ( $d1, $d2, $rev ) = @_;
282 |  |  |  |  |
283 |  |  |  |  | ( $d1, $d2 ) = ( $d2, $d1 ) if $rev;
284 |  |  |  |  |
285 |  |  |  |  | Carp::croak(
286 |  |  |  |  | "Cannot subtract a DateTime object from a DateTime::Duration object")
287 |  |  |  |  | if DateTime::Helpers::isa( $d2, 'DateTime' );
288 |  |  |  |  |
289 |  |  |  |  | return $d1->clone->subtract_duration($d2);
290 |  |  |  |  | }
291 |  |  |  |  |
292 |  |  |  |  | sub _multiply_overload {
293 |  |  |  |  | my $self = shift;
294 |  |  |  |  |
295 |  |  |  |  | my $new = $self->clone;
296 |  |  |  |  |
297 |  |  |  |  | return $new->multiply(@_);
298 |  |  |  |  | }
299 |  |  |  |  |
300 |  |  |  |  | sub _compare_overload {
301 |  |  |  |  | Carp::croak( 'DateTime::Duration does not overload comparison.'
302 |  |  |  |  | . ' See the documentation on the compare() method for details.'
303 |  |  |  |  | );
304 |  |  |  |  | }
305 |  |  |  |  |
306 | 1 | 5µs |  |  | 1;
307 |  |  |  |  |
308 |  |  |  |  | __END__
309 |  |  |  |  |
310 |  |  |  |  | =head1 NAME
311 |  |  |  |  |
312 |  |  |  |  | DateTime::Duration - Duration objects for date math
313 |  |  |  |  |
314 |  |  |  |  | =head1 SYNOPSIS
315 |  |  |  |  |
316 |  |  |  |  | use DateTime::Duration;
317 |  |  |  |  |
318 |  |  |  |  | $d = DateTime::Duration->new( years => 3,
319 |  |  |  |  | months => 5,
320 |  |  |  |  | weeks => 1,
321 |  |  |  |  | days => 1,
322 |  |  |  |  | hours => 6,
323 |  |  |  |  | minutes => 15,
324 |  |  |  |  | seconds => 45,
325 |  |  |  |  | nanoseconds => 12000 );
326 |  |  |  |  |
327 |  |  |  |  | # Convert to different units
328 |  |  |  |  | $d->in_units('days', 'hours', 'seconds');
329 |  |  |  |  |
330 |  |  |  |  | # The important parts for date math
331 |  |  |  |  | $d->delta_months
332 |  |  |  |  | $d->delta_days
333 |  |  |  |  | $d->delta_minutes
334 |  |  |  |  | $d->delta_seconds
335 |  |  |  |  | $d->delta_nanoseconds
336 |  |  |  |  |
337 |  |  |  |  | my %deltas = $d->deltas
338 |  |  |  |  |
339 |  |  |  |  | $d->is_wrap_mode
340 |  |  |  |  | $d->is_limit_mode
341 |  |  |  |  | $d->is_preserve_mode
342 |  |  |  |  |
343 |  |  |  |  | print $d->end_of_month_mode;
344 |  |  |  |  |
345 |  |  |  |  | # Multiple all deltas by -1
346 |  |  |  |  | my $opposite = $d->inverse;
347 |  |  |  |  |
348 |  |  |  |  | my $bigger = $dur1 + $dur2;
349 |  |  |  |  | my $smaller = $dur1 - $dur2; # the result could be negative
350 |  |  |  |  | my $bigger = $dur1 * 3;
351 |  |  |  |  |
352 |  |  |  |  | my $base_dt = DateTime->new( year => 2000 );
353 |  |  |  |  | my @sorted =
354 |  |  |  |  | sort { DateTime::Duration->compare( $a, $b, $base_dt ) } @durations;
355 |  |  |  |  |
356 |  |  |  |  | # Human-readable accessors, always positive, but use
357 |  |  |  |  | # DateTime::Format::Duration instead
358 |  |  |  |  | $d->years;
359 |  |  |  |  | $d->months;
360 |  |  |  |  | $d->weeks;
361 |  |  |  |  | $d->days;
362 |  |  |  |  | $d->hours;
363 |  |  |  |  | $d->minutes;
364 |  |  |  |  | $d->seconds;
365 |  |  |  |  | $d->nanoseconds;
366 |  |  |  |  |
367 |  |  |  |  | if ( $d->is_positive ) { ... }
368 |  |  |  |  | if ( $d->is_zero ) { ... }
369 |  |  |  |  | if ( $d->is_negative ) { ... }
370 |  |  |  |  |
371 |  |  |  |  | =head1 DESCRIPTION
372 |  |  |  |  |
373 |  |  |  |  | This is a simple class for representing duration objects. These
374 |  |  |  |  | objects are used whenever you do date math with DateTime.pm.
375 |  |  |  |  |
376 |  |  |  |  | See the L<How Date Math is Done|DateTime/"How Date Math is Done">
377 |  |  |  |  | section of the DateTime.pm documentation for more details. The short
378 |  |  |  |  | course: One cannot in general convert between seconds, minutes, days,
379 |  |  |  |  | and months, so this class will never do so. Instead, create the
380 |  |  |  |  | duration with the desired units to begin with, for example by calling
381 |  |  |  |  | the appropriate subtraction/delta method on a C<DateTime.pm> object.
382 |  |  |  |  |
383 |  |  |  |  | =head1 METHODS
384 |  |  |  |  |
385 |  |  |  |  | Like C<DateTime> itself, C<DateTime::Duration> returns the object from
386 |  |  |  |  | mutator methods in order to make method chaining possible.
387 |  |  |  |  |
388 |  |  |  |  | C<DateTime::Duration> has the following methods:
389 |  |  |  |  |
390 |  |  |  |  | =over 4
391 |  |  |  |  |
392 |  |  |  |  | =item * new( ... )
393 |  |  |  |  |
394 |  |  |  |  | This method takes the parameters "years", "months", "weeks", "days",
395 |  |  |  |  | "hours", "minutes", "seconds", "nanoseconds", and "end_of_month". All
396 |  |  |  |  | of these except "end_of_month" are numbers. If any of the numbers are
397 |  |  |  |  | negative, the entire duration is negative.
398 |  |  |  |  |
399 |  |  |  |  | All of the numbers B<must be integers>.
400 |  |  |  |  |
401 |  |  |  |  | Internally, years as just treated as 12 months. Similarly, weeks are
402 |  |  |  |  | treated as 7 days, and hours are converted to minutes. Seconds and
403 |  |  |  |  | nanoseconds are both treated separately.
404 |  |  |  |  |
405 |  |  |  |  | The "end_of_month" parameter must be either "wrap", "limit", or
406 |  |  |  |  | "preserve". This parameter specifies how date math that crosses the
407 |  |  |  |  | end of a month is handled.
408 |  |  |  |  |
409 |  |  |  |  | In "wrap" mode, adding months or years that result in days beyond the
410 |  |  |  |  | end of the new month will roll over into the following month. For
411 |  |  |  |  | instance, adding one year to Feb 29 will result in Mar 1.
412 |  |  |  |  |
413 |  |  |  |  | If you specify "end_of_month" mode as "limit", the end of the month is
414 |  |  |  |  | never crossed. Thus, adding one year to Feb 29, 2000 will result in
415 |  |  |  |  | Feb 28, 2001. If you were to then add three more years this will
416 |  |  |  |  | result in Feb 28, 2004.
417 |  |  |  |  |
418 |  |  |  |  | If you specify "end_of_month" mode as "preserve", the same calculation
419 |  |  |  |  | is done as for "limit" except that if the original date is at the end
420 |  |  |  |  | of the month the new date will also be. For instance, adding one
421 |  |  |  |  | month to Feb 29, 2000 will result in Mar 31, 2000.
422 |  |  |  |  |
423 |  |  |  |  | For positive durations, the "end_of_month" parameter defaults to wrap.
424 |  |  |  |  | For negative durations, the default is "limit". This should match how
425 |  |  |  |  | most people "intuitively" expect datetime math to work.
426 |  |  |  |  |
427 |  |  |  |  | =item * clone
428 |  |  |  |  |
429 |  |  |  |  | Returns a new object with the same properties as the object on which
430 |  |  |  |  | this method was called.
431 |  |  |  |  |
432 |  |  |  |  | =item * in_units( ... )
433 |  |  |  |  |
434 |  |  |  |  | Returns the length of the duration in the units (any of those that can
435 |  |  |  |  | be passed to L<new>) given as arguments. All lengths are integral,
436 |  |  |  |  | but may be negative. Smaller units are computed from what remains
437 |  |  |  |  | after taking away the larger units given, so for example:
438 |  |  |  |  |
439 |  |  |  |  | my $dur = DateTime::Duration->new( years => 1, months => 15 );
440 |  |  |  |  |
441 |  |  |  |  | $dur->in_units( 'years' ); # 2
442 |  |  |  |  | $dur->in_units( 'months' ); # 27
443 |  |  |  |  | $dur->in_units( 'years', 'months' ); # (2, 3)
444 |  |  |  |  | $dur->in_units( 'weeks', 'days' ); # (0, 0) !
445 |  |  |  |  |
446 |  |  |  |  |
447 |  |  |  |  | The last example demonstrates that there will not be any conversion
448 |  |  |  |  | between units which don't have a fixed conversion rate. The only
449 |  |  |  |  | conversions possible are:
450 |  |  |  |  |
451 |  |  |  |  | =over 8
452 |  |  |  |  |
453 |  |  |  |  | =item * years <=> months
454 |  |  |  |  |
455 |  |  |  |  | =item * weeks <=> days
456 |  |  |  |  |
457 |  |  |  |  | =item * hours <=> minutes
458 |  |  |  |  |
459 |  |  |  |  | =item * seconds <=> nanoseconds
460 |  |  |  |  |
461 |  |  |  |  | =back
462 |  |  |  |  |
463 |  |  |  |  | For the explanation of why this happens, please see the L<How Date
464 |  |  |  |  | Math is Done|DateTime/"How Date Math is Done"> section of the
465 |  |  |  |  | DateTime.pm documentation
466 |  |  |  |  |
467 |  |  |  |  | Note that the numbers returned by this method may not match the values
468 |  |  |  |  | given to the constructor.
469 |  |  |  |  |
470 |  |  |  |  | In list context, in_units returns the lengths in the order of the units
471 |  |  |  |  | given. In scalar context, it returns the length in the first unit (but
472 |  |  |  |  | still computes in terms of all given units).
473 |  |  |  |  |
474 |  |  |  |  | If you need more flexibility in presenting information about
475 |  |  |  |  | durations, please take a look a C<DateTime::Format::Duration>.
476 |  |  |  |  |
477 |  |  |  |  | =item * delta_months, delta_days, delta_minutes, delta_seconds, delta_nanoseconds
478 |  |  |  |  |
479 |  |  |  |  | These methods provide the information C<DateTime.pm> needs for doing
480 |  |  |  |  | date math. The numbers returned may be positive or negative.
481 |  |  |  |  |
482 |  |  |  |  | =item * deltas
483 |  |  |  |  |
484 |  |  |  |  | Returns a hash with the keys "months", "days", "minutes", "seconds",
485 |  |  |  |  | and "nanoseconds", containing all the delta information for the
486 |  |  |  |  | object.
487 |  |  |  |  |
488 |  |  |  |  | =item * is_positive, is_zero, is_negative
489 |  |  |  |  |
490 |  |  |  |  | Indicates whether or not the duration is positive, zero, or negative.
491 |  |  |  |  |
492 |  |  |  |  | If the duration contains both positive and negative units, then it
493 |  |  |  |  | will return false for B<all> of these methods.
494 |  |  |  |  |
495 |  |  |  |  | =item * is_wrap_mode, is_limit_mode, is_preserve_mode
496 |  |  |  |  |
497 |  |  |  |  | Indicates what mode is used for end of month wrapping.
498 |  |  |  |  |
499 |  |  |  |  | =item * end_of_month_mode
500 |  |  |  |  |
501 |  |  |  |  | Returns one of "wrap", "limit", or "preserve".
502 |  |  |  |  |
503 |  |  |  |  | =item * calendar_duration
504 |  |  |  |  |
505 |  |  |  |  | Returns a new object with the same I<calendar> delta (months and days
506 |  |  |  |  | only) and end of month mode as the current object.
507 |  |  |  |  |
508 |  |  |  |  | =item * clock_duration
509 |  |  |  |  |
510 |  |  |  |  | Returns a new object with the same I<clock> deltas (minutes, seconds,
511 |  |  |  |  | and nanoseconds) and end of month mode as the current object.
512 |  |  |  |  |
513 |  |  |  |  | =item * inverse( ... )
514 |  |  |  |  |
515 |  |  |  |  | Returns a new object with the same deltas as the current object, but
516 |  |  |  |  | multiple by -1. The end of month mode for the new object will be the
517 |  |  |  |  | default end of month mode, which depends on whether the new duration
518 |  |  |  |  | is positive or negative.
519 |  |  |  |  |
520 |  |  |  |  | You can set the end of month mode in the inverted duration explicitly by
521 |  |  |  |  | passing "end_of_month => ..." to the C<inverse()> method.
522 |  |  |  |  |
523 |  |  |  |  | =item * add_duration( $duration_object ), subtract_duration( $duration_object )
524 |  |  |  |  |
525 |  |  |  |  | Adds or subtracts one duration from another.
526 |  |  |  |  |
527 |  |  |  |  | =item * add( ... ), subtract( ... )
528 |  |  |  |  |
529 |  |  |  |  | Syntactic sugar for addition and subtraction. The parameters given to
530 |  |  |  |  | these methods are used to create a new object, which is then passed to
531 |  |  |  |  | C<add_duration()> or C<subtract_duration()>, as appropriate.
532 |  |  |  |  |
533 |  |  |  |  | =item * multiply( $number )
534 |  |  |  |  |
535 |  |  |  |  | Multiplies each unit in the by the specified number.
536 |  |  |  |  |
537 |  |  |  |  | =item * DateTime::Duration->compare( $duration1, $duration2, $base_datetime )
538 |  |  |  |  |
539 |  |  |  |  | This is a class method that can be used to compare or sort durations.
540 |  |  |  |  | Comparison is done by adding each duration to the specified
541 |  |  |  |  | C<DateTime.pm> object and comparing the resulting datetimes. This is
542 |  |  |  |  | necessary because without a base, many durations are not comparable.
543 |  |  |  |  | For example, 1 month may or may not be longer than 29 days, depending
544 |  |  |  |  | on what datetime it is added to.
545 |  |  |  |  |
546 |  |  |  |  | If no base datetime is given, then the result of C<< DateTime->now >>
547 |  |  |  |  | is used instead. Using this default will give non-repeatable results
548 |  |  |  |  | if used to compare two duration objects containing different units.
549 |  |  |  |  | It will also give non-repeatable results if the durations contain
550 |  |  |  |  | multiple types of units, such as months and days.
551 |  |  |  |  |
552 |  |  |  |  | However, if you know that both objects only consist of one type of
553 |  |  |  |  | unit (months I<or> days I<or> hours, etc.), and each duration contains
554 |  |  |  |  | the same type of unit, then the results of the comparison will be
555 |  |  |  |  | repeatable.
556 |  |  |  |  |
557 |  |  |  |  | =item * years, months, weeks, days, hours, minutes, seconds, nanoseconds
558 |  |  |  |  |
559 |  |  |  |  | These methods return numbers indicating how many of the given unit the
560 |  |  |  |  | object represents, after having done a conversion to any larger units.
561 |  |  |  |  | For example, days are first converted to weeks, and then the remainder
562 |  |  |  |  | is returned. These numbers are always positive.
563 |  |  |  |  |
564 |  |  |  |  | Here's what each method returns:
565 |  |  |  |  |
566 |  |  |  |  | $dur->years() == abs( $dur->in_units('years') )
567 |  |  |  |  | $dur->months() == abs( ( $dur->in_units( 'months', 'years' ) )[0] )
568 |  |  |  |  | $dur->weeks() == abs( $dur->in_units( 'weeks' ) )
569 |  |  |  |  | $dur->days() == abs( ( $dur->in_units( 'days', 'weeks' ) )[0] )
570 |  |  |  |  | $dur->hours() == abs( $dur->in_units( 'hours' ) )
571 |  |  |  |  | $dur->minutes == abs( ( $dur->in_units( 'minutes', 'hours' ) )[0] )
572 |  |  |  |  | $dur->seconds == abs( $dur->in_units( 'seconds' ) )
573 |  |  |  |  | $dur->nanoseconds() == abs( ( $dur->in_units( 'nanoseconds', 'seconds' ) )[0] )
574 |  |  |  |  |
575 |  |  |  |  | If this seems confusing, remember that you can always use the
576 |  |  |  |  | C<in_units()> method to specify exactly what you want.
577 |  |  |  |  |
578 |  |  |  |  | Better yet, if you are trying to generate output suitable for humans,
579 |  |  |  |  | use the C<DateTime::Format::Duration> module.
580 |  |  |  |  |
581 |  |  |  |  | =back
582 |  |  |  |  |
583 |  |  |  |  | =head2 Overloading
584 |  |  |  |  |
585 |  |  |  |  | This class overloads addition, subtraction, and mutiplication.
586 |  |  |  |  |
587 |  |  |  |  | Comparison is B<not> overloaded. If you attempt to compare durations
588 |  |  |  |  | using C<< <=> >> or C<cmp>, then an exception will be thrown! Use the
589 |  |  |  |  | C<compare()> class method instead.
590 |  |  |  |  |
591 |  |  |  |  | =head1 SUPPORT
592 |  |  |  |  |
593 |  |  |  |  | Support for this module is provided via the datetime@perl.org email
594 |  |  |  |  | list. See http://lists.perl.org/ for more details.
595 |  |  |  |  |
596 |  |  |  |  | =head1 AUTHOR
597 |  |  |  |  |
598 |  |  |  |  | Dave Rolsky <autarch@urth.org>
599 |  |  |  |  |
600 |  |  |  |  | However, please see the CREDITS file for more details on who I really
601 |  |  |  |  | stole all the code from.
602 |  |  |  |  |
603 |  |  |  |  | =head1 COPYRIGHT
604 |  |  |  |  |
605 |  |  |  |  | Copyright (c) 2003-2010 David Rolsky. All rights reserved. This
606 |  |  |  |  | program is free software; you can redistribute it and/or modify it
607 |  |  |  |  | under the same terms as Perl itself.
608 |  |  |  |  |
609 |  |  |  |  | Portions of the code in this distribution are derived from other
610 |  |  |  |  | works. Please see the CREDITS file for more details.
611 |  |  |  |  |
612 |  |  |  |  | The full text of the license can be found in the LICENSE file included
613 |  |  |  |  | with this module.
614 |  |  |  |  |
615 |  |  |  |  | =head1 SEE ALSO
616 |  |  |  |  |
617 |  |  |  |  | datetime@perl.org mailing list
618 |  |  |  |  |
619 |  |  |  |  | http://datetime.perl.org/
620 |  |  |  |  |
621 |  |  |  |  | =cut
622 |  |  |  |  |