2

Perlスクリプトを実行してデータベースにアクセスする必要がある2台のLinuxマシンがあります。何らかの理由で、日付自体は正しいですが、Perlからエポックを返すには1時間の違いがあり、一方のマシンにはUTCエポックタイムスタンプがあり、もう一方のマシンには必要なCETがあります。

Aの日付:

2012年12月11日火曜日13:34:09CET

Bの日付:

2012年12月11日火曜日13:33:20CET

何が起こっているかを確認するために、最小限の例を作成します。スクリプトは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->日時01355229343

出力機B:

2012年12月11日火曜日13:34:25->日時01355232865

ご覧のとおり、タイムゾーンなどに問題があるはずです。時間によって異なります。しかし、日付自体が正しい時刻を出力するので、どこを見れば何を設定すればよいのかわかりません。

4

2 に答える 2

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オペレーティングシステムのネイティブstrptime関数です。それはどこにも文書化されていませんが、現地時間を返すように見えます。

#    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ます。2番目のパラメーターは_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
于 2012-12-11T16:24:34.353 に答える
-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
于 2012-12-11T14:30:35.617 に答える