2016-04-25 16 views
1

過去にタイムスタンプがあり、すべてがUTCであるファイルがあります。これらを東部時間に変換する必要があります。私は近づいてきましたが、夏時間の切り替えの回りにはうんざりします。あなたが見ることができるようにUTCからローカルへのヒストリカルタイムスタンプの変換

#!/usr/bin/perl 
use strict; 
use warnings; 
use Time::Piece; 

#DST not in effect 
my $utc = '2015-03-08 01:59:00.000'; 
my $local = utc_to_local($utc); 
print "DST not in effect: utc($utc) = local($local)\n"; 

#DST not in effect 
$utc = '2015-03-08 02:00:00.000'; 
$local = utc_to_local($utc); 
print "DST not in effect: utc($utc) = local($local)\n"; 


sub utc_to_local 
{ 
    my $utc_ts = $_[0]; #this has ms on right side, we want left 19 characters 
    $utc_ts = substr $utc_ts, 0, 19; 
    my $local_tp = localtime->strptime($utc_ts, '%Y-%m-%d %H:%M:%S'); 
    $local_tp = $local_tp + $local_tp->tzoffset(); 

    return $local_tp->strftime('%Y-%m-%d %H:%M:%S'); 
} 

、私は3/8に3/8と2のAM UTCに1時59分AMのUTCをしようとした場合、それは変更が発生していると考えますが、2 AM UTCが唯一の3/7であります午後9時。夏時間の切り替えから離れて、-5と-4のオフセットが正しく行われます。

DST not in effect: utc(2015-03-08 01:59:00.000) = local(2015-03-07 20:59:00) 
DST not in effect: utc(2015-03-08 02:00:00.000) = local(2015-03-07 22:00:00) 
+0

DSTの変更が午前2時に起こります東部標準時間ではなく、午前2時(UTC)ではありません。重要な秒は2015-03-08 01:59:59 EST(UTC-05:00)== 2015-03-08 06:59:59 UTCに続いて2015-03-08 03:00:00 EDT(UTC -04:00)== 2015-03-08 07:00:00 UTC。また、 'localtime'はあなたの現在のタイムゾーンを使用していますが、必ずしもあなたが*入っていたタイムゾーンではありません。 – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNot正しく、なぜそれが間違っているのか理解しています。 2番目の部分はここでは心配していません。データはすべて東部時間帯で生成されますが、より一般的な解決策としては良い点です。 – kchinger

答えて

3

$utc_tsは現地時間ではありません。

my $local_tp = localtime->strptime($utc_ts, '%Y-%m-%d %H:%M:%S'); 

my $utc_tp = Time::Piece->strptime($utc_ts, '%Y-%m-%d %H:%M:%S'); 

でなければなりませんそして、localtimeのために変換の問題があります。

$local_tp = $local_tp + $local_tp->tzoffset(); 

はすべて一緒に

my $local_tp = localtime($utc_tp->epoch); 

次のようになります。

#!/usr/bin/perl 
use strict; 
use warnings; 
use POSIX qw(); 
use Time::Piece; 

sub utc_to_local { 
    my ($utc_ts) = @_; 
    my $utc_tp = Time::Piece->strptime($utc_ts, '%Y-%m-%d %H:%M:%S'); 
    my $local_tp = localtime($utc_tp->epoch); 
    return $local_tp->strftime('%Y-%m-%d %H:%M:%S'); 
} 

sub local_to_utc { 
    my ($local_ts) = @_; 
    my $local_tp = Time::Piece->strptime($local_ts, '%Y-%m-%d %H:%M:%S'); 
    my $utc_tp = gmtime($local_tp->epoch); 
    return $utc_tp->strftime('%Y-%m-%d %H:%M:%S'); 
} 

{ 
    $ENV{TZ} = 'America/Toronto'; 
    POSIX::tzset(); 

    # DST not in effect 
    my $utc = '2015-03-08 06:59:00.000'; 
    my $local = utc_to_local(substr($utc, 0, -4)); 
    print "DST not in effect: utc($utc) = local($local)\n"; 

    # DST not in effect 
    $utc = '2015-03-08 07:00:00.000'; 
    $local = utc_to_local(substr($utc, 0, -4)); 
    print "DST not in effect: utc($utc) = local($local)\n"; 
} 

出力:

DST not in effect: utc(2015-03-08 06:59:00.000) = local(2015-03-08 01:59:00) 
DST not in effect: utc(2015-03-08 07:00:00.000) = local(2015-03-08 03:00:00) 
+0

素晴らしいです。私は考えていない普遍的な翻訳の一種として、時代からの秒数を使用していました。 – kchinger

関連する問題