So I am parsing a log file and look for certain time stamps and then subtracting them to get time elapsed.
So I tried a simple code to see if I can use Time::Piece but wasnt successful. My code below:
use Time::Piece;
my ($S, $E);
GetOptions (
"S=s" => \$S,
"E=s" => \$E,
);
my $start = $S;
my $end = $E;
my %build_time;
my $start_time;
my $end_time;
if(my ($start_time) = $start =~ /\[gg\s (\d \:\d \:\d )\s I\]/){
print"Build_Time: start at $start_time\n";
}
#--------------------
# End time from dj
if(my ($end_time) = $end =~ /\[gg\s (\d \:\d \:\d )\s I\]/){
print "Build_Time: end at $end_time\n";
}
my $difference = Time::Piece->strptime($end_time,'%H:%M:%S') - Time::Piece->strptime($start_time,'%H:%M:%S');
print " difference: $difference \n";
Execute: perl time.pl -S "[gg 8:11:03 I]: Copyright" -E "[gg 8:19:03 I]: BT_DEPTH=99 "
Build_Time: start at 8:11:03 Build_Time: end at 8:19:03 difference: 0
Also what is the time is in 24 hr format and log contains over night run ( so the difference would be negative)?
CodePudding user response:
Your code has a scoping issue: $start_time
and $end_time
in your if
statements mask the outer variables.
If the time difference is 23:59:59 max you can use a modulo operation to fix the negative seconds output caused by crossing a date boundary:
time.pl:
use strict;
use warnings;
use Getopt::Long;
use Time::Piece;
my ($S, $E);
GetOptions (
"S=s" => \$S,
"E=s" => \$E,
);
my $start = $S;
my $end = $E;
my %build_time;
my $start_time;
my $end_time;
if( ($start_time) = $start =~ /\[gg\s (\d \:\d \:\d )\s I\]/){
print"Build_Time: start at $start_time\n";
}
#--------------------
# End time from dj
if( ($end_time) = $end =~ /\[gg\s (\d \:\d \:\d )\s I\]/){
print "Build_Time: end at $end_time\n";
}
my $tp_st = Time::Piece->strptime($start_time,'%H:%M:%S');
my $tp_e = Time::Piece->strptime($end_time,'%H:%M:%S');
my $difference = $tp_e -$tp_st;
$difference %= 60*60*24; # 1 day
print " difference: $difference \n";
testing:
perl time.pl -S "[gg 8:19:04 I]: Copyright" -E "[gg 8:19:14 I]: BT_DEPTH=99 "
Build_Time: start at 8:19:04
Build_Time: end at 8:19:14
difference: 10
perl time.pl -S "[gg 8:19:04 I]: Copyright" -E "[gg 8:19:03 I]: BT_DEPTH=99 "
Build_Time: start at 8:19:04
Build_Time: end at 8:19:03
difference: 86399
CodePudding user response:
If input is indeed limited to times within 24 hours then if start time is larger than end time it means it rolled into another day. So you can substract Time::Piece
objects and adjust if negative
use warnings;
use strict;
use feature 'say';
use Getopt::Long;
use Time::Piece;
GetOptions ( "S=s" => \my $S, "E=s" => \my $E );
my ($tp_beg, $tp_end) = map {
my ($time) = /\[gg\s ([0-9] :[0-9] :[0-9] ) \s I\]/x;
die "Unexpected input format ($_)" if not $time;
Time::Piece->strptime($time, "%H:%M:%S")
} $S, $E;
my $diff_secs = $tp_end - $tp_beg;
$diff_secs = 24*60*60 if $diff_secs < 0;
say "Difference is $diff_secs secs";
say "Difference is ", sec_in_day_to_hms($diff_secs);
sub sec_in_day_to_hms { # add ($tt >= 3600*24) branch for multiple days
my ($tt) = @_;
my $msg = do {
if ( $tt >= 3600 ) {
sprintf("%d:d:d (hr:min:sec)",
$tt/3600, ($tt600)/60, $tt`);
}
elsif ( $tt >= 60 ) {
sprintf("%d min %d sec", ($tt600)/60, $tt`);
}
else { sprintf("%d sec", $tt`); }
};
return $msg;
}
Running as in the question
perl time_diff.pl -S "[gg 8:11:03 I]: Copyright" -E "[gg 8:19:03 I]: BT_DEPTH=99 "
prints
Difference is 480 secs Difference is 8 min 0 sec
If we change 8:19:03
to 6:19:03
(so it rolled all the way by about two hours short of a full day) and run it as
perl time_diff.pl -S "[gg 8:11:03 I]: Copyright" -E "[gg 6:19:03 I]: BT_DEPTH=99 "
then it prints
Difference is 79680 secs Difference is 22:08:00 (hr:min:sec)
A comment on the code in the question
It firstly has a mistake of defining a variable $start_time
also inside an if
block
if(my ($start_time) = $start =~ /.../){
and that variable masks (shadows) the one with the same name declared earlier. After the if
block is exited, the earlier $start_time
is restored, um, to undef
.
When that's used later in the program (for subtraction) it would print warnings -- if you had them on! Please add
use strict;
use warnings;
to the top of every program. These are directly helpful.
One simple way to fix that would be to just remove that my
-- then the regex's return is assigned indeed to the earlier declared $start_time
. However, I find that there are too many variables introduced for the purpose so I'd suggest to simplify instead.
Then, the possibly negative difference isn't handled, what the question itself asserts.