在Perl中将纪元时间转换为标准约定的问题 [英] Issue converting epoch time to standard convention in Perl

查看:97
本文介绍了在Perl中将纪元时间转换为标准约定的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Perl中,我尝试使用以下代码将包含毫秒纪元时间变量 $ adjSendTime 的变量转换为标准约定:

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);

问题是,每当达到第59秒时,时间的分钟部分就会变成分钟。高于应有的水平。输出看起来像

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

$ 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;
}

$ currentSecond 在代码的两个不同部分中。当 $ FIRST = 1; 时,第一部分在循环中第一次出现。在执行此if语句之后, $ FIRST 再也不会重置为1。

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;
}

以及子例程 resetCounters 脚本中计算出的每个值都重新初始化为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 = ();
}

谁能帮我弄清楚为什么Perl会这样做,因为当我发现通过长手除法剩下的我没有这个问题吗?我意识到我可以使用datetime来找到进行计算的小时和分钟,但是我仍然想确定我的计算出了什么问题,以便将来在使用<$ c $时可以避免这样的问题c>%在Perl中。

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.

推荐答案

这里是使用两个内置perl的简单版本函数:

Here is a simple version which uses two built-in perl functions:

my $timeLabel = sprintf "%02d:%02d:%02d", (localtime($adjSendTime/1000))[2,1,0];

对于比这更复杂的事情,我可能会使用外部模块,但我只是不这样做为此特殊需求这样做没有多大意义。

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.

这篇关于在Perl中将纪元时间转换为标准约定的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆