| 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 | DateTime::Duration::BEGIN@3 |
| 1 | 1 | 1 | 11µs | 43µs | DateTime::Duration::BEGIN@11 |
| 1 | 1 | 1 | 8µs | 74µs | DateTime::Duration::BEGIN@13 |
| 1 | 1 | 1 | 7µs | 16µs | DateTime::Duration::BEGIN@4 |
| 1 | 1 | 1 | 7µs | 37µs | DateTime::Duration::BEGIN@22 |
| 1 | 1 | 1 | 6µs | 6µs | DateTime::Duration::BEGIN@9 |
| 1 | 1 | 1 | 4µs | 4µs | DateTime::Duration::BEGIN@10 |
| 1 | 1 | 1 | 3µs | 3µs | DateTime::Duration::BEGIN@8 |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::_add_overload |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::_compare_overload |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::_has_negative |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::_has_positive |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::_multiply_overload |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::_normalize_nanoseconds |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::_subtract_overload |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::add |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::add_duration |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::calendar_duration |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::clock_duration |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::clone |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::compare |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::days |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::delta_days |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::delta_minutes |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::delta_months |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::delta_nanoseconds |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::delta_seconds |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::deltas |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::end_of_month_mode |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::hours |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::in_units |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::inverse |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::is_limit_mode |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::is_negative |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::is_positive |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::is_preserve_mode |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::is_wrap_mode |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::is_zero |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::minutes |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::months |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::multiply |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::nanoseconds |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::new |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::seconds |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::subtract |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::subtract_duration |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::weeks |
| 0 | 0 | 0 | 0s | 0s | DateTime::Duration::years |
| 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 |