为什么 POSIX qw{strftime};是在“0”秒时给我一个小时吗?

why POSIX qw{strftime}; is giving me a houre on "0" seconds?

我正在尝试 POSIX qw{strftime}; 用作程序的正常运行时间,我发现了一些我不知道为什么会发生的事情。我没有那么多时间,这就是我搞砸它的原因(学习填写 "time" :P) 数学给了我 | uptime: 01:00:00 我应该在的地方 00:00:00 我输入了行 $stop_secs = $stop_secs - "3600"; 和 "fixed" 它,但我想知道额外的一小时是从哪里来的。

我不知道为什么,谁能解释一下或者为什么会这样?谢谢。

#!/usr/bin/perl
#
use strict;
use warnings;
use POSIX qw{strftime};


my $start_secs = time();
my $start_time = strftime '%H:%M:%S', localtime $start_secs; # all is: "%Y-%m-%d %H:%M:%S"

my $stop_secs = time();
$stop_secs = $stop_secs - "3600";  #<--- this fix the 1h "bug"? 

my $diff_secs = $stop_secs - $start_secs;
my $diff_time = strftime '%H:%M:%S', localtime $diff_secs;

print " 
    | Time started: $start_time
    | uptime:   $diff_time

\n";

localtime(0) 生成关于纪元开始时当地时区时间的信息。除非您与英格兰格林威治位于同一时区(并且不在夏令时),否则 strftime 不会将其转换为零。例如,在加利福尼亚这里,我得到

$ perl -MPOSIX=strftime -E 'say strftime "%H:%M:%S",localtime(0)'
16:00:00

我不知道 strftime 和 returns 时间信息列表的 perl 函数的组合是否是完成这项工作的正确工具,但如果你打算走那条路,使用 gmtime 而不是 localtime.

$ perl -MPOSIX=strftime -E 'say strftime "%H:%M:%S",gmtime(0)'
00:00:00

time returns 日期时间(在日历中)。

localtimegmtimePOSIX::strftime 旨在处理这些日历日期 - 而不是时间跨度。

我建议查看 DateTime 的日期和 DateTime::Span 的跨度。

localtime($seconds) returns 有关本地日期时间的信息,对应于 1970 年 1 月 1 日午夜过后 $seconds 秒,UTC (1970-01-01T00:00:00Z ), 忽略闰秒。

所以假设一台机器使用 Europe/Paris 作为它的时区。当 1970-01-01T00:00:00Z 过去 0 秒时,当地时间应该是 1970-01-01T01:00:00+01:00。因此,在这样的机器上,您会得到 01:00:00.

#!/usr/bin/perl
use feature qw( say );
use POSIX qw( strftime );
say strftime("%Y-%m-%dT%H:%M:%S%z", localtime(0)) =~ s/(?=..\z)/:/r;
say strftime("           %H:%M:%S", localtime(0));
$ TZ=Europe/Paris ./a
1970-01-01T01:00:00+01:00
           01:00:00

$ TZ=America/Montreal ./a
1969-12-31T19:00:00-05:00
           19:00:00

您不应该使用 localtime。您可以在某种程度上使用 gmtime

#!/usr/bin/perl
use feature qw( say );
use POSIX qw( strftime );
say strftime("%Y-%m-%dT%H:%M:%SZ", gmtime(0));
say strftime("           %H:%M:%S", gmtime(0));
$ TZ=Europe/Paris ./b
1970-01-01T00:00:00Z
           00:00:00

$ TZ=America/Montreal ./b
1970-01-01T00:00:00Z
           00:00:00

但实际上,您甚至不应该使用 strftime,因为那是用于日期时间,而不是持续时间。它会起作用,但仅限于一定程度。

  • strftime("%H:%M:%S", gmtime($secs)) 的持续时间最长为 24*60*60 秒,但不包括在内。
  • strftime("%d:%H:%M:%S", gmtime($secs)) 将在最长但不包括 31*24*60*60 秒的时间内工作,前提是您可以将一天表示为 24 小时。