2016-04-25 191 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點UTC凌晨1:59。UTC,它認爲已經發生了變化,但凌晨2點UTC只有3/7在9 PM。遠離夏令時轉換,它可以正確地進行-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點東部時間,而不是UTC 2:00 a.m.臨界秒數是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不正確,我明白爲什麼它是錯誤的,我只是不知道如何解決它。第二部分在這裏不是問題,數據全部在東部時區產生,但是爲更一般的解決方案提供了一個好點。 – 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