Marsel has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

I need to compute duration intervals from various dates. I read through the DateTime Tutorial on perlmonks and choose to use this module. Unfortunately, i'm getting strange results on a first test : misunderstanding or bug ?

here is the code :

use strict; use warnings; use DateTime; my $t1 = DateTime->new(year => 2001, month => 4, day => 23, hour => 22, minute => 32); my $t2 = DateTime->new(year => 2001, month => 4, day => 22, hour => 15, minute => 42); print "T1 = ".$t1->hour.":".$t1->minute."\n T2 = ".$t2->hour.":".$t2->minute."\n T1-T2 = ".$t1->subtract_datetime($t2)->hours."\n T2-T1 = ".$t2->subtract_datetime($t1)->hours."\n";

Here is the result :

T1 = 22:32
T2 = 15:42
T1-T2 = 6
T2-T1 = 6


Any comment or help would be appreciated, or if you know a better module to do that (i'll need to compute duration intervals in term of days also, which implies knowing the month's lengh ...)


Thanks,

Marcel

Replies are listed 'Best First'.
Re: DateTime usage for duration computation
by derby (Abbot) on Aug 29, 2007 at 12:25 UTC

    I think it's part misunderstanding and part bad documentation. Looking at DateTime, the subtract_datetime method returns a DateTime::Duration object. Looking at DateTime::Duration hours method, it's a a wrapper over the in_units method which when asking for hours, does an int on the numbers, effectively rounding the value (but probably not in a way you want).

    -derby

    update: I prefer Date::Manip for date calculations.

Re: DateTime usage for duration computation
by andreas1234567 (Vicar) on Aug 29, 2007 at 13:04 UTC
    DateTime::Duration:
    * years, months, weeks, days, hours, minutes, seconds, nanoseconds

    These methods return numbers indicating how many of the given unit the object represents, after having done a conversion to any larger units. For example, days are first converted to weeks, and then the remainder is returned. These numbers are always positive.

    $ perl -l use strict; use warnings; use DateTime; my $t1 = DateTime->new( year => 2001, month => 4, day => 23, hour => 22, minute => 32 ); my $t2 = DateTime->new( year => 2001, month => 4, day => 22, hour => 15, minute => 42 ); # subtract_datetime returns a "DateTime::Duration" object my $dtd1 = $t1->subtract_datetime($t2); print $dtd1->years . q{ years} if $dtd1->years; print $dtd1->months . q{ months} if $dtd1->months; print $dtd1->weeks . q{ weeks} if $dtd1->weeks; print $dtd1->days . q{ days} if $dtd1->days; print $dtd1->hours . q{ hours} if $dtd1->hours; print $dtd1->minutes . q{ minutes} if $dtd1->minutes; print $dtd1->seconds . q{ seconds} if $dtd1->seconds; print $dtd1->nanoseconds . q{ nanoseconds} if $dtd1->nanoseconds; __END__ 1 days 6 hours 50 minutes
    --
    Andreas
Re: DateTime usage for duration computation
by girarde (Hermit) on Aug 29, 2007 at 14:09 UTC
    I prefer Date::Manip as well. This is a case, though, where could go with something like:

    my $t1 = DateTime->new(year => 2001, month => 4, day => 23, hour => 22, minute => 32); my $t2 = DateTime->new(year => 2001, month => 4, day => 22, hour => 15, minute => 42); my $delta = $t1->subtract_datetime_absolute($t2) my $days = int($delta / 86400); $delta = $delta % 86400; my $hours = int($delta / 3600); $delta = $delta % 3600);

    etcetera. Not elegant, but nice and obvious what's happening.

      I think that your $delta, since it's a duration object, needs to be dereferenced into seconds to make this work.

      my $days = int($delta->seconds / 86400);

      Right?