Perl epoch 在 2 台不同的机器(UTC 和 CET)上返回不同的值 [英] Perl epoch returns different values on 2 different machines (UTC and 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屋!