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

Hello Monks,

i have a question here regarding to calculate the minutes difference between two dates. i have written a code here, but i know it's not very accurate, because i assume every month is 30 days and 365 days in a year (it goes very wrong when calculate the dates for example: 2007-12-31 16:50:00;2008-1-1 04:24:00;), anyone know there is a perl module can calculate the accurate minuets between two dates ?

#!/usr/bin/perl use strict; use warnings; #Using perl package use Date::Calc qw(Delta_YMDHMS); use Date::Calc qw(Add_Delta_DHMS); #subroutine: rounding no sub round($); while (<TEMP>) { my @line=split(";"); my @start_time=($line[3]=~/(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/); + #parsing the start time my @stop_time=($line[4]=~/(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/); + #parsing the stop time my @diff=Delta_YMDHMS(@start_time,@stop_time); + #calculate diff in YMDHMS my($yyyy,$m,$d,$hh,$mm,$ss)=@diff; $min_diff=($yyyy*365*24*60+$m*30*24*60+$d*24*60+$hh*60+$mm*1+$ss*0); + #convert to mins $interval=round($min_diff/15); + #get the interval print "minutes difference between two dates are: $min_diff"; } sub round($) { my($number) = shift; return int($number + .5); }
thanks,

Replies are listed 'Best First'.
Re: Calculate time difference between two dates
by ikegami (Patriarch) on Oct 06, 2009 at 19:46 UTC

    It's impossible to know the different in minutes without knowing the timezone of the times.

    I use DateTime

    #!/usr/bin/perl use strict; use warnings; use DateTime qw( ); use DateTime::Format::Strptime qw( ); my $format = DateTime::Format::Strptime->new( pattern => '%Y-%m-%d %H:%M:%S', ); my $start = $format->parse_datetime( '2007-12-31 16:50:00' ); my $stop = $format->parse_datetime( '2008-1-1 04:24:00' ); $_->set_time_zone('local') for $start, $stop; print( $start->delta_ms($stop)->in_units('minutes'), "\n" ); # 694
Re: Find minutes difference between two dates
by Anonymous Monk on Oct 06, 2009 at 20:36 UTC
    thank you for ikegami and the anonymous.

    ikegami: is it possible to use your method to parse date string from a csv file. coz i have lots of dates need to be calculated. can i use something like:

    while ($line=<TEMP>) { my $start = $format->parse_datetime( $line[3] ); my $stop = $format->parse_datetime( $line[4] ); }

    the anonymous: i have tried your code, however get the following error:

    Month '12' out of range 0..11 at test.perl line 33

    any suggestions for correction ?

    many thanks guys ! Simon

      can i use something like:

      Yes.

      Month '12' out of range 0..11 at test.perl line 33

      Subtract 1 from the month and 1900 from the year before passing to timelocal.

      any suggestions for correction ?

      Oh. I forgot that timelocal expects the month parameter to be in the range of 0..11, 0 being January and 11 being december.

      my $start_time = timelocal($start_time[5], $start_time[4], $start_time +[3], $start_time[2], $start_time[1]-1, $start_time[0]); my $end_time = timelocal($end_time[5], $end_time[4], $end_time[3], $ +end_time[2], $end_time[1]-1, $end_time[0]);
      Note the -1's.

      Ikegami's solution is much better when it comes to readability and maintainability, but mine is probably cheaper.
Re: Find minutes difference between two dates
by Anonymous Monk on Oct 06, 2009 at 19:50 UTC
    For example:

    use Time::Local; while (<>) { my @line=split(";"); my @start_time=($line[3]=~/(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/); + #parsing the start time my @stop_time=($line[4]=~/(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/); # +parsing the stop time my $start_time = timelocal($start_time[5], $start_time[4], $start_ti +me[3], $start_time[2], $start_time[1], $start_time[0]); my $end_time = timelocal($end_time[5], $end_time[4], $end_time[3], $ +end_time[2], $end_time[1], $end_time[0]); my $min_diff = sprintf("%.0f", ($end_time - $start_time) / 60); print $min_diff."\n"; }
    (untested code)

    Also, your rounding function is weird. Use (s)printf if you want correctly rounded numbers.

      Also, your rounding function is weird. Use (s)printf if you want correctly rounded numbers.

      Not weird, and definitely cheaper than building a string then converting the string into a number.