File | /usr/local/lib/perl5/site_perl/5.10.1/darwin-2level/DateTime/Duration.pm |
Statements Executed | 27 |
Statement Execution Time | 1.37ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 15µs | 18µs | BEGIN@3 | DateTime::Duration::
1 | 1 | 1 | 11µs | 43µs | BEGIN@11 | DateTime::Duration::
1 | 1 | 1 | 8µs | 74µs | BEGIN@13 | DateTime::Duration::
1 | 1 | 1 | 7µs | 16µs | BEGIN@4 | DateTime::Duration::
1 | 1 | 1 | 7µs | 37µs | BEGIN@22 | DateTime::Duration::
1 | 1 | 1 | 6µs | 6µs | BEGIN@9 | DateTime::Duration::
1 | 1 | 1 | 4µs | 4µs | BEGIN@10 | DateTime::Duration::
1 | 1 | 1 | 3µs | 3µs | BEGIN@8 | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | _add_overload | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | _compare_overload | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | _has_negative | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | _has_positive | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | _multiply_overload | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | _normalize_nanoseconds | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | _subtract_overload | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | add | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | add_duration | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | calendar_duration | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | clock_duration | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | clone | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | compare | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | days | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | delta_days | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | delta_minutes | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | delta_months | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | delta_nanoseconds | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | delta_seconds | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | deltas | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | end_of_month_mode | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | hours | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | in_units | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | inverse | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | is_limit_mode | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | is_negative | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | is_positive | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | is_preserve_mode | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | is_wrap_mode | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | is_zero | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | minutes | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | months | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | multiply | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | nanoseconds | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | new | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | seconds | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | subtract | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | subtract_duration | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | weeks | DateTime::Duration::
0 | 0 | 0 | 0s | 0s | years | DateTime::Duration::
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 # 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 # 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 # 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 # 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 # 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 # 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 | ||||
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 # 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 |