【问题标题】:Perl epoch returns different values on 2 different machines (UTC and CET)Perl epoch 在 2 台不同的机器(UTC 和 CET)上返回不同的值
【发布时间】:2012-12-11 13:14:47
【问题描述】:

我有 2 台 linux 机器需要运行 perl 脚本并访问数据库。 出于任何原因,日期本身是正确的,但从 Perl 返回的纪元有 1 小时的差异,导致在一台机器上具有 UTC 纪元时间戳,而在另一台机器上具有所需的 CET。

A 日期:

2012 年 12 月 11 日星期二 13:34:09 CET

日期:

2012 年 12 月 11 日星期二 13:33:20 CET

为了检查发生了什么,我构建了一个简约示例。 该脚本使用 Time::HiRes 并收集 localtime->epoch 来生成日期。 我构建了一个简约的以下脚本来输出行为:

#/usr/bin/perl
#
use Time::HiRes qw(time);
use Time::Piece;
#
my $date = Time::Piece->strptime(localtime->epoch,"%s");
print "$date->datetime"."\n";
print $date->tzoffset."\n";
print $date->epoch."\n";

输出机器A:

2012 年 12 月 11 日星期二 12:35:43->日期​​时间 0 1355229343

输出机器B:

2012 年 12 月 11 日星期二 13:34:25->日期时间 0 1355232865

因此,正如您所见,时区一定有问题。相差一个小时。但我不知道在哪里看以及配置什么,因为日期本身会输出正确的时间。

【问题讨论】:

  • perl -le'print time' 给了什么?
  • 您的脚本不使用 Time::HiRes。 (它加载模块,但不使用它。)

标签: perl time timezone


【解决方案1】:

这似乎是Time::Piece->strptime(STRING, FORMAT) 中的一个错误。这是有问题的代码:

sub strptime {
    my $time = shift;
    my $string = shift;
    my $format = @_ ? shift(@_) : "%a, %d %b %Y %H:%M:%S %Z";
    my @vals = _strptime($string, $format);

让我们从这里开始。 _strptime 是操作系统的native strptime function。它似乎返回当地时间,尽管任何地方都没有记录。

#    warn(sprintf("got vals: %d-%d-%d %d:%d:%d\n", reverse(@vals)));
    return scalar $time->_mktime(\@vals, (ref($time) ? $time->[c_islocal] : 0));

好的,所以我们使用_mktime 方法将_strptime 的输出转换为Time::Piece 对象。第二个参数是_mktime 应该解释为本地时间还是UTC。当以Time::Piece->strptime(STRING, FORMAT) 调用时,ref($time) 将为假,因此_mktime 将以$islocal=0 调用,即_strptime 返回一个UTC 时间。这是错误的,我们已经找到了错误。 (我对 C 时间函数知之甚少,不知道应该怎么做。)

}

所以你必须使用localtime->strptime(STRING, FORMAT)。除了由于_mktime 中的另一个错误,旧版本的模块仍然会失败(我的发行版附带了 1.15 版,该版本仍然存在问题,但在 1.20 中已修复)。

这甚至不是%s 特有的奇怪问题。任何Time::Piece->strptime 呼叫都会发生这种情况:

$ perl -MTime::Piece -E'say $x=Time::Piece->strptime("11 Dec 2012 10:00","%d %b %Y %H:%M")->epoch;say scalar localtime $x'
1355220000
Tue Dec 11 04:00:00 2012
$ perl -MTime::Piece -E'say $x=localtime->strptime("11 Dec 2012 10:00","%d %b %Y %H:%M")->epoch;say scalar localtime $x'
1355220000
Tue Dec 11 04:00:00 2012
$ export PERL5LIB=Time-Piece-1.20/blib/lib:Time-Piece-1.20/blib/arch
$ perl -MTime::Piece -E'say $x=Time::Piece->strptime("11 Dec 2012 10:00","%d %b %Y %H:%M")->epoch;say scalar localtime $x'
1355220000
Tue Dec 11 04:00:00 2012
$ perl -MTime::Piece -E'say $x=localtime->strptime("11 Dec 2012 10:00","%d %b %Y %H:%M")->epoch;say scalar localtime $x'
1355241600
Tue Dec 11 10:00:00 2012

【讨论】:

    【解决方案2】:

    我建议你尝试使用gmtime 而不是localtime


    没有帮助:

    >perl -MTime::Piece -E"say Time::Piece->strptime(localtime->epoch,'%s')->epoch;"
    1355239881
    
    >perl -MTime::Piece -E"say Time::Piece->strptime(gmtime->epoch,'%s')->epoch;"
    1355239881
    
    >perl -E"say time"
    1355239881
    

    【讨论】:

    • 这没有帮助。比较perl -E"say time",这是正确的值。
    猜你喜欢
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    相关资源
    最近更新 更多