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