Perl epoch 在 2 台不同的机器(UTC 和 CET)上返回不同的值 [英] Perl epoch returns different values on 2 different machines (UTC and CET)

查看:125
本文介绍了Perl epoch 在 2 台不同的机器(UTC 和 CET)上返回不同的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have 2 linux machines that need to run a perl script and access a database. For any reason, date itself is correct, but returning epoch from Perl has 1 hour difference resulting in having on one machine UTC epoch-timestamp and on the other the wanted CET.

A 上的日期:

欧洲中部时间 2012 年 12 月 11 日星期二 13:34:09

Tue Dec 11 13:34:09 CET 2012

B 上的日期:

欧洲中部时间 2012 年 12 月 11 日星期二 13:33:20

Tue Dec 11 13:33:20 CET 2012

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

To check whats going on I build a minimalistic example. The script uses Time::HiRes and gathering the localtime->epoch to generate a date. I build a minimalistic following script to output the behaviour:

#/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->日期​​时间01355229343

Tue Dec 11 12:35:43 2012->datetime 0 1355229343

输出机器 B:

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

Tue Dec 11 13:34:25 2012->datetime 0 1355232865

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

So as you see something must be wrong with timezone or so. The differ with an hour. But I don't know where to look and what to configure as date itself outputs the correct time.

推荐答案

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

This seems to be a bug in Time::Piece->strptime(STRING, FORMAT). Here is the code in question:

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 是操作系统的原生strptime功能.它似乎返回本地时间,尽管在任何地方都没有记录.

Let's start here. _strptime is the operating system's native strptime function. It appears to return local time, although that's not documented anywhere.

#    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 时间函数的了解不够,不知道应该怎么做.)

Okay, so we use our _mktime method to turn the output of _strptime into a Time::Piece object. The second parameter is whether _mktime should interpret as local time or UTC. When called as Time::Piece->strptime(STRING, FORMAT), ref($time) will be false, and so _mktime will be called with $islocal=0, i.e. that _strptime returned a UTC time. This is wrong, and we've found the bug. (I don't know enough about the C time functions to know how it should be done.)

}

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

So you have to use localtime->strptime(STRING, FORMAT). Except this will still fail on old versions of the module due to another bug in _mktime (my distribution comes with version 1.15 where this is still broken, but it's fixed in 1.20).

这甚至不是 %s 特有的奇怪问题.它发生在任何 Time::Piece->strptime 调用中:

It's not even a strange issue specific to %s. It happens for any Time::Piece->strptime call:

$ 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

这篇关于Perl epoch 在 2 台不同的机器(UTC 和 CET)上返回不同的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆