【问题标题】:why POSIX qw{strftime}; is giving me a houre on "0" seconds?为什么 POSIX qw{strftime};在“0”秒上给我一个小时?
【发布时间】:2020-08-09 07:11:37
【问题描述】:

我在玩 POSIX qw{strftime}; 以用作程序的正常运行时间,但我发现了一些我不知道为什么会发生的事情。我不怎么花时间,这就是我搞砸它的原因(学习填补“时间”:P) 数学给了我| uptime: 01:00:00我应该在哪里00:00:00我输入了 $stop_secs = $stop_secs - "3600"; 并“修复”了它,但我想知道额外的时间是从哪里来的。

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

#!/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";

【问题讨论】:

    标签: perl math time strftime seconds


    【解决方案1】:

    localtime($seconds) 返回与 UTC (1970-01-01T00:00:00Z) 午夜过后的 $seconds 秒对应的本地日期时间信息,忽略闰秒。

    假设一台机器使用欧洲/巴黎作为其时区。当 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 小时。

    【讨论】:

      【解决方案2】:

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

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

      我不知道strftime 和返回时间信息列表的 perl 函数的组合是否适合这项工作,但如果你打算这样做,请使用 gmtime而不是localtime

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

      【讨论】:

      • 看来gmtime 让情况变得更糟,给了我 2 小时的错误时间,我研究了localtime() 是如何处理我使用它时发出的请求的。但它似乎解决了数学问题
      • @Sounix, Re "gmtime 让事情变得更糟",嗯?你误会了。 strftime "%H:%M:%S",gmtime(0)) 将始终返回 00:00:00。 1 秒将返回00:00:01。 60 秒将返回 00:01:00 等。这将适用于但不包括 24*60*60。
      • 是的,它让我的localtime 错了两个小时,但它修正了数学:P。但就像你解释的那样,它不是适合这项工作的工具,我学到了一些新东西。谢谢你的帮助。 ;-) result =&gt; | uptime: 00:00:00
      【解决方案3】:

      time 返回日期时间(在日历中)。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-05
        • 2016-03-28
        • 2012-08-08
        • 2017-07-12
        • 2017-10-30
        • 2023-03-17
        • 2021-03-04
        • 1970-01-01
        相关资源
        最近更新 更多