在新加坡计算小时差时,转换为hh:mm:ss.mmm会增加30分钟



我有这个Perl脚本,需要在其中监视DBI调用的执行时间。

在欧洲(法国),我没有问题:据报道,2秒的执行时间是2秒。

在新加坡的一台计算机上运行的相同脚本报告为30分2秒。

为什么?

use strict;
use Time::Format qw(%time);
use Time::HiRes qw(gettimeofday);
my $time_start = gettimeofday();
sleep 2;  # some action goes here
my $stat_perf = gettimeofday() - $time_start;
print STDOUT $time{'mm:ss.mmm', $stat_perf} . " n";

法国的产量是

00:02.000 

在新加坡运行的相同脚本产生:

30:02.001 

为什么?

根据本文档,gettimeofday函数返回自unix epoch(1970年1月1日)以来的秒或微秒UTC。因为它在UTC,所以完全不受时区的影响。

此外,在您的原始代码中,您只是使用gettimeofday,它将返回现在的时间戳,而不是1970年的时间戳。但在你建议的答案中,出于某种原因,你已经硬设置了时间戳,这对你没有多大帮助。

是的,几乎每个时区都有历史,包括新加坡。您可以在TZDB中看到它。但是你说的时间是+8:30是不对的。实际上是+7:30。您也可以在此网站上进行验证。但这并不重要,因为正如我所说,gettimeofday在UTC中严格工作。

我认为问题在于你如何解读结果。你的最后一行是:

print STDOUT $time{'mm:ss.mmm', $stat_perf} . " n";

但是$stat_perf是经过的持续时间,而不是一个可以作为时间戳的值。您可能不应该将其传递给$time,因为使用本地时区,并且需要完整的时间戳。

此外,您可能希望使用tv_interval,如示例所示。

更新

我搜索了CPAN档案,我确信某个地方有一个用于格式化经过的时间的模块,但我似乎找不到。无论如何,自己写这篇文章并不太难。在这里,这应该有效:

my $min = $stat_perf / 60;
my $sec = ($stat_perf * 1000 % 60000) / 1000;
my $elapsed = sprintf("%02u:%06.3f", $min, $sec);
print STDOUT $elapsed . "n";

anser是。。。

新加坡现在距离UTC偏移08h00。1970年,它被抵消了08h30。要求将几秒钟转换成字符串会让我们回到1970年,而不是今天的日期和时区。

通过请求

print STDOUT $time{'mm:ss.mmm', 2} . " n";

系统调整到1970(历元)时区偏移。

为了在新加坡取得正确的结果,我们必须转移到1982年之后,当时新加坡进行了最后一次时区更改。

print STDOUT $time{'mm:ss.mmm', 2 + 1356994800} . " n";

作为

UNIX_TIMESTAMP('2013-01-01 00:00:00')  = 1356994800

我们只关心日期的时间部分,所以这样做了

使用检查

zdump -v Asia/Singapore

这就是诀窍。

这里有一个脚本,它模拟$time{}将实数转换为表示整数部分的mm:ss sexagesimal转换的字符串,并与格式化为微秒的十进制余数连接。

由于这将是库的一部分,因此设置了一些保护措施,以避免使用错误的参数调用它。

我希望我没有错过什么。

use strict;
use Time::Format qw(%time);

# ----------------------------------------------------------
# A substitute to $time{} as we have issues with TZ offsets at epoch days in some part of the World
# A real to sexagesimal converter
# Format will be set to match $time{'mm:ss.mmm', $stat_perf};
sub microTime {
  return '' unless (my ($intertime) = @_);
  return '' unless (ref ($intertime) eq '');
  return '' unless (sprintf("%s", $intertime) =~ m/^(?:[d]+)(?:.(?:[d]+))?$/);
  my $intNum = int($intertime);
  "a" =~ /a/; # Resets regex buffers
  sprintf ("%.03f", $intertime - $intNum) =~ m,.([d]+),;
  my $intDec = $1;  # It's always defined
  my $intUnder = $intNum % 3600;
  my $intMin = int($intUnder / 60);
  my $intSec = $intUnder % 60;
  return sprintf ("%02d:%02d.%03d", $intMin, $intSec, $intDec);
}

  my $stat_perf;
  $stat_perf = 345.987;
  $stat_perf = 345;
  $stat_perf = 3945.987;
  $stat_perf = 0;
  $stat_perf = 3945.918733;

  print STDOUT sprintf (" >> %sn", &microTime ($stat_perf));
  print STDOUT sprintf (" == %sn", $time{'mm:ss.mmm', $stat_perf});

相关内容

  • 没有找到相关文章

最新更新