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

Hello Monks, I am pretty much new to Perl and writing a log parsing application,
where i need to compare the time stamp of every line in the log file to the previous line.
I tried using the DateCalc function of Date::Manip , but its taking ever to complete a file with some 65000 lines.
So thought of writing my own function. And below is the code snippet.

my (@d_in_m) = ( 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); my $t1 = "2009-04-12 23:59:55 PM"; my $t2 = "2009-03-30 00:00:02 PM"; my @date1 = split( /-| |:/, $t1 ); my @date2 = split( /-| |:/, $t2 ); my $delta_sec = 0; sub month_delta { my ( $from_month, $to_month, $from_year, $to_year ) = @_; my $delta = 0; if ( ( $to_year > $from_year ) && ( $to_month > $from_month ) ) { $delta += ( $to_year - $from_year ) * 31536000; } for ( my $i = ( ( $from_month + 1 ) > 12 ) ? 1 : ( $from_month + 1 ) + ; $i < $to_month ; $i++ ) { $delta += ( $d_in_m[$i] * 86400 ); } return $delta; } my ( $date1_ref, $date2_ref ) = ( \@date1, \@date2 ); if(($date2[0]<= $date1[0]) && ($date2[1]< $date1[1]) ){ print "swapping the date \n"; ($date1_ref, $date2_ref) = ($date2_ref, $date1_ref); } if ( $date2_ref->[0] . $date2_ref->[1] eq $date1_ref->[0] . $date1_ +ref->[1] ) { $delta_sec = $date2_ref->[5] - $date1_ref->[5]; $delta_sec += ( $date2_ref->[4] - $date1_ref->[4] ) * 60; $delta_sec += ( $date2_ref->[3] - $date1_ref->[3] ) * 3600; $delta_sec += ( $date2_ref->[2] - $date1_ref->[2] ) * 86400; } elsif ( $date1_ref->[2] <= $d_in_m[ $date1_ref->[1] ] ) { $delta_sec = $date2_ref->[5] - $date1_ref->[5]; $delta_sec += ( $date2_ref->[4] - $date1_ref->[4] ) * 60; $delta_sec += ( $date2_ref->[3] - $date1_ref->[3] ) * 3600; $delta_sec += ( $date2_ref->[2] ) * 86400; $delta_sec += ( $d_in_m[ $date1_ref->[1] ] - $date1_ref->[2] ) * 86400 + month_delta( $date1_ref->[1], $date2_ref->[1], $date1_ref->[0], $date2_ref->[0] ); } else { print "Seems to be a invalid comparison delta b/w $t1 and $t2\ +n"; } print "!!!! Delta b/w $t1 and $t2 is " . $delta_sec . "\n";


I have tested this for several combinations and it seems to work.
Yet to handle the leap year case which is any ways of least needed for my program.

This is much more faster than the Date::Manip module.

Please look at this and let me know if i can make it more optimized or missed out any scenarios.


If needed you can use this code also :-)


Thanks

Replies are listed 'Best First'.
Re: Code to calculate Delta b/w two dates in seconds
by Sewi (Friar) on Sep 22, 2009 at 20:52 UTC
    my $t1 = "2009-04-12 23:59:55 PM"; my $t2 = "2009-03-30 00:00:02 PM";
    There is no 23:59:55 with PM. Either you got 24hour-format or AM/PM :-)

    Your solution assums that each day has 24 hours. It's a common mistake, but it is simply not true. There is daylight saving, once they even put some days difference in a second and February hasn't always 28 days.

    use Time::Local; sub String2Time { $_[0] =~ /^(\d{4})\-(\d{2})\-(\d{2}) (\d{2})\:(\d{2})\:(\d{2})/ or di +e "Invalid format: $_[0]"; return timelocal($6,$5,$4,$3,($2 - 1),($1 - 1900)); } my $t1 = "2009-04-12 23:59:55 PM"; my $t2 = "2009-03-30 00:00:02 PM"; print &String2Time($t1) - &String2Time($t2);
    Just parse your timestamp and feed it into timelocal from Time::Local.

    Please let us know if this is faster or slower than your solution.

      Thanks for the inputs. It works well and speed of execution seems to have no much difference.
      Can we use the same approach of Time::Local to add a some seconds to the existing time.

      I need something to work like the behaviour mentioned below
      my $t1 = "2009-04-12 23:59:55"; my $delta = 600; # seconds $updated_time = &String2Time($t1) + $delta;

      Thanks again
Re: Code to calculate Delta b/w two dates in seconds
by moritz (Cardinal) on Sep 22, 2009 at 20:23 UTC

    It might be more robust (and maybe faster) to use POSIX::mktime or Time::Local::timelocal to calculate the epoch date for both dates, and simply subtract the second from the first.

    Perl 6 - links to (nearly) everything that is Perl 6.
Re: Code to calculate Delta b/w two dates in seconds
by vitoco (Hermit) on Sep 22, 2009 at 21:52 UTC

    It is strange that dates in a log file are not sorted, unless they are starting timestamps written by different threads when finishing their long running job. Anyway, why are you swapping dates based only on years and months?

    I guess that references are used only because of the dates swap. Your date strings are sortable, so why don't do it before splitting them? Then, you can use the arrays directly.

    You need speed. Try splitting with /[-: ]/ or /\D+/ (as it was said, "PM" is irrelevant because your hours are in 00 to 23 range).