在Perl中,我尝试$adjSendTime使用以下代码将包含毫秒纪元时间变量的变量转换为标准约定:
$timeLabel = sprintf("%02d:%02d:%02d", (($adjSendTime/3600000) % 24), (($adjSendTime/60000) % 60), $currentSecond);
Run Code Online (Sandbox Code Playgroud)
问题在于,无论何时达到第59秒,时间的一小部分时间都将高于应有的时间.输出看起来像
11:58:57
11:58:58
11:59:59
11:59:00
11:59:01
Run Code Online (Sandbox Code Playgroud)
计算$adjSendTime如下:
# 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;
}
Run Code Online (Sandbox Code Playgroud)
计算$currentSecond在代码的两个不同部分.第一件事发生在第一次循环时$FIRST = 1;.$FIRST在执行此if语句后,永远不会再次重置为1.
$second = ($adjSendTime/1000) % 60;
if ($FIRST) {
$currentSecond = $second;
$prevSeqId = $seqId;
$FIRST = 0;
}
Run Code Online (Sandbox Code Playgroud)
并且在子例程resetCounters中,脚本中计算的每个值都重新初始化为0.调用此子例程在输入日志文件中每隔一秒开始时调用.
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 = ();
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮我弄清楚为什么Perl会这样做,因为当我通过长手分区找到剩余部分时我没有这个问题吗?我意识到我可以使用datetime来计算这个计算的小时和分钟,但我仍然有兴趣确定我的计算有什么问题,以便我可以在将来使用%Perl 时避免这样的问题.
小智 11
为什么在使用时重新发明轮子DateTime?
use strict;
use warnings;
use DateTime;
my $epoch=1254121251.352329;
my $dt = DateTime->from_epoch(epoch=>$epoch,time_zone => "America/Chicago");
print $dt->ymd . " " . $dt->hms . "\n";
Run Code Online (Sandbox Code Playgroud)
输出是:
2009-09-28 02:00:51
Run Code Online (Sandbox Code Playgroud)
这可以简单地使用核心工具achived:POSIX的strftime与组合localtime.
use POSIX qw( strftime );
say strftime('%H:%M:%S', localtime( $mstime/1000 ));
Run Code Online (Sandbox Code Playgroud)
DateTime是一个很棒的模块,但对于这项工作来说,这是不必要的慢.而且更加啰嗦.
use DateTime qw( );
my $dt = DateTime->from_epoch(epoch => $mstime/1000, time_zone => 'local');
say $dt->strftime('%H:%M:%S');
Run Code Online (Sandbox Code Playgroud)