In Perl I am trying to convert a variable containing millisecond epoch time variable $adjSendTime
to standard convention using the following code:
$timeLabel = sprintf("%02d:%02d:%02d", (($adjSendTime/3600000) % 24), (($adjSendTime/60000) % 60), $currentSecond);
The issue is that whenever it has reach the 59th second the minute portion of the time will be on minute higher than it should be. The output looks something like
11:58:57
11:58:58
11:59:59
11:59:00
11:59:01
The calculation for $adjSendTime
is as follows:
# Determine number of hours between local time and UTC.
# This code is needed to compare timestamps in local time with those in epoch time.
# This code only works in time zones with current time less than UTC time.
@timeArray = gmtime();
$utcHour = $timeArray[2];
@timeArray = localtime();
$localHour = $timeArray[2];
# calculate number of milliseconds between current time and UTC time
$utcShift = ($utcHour - $localHour + 24) % 24;
$utcShift = $utcShift*60*60*1000;
...
if ($field[$i] =~ /^\[29997]=/) {
$sendTimestamp = $field[$i];
$sendTimestamp =~ s/.*=(\d*).*/$1/;
# convert send time to local time.
$adjSendTime = $sendTimestamp - $utcShift;
}
The calculation for $currentSecond
is in two different parts of the code. The first piece occurs the first time through the loop when $FIRST = 1;
. $FIRST
is never reset to 1 again after this if statement is executed.
$second = ($adjSendTime/1000) % 60;
if ($FIRST) {
$currentSecond = $second;
$prevSeqId = $seqId;
$FIRST = 0;
}
and in the subroutine resetCounters
where every value that is calculated in the script is reinitialize to 0. This subroutine is called is called at the start of every new second in the input log file.
sub resetCounters
# -----------------------------------------------------------
# resets all metrics counters
# -----------------------------------------------------------
{
$tps = 0;
$mps = 0;
$batch = 0;
$maxBatch = 0;
$avgBatch = 0;
$latency = 0;
$latencySum = 0;
$maxLatency = 0;
$avgLatency = 0;
$overThreshold = 0;
$percentOver = 0;
$zeroLatencyCount = 0;
$currentSecond = $second;
@latencies = ();
}
Can anyone help me figure out why Perl would be doing this because when I find the remainder via long hand division I do not have this issue? I realize that I could use datetime to possibly find the hour and minute for this calculation, but I would still be interested in determining what is wrong with my calculation so that I can hopefully avoid issues like this in the future when using %
in Perl.
This can be achived simply using core tools: POSIX's
strftime
in combination withlocaltime
.DateTime is a great module, but it's needlessly slow for this job. And much wordier.
Here is a simple version which uses two built-in perl functions:
For anything much more complicated than this, I would likely use an external module, but I just don't see much point in doing so for this particular need.
Why reinvent the wheel when you can use
DateTime
?The output is: