Perl epoch在2台不同的机器上返回不同的值(UTC和CET)

时间:2012-12-11 13:14:47

标签: perl time timezone

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

日期:A:

  

Tue Dec 11 13:34:09 CET 2012

日期在B:

  

Tue Dec 11 13:33:20 CET 2012

为了检查最新情况,我构建了一个简约的例子。 该脚本使用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-> datetime   0   1355229343

输出机器B:

  

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

所以当你看到时区必须出错时。与一小时不同。但我不知道在哪里查看以及配置什么,因为日期本身会输出正确的时间。

2 个答案:

答案 0 :(得分:3)

这似乎是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)将为false,因此将使用_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

答案 1 :(得分:-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