2016-04-25 9 views
1

Ich habe eine Datei mit Zeitstempeln, die in der Vergangenheit liegen und alle in UTC sind. Ich muss diese in Eastern Time konvertieren. Ich bin nah dran, aber es dreht sich um die Umstellung der Sommerzeit.Historische Zeitstempel von UTC in Lokal umwandeln

#!/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'); 
} 

Wie Sie sehen können, wenn ich 1.59 UTC anprobieren 08.03 und 02.00 UTC auf 3/8, denkt, dass es die Änderung stattgefunden hat, aber 02.00 UTC ist nur 3/7 an 9 Uhr. Abgesehen von der Umstellung auf die Umstellung auf Sommerzeit werden die Einstellungen -5 und -4 korrekt korrigiert.

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

Der DST-Änderung bei 02.00 geschieht Eastern Zeit, nicht 2:00 Uhr UTC. Die kritischen Sekunden sind 2015-03-08 01:59:59 EST (UTC-05: 00) == 2015-03-08 06:59:59 UTC gefolgt von 2015-03-08 03:00:00 EDT (UTC -04: 00) == 2015-03-08 07:00:00 UTC. "Localtime" verwendet auch die Zeitzone, in der du dich gerade befindest, was nicht unbedingt die Zeitzone ist, in der du * warst. – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNot Richtig, ich verstehe, warum es falsch ist, ich weiß einfach nicht, wie ich es beheben kann. Und der zweite Teil ist hier kein Problem, die Daten werden alle in der östlichen Zeitzone generiert, aber ein guter Punkt für eine allgemeinere Lösung. – kchinger

Antwort

3

$utc_ts ist keine Ortszeit.

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

sollte

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

Dann gibt es noch das Problem auf lokale Zeit umzuwandeln.

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

sollte

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

Alle zusammen sein:

#!/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"; 
} 

Ausgang:

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

Ehrfürchtig, das hat funktioniert. Es benutzte die Sekunden seit der Epoche als eine Art universelle Übersetzung, an die ich nicht dachte. – kchinger