2009-01-04 10 views
26

He utilizado la función localtime en Perl para obtener la fecha y hora actual pero necesito analizar en las fechas existentes. Tengo una fecha GMT en el siguiente formato: "20090103 12:00" Me gustaría analizarlo en un objeto de fecha con el que puedo trabajar y luego convertir la hora/fecha GMT en mi zona horaria actual, que actualmente es hora estándar del este . Así que me gustaría convertir "20090103 12:00" a "20090103 7:00". Cualquier información sobre cómo hacer esto sería muy apreciada.¿Cómo puedo analizar las fechas y convertir las zonas horarias en Perl?

+0

Ver también: http: // stackoverflow.com/questions/95492/how-do-i-convert-a-date – dreeves

+0

Verifique esto: [http://www.bestofperl.com/how-tos/timezone-conversion-date-time](http://) www.bestofperl.com/how-tos/timezone-conversion-date-time) [http://www.bestofperl.com/how-tos/parsing-datetime-strings](http://www.bestofperl.com/how-tos/parsing-datetime-strings) – Pradeep

Respuesta

44

Debido a que las interfaces de manejo de fechas integradas de Perl son un tanto torpes y se termina pasando alrededor de media docena de variables, la mejor manera es usar ya sea DateTime o Time::Piece. DateTime es el objeto de fecha Perl que canta y baila, y es probable que quieras usarlo, pero Time :: Piece es más simple y perfectamente adecuado para esta tarea, tiene la ventaja de enviarlo con 5.10 y la técnica es básicamente lo mismo para ambos.

Esta es la manera simple y flexible de utilizar Time :: Piece y strptime.

#!/usr/bin/perl 

use 5.10.0; 

use strict; 
use warnings; 

use Time::Piece; 

# Read the date from the command line. 
my $date = shift; 

# Parse the date using strptime(), which uses strftime() formats. 
my $time = Time::Piece->strptime($date, "%Y%m%d %H:%M"); 

# Here it is, parsed but still in GMT. 
say $time->datetime; 

# Create a localtime object for the same timestamp. 
$time = localtime($time->epoch); 

# And here it is localized. 
say $time->datetime; 

Y aquí está la forma manual, para el contraste.

Dado que el formato es fijo, una expresión regular funcionará correctamente, pero si el formato cambia, deberá ajustar la expresión regular.

my($year, $mon, $day, $hour, $min) = 
    $date =~ /^(\d{4}) (\d{2}) (\d{2})\ (\d{2}):(\d{2})$/x; 

luego convertirlo en cuando Epoch Unix (segundos desde el 1 de Ene, 1970)

use Time::Local; 
# Note that all the internal Perl date handling functions take month 
# from 0 and the year starting at 1900. Blame C (or blame Larry for 
# parroting C). 
my $time = timegm(0, $min, $hour, $day, $mon - 1, $year - 1900); 

y luego de vuelta a su hora local.

(undef, $min, $hour, $day, $mon, $year) = localtime($time); 

my $local_date = sprintf "%d%02d%02d %02d:%02d\n", 
    $year + 1900, $mon + 1, $day, $hour, $min; 
+4

Incluso al rodar uno propio, uno puede 'usar POSIX qw (strftime)' en sistemas Unix y Windows desde al menos Perl 5.6.0 en adelante. Eso permite que el "roll-your-own" final se convierta en el más corto y más fácil de mantener: 'my $ local_date = strftime"% Y% m% d% H:% M \ n ", localtime ($ time);'. – pjf

+3

$ time-> localtime-> tzoffset AFAICT devuelve el desplazamiento para la hora actual, no el tiempo dado. – ysth

+0

@ysth Sí, y eso está bien a menos que deseemos preocuparnos por los cambios históricos en la zona horaria, lo que seguro no es cierto. El horario de verano podría ser importante. – Schwern

4

una serie de opciones:

Hay un trillón de otros, sin duda, pero probablemente sean los principales contendientes.

+0

Fecha :: Calc tuvo bastante actividad en 2009. – rlandster

+0

Pero no creo que la actividad haya tenido lugar el 4 de enero de 2009 cuando escribí ese comentario. Sin embargo, es bueno saber que se está manteniendo. Los buenos módulos estables no necesariamente necesitan mucho trabajo a medida que Perl progresa. –

21

He aquí un ejemplo, usando DateTime y su módulo strptime formato.

use DateTime; 
use DateTime::Format::Strptime; 

my $val = "20090103 12:00"; 

my $format = new DateTime::Format::Strptime(
       pattern => '%Y%m%d %H:%M', 
       time_zone => 'GMT', 
       ); 

my $date = $format->parse_datetime($val); 

print $date->strftime("%Y%m%d %H:%M %Z")."\n"; 

$date->set_time_zone("America/New_York"); # or "local" 

print $date->strftime("%Y%m%d %H:%M %Z")."\n"; 

$ perl dates.pl 
20090103 12:00 UTC 
20090103 07:00 EST 


Si se hubiera querido analizar hora local, así es como usted lo haría :)

use DateTime; 

my @time = (localtime); 

my $date = DateTime->new(year => $time[5]+1900, month => $time[4]+1, 
       day => $time[3], hour => $time[2], minute => $time[1], 
       second => $time[0], time_zone => "America/New_York"); 

print $date->strftime("%F %r %Z")."\n"; 

$date->set_time_zone("Europe/Prague"); 

print $date->strftime("%F %r %Z")."\n"; 
+0

¿Y qué pasa con esto? –

+0

Falta la parte de análisis. – Schwern

+0

Oh, cierto. Supuse equivocadamente que quería usar la salida de tiempo local. –

5

Eso es lo que haría ...

#!/usr/bin/perl 
use Date::Parse; 
use POSIX; 

$orig = "20090103 12:00"; 

print strftime("%Y%m%d %R", localtime(str2time($orig, 'GMT'))); 

Usted también puede usar Time::ParseDate y parsedate() en lugar de Date::Parse y str2time(). Tenga en cuenta que la atmósfera estándar de facto. parece ser DateTime (pero es posible que no desee utilizar la sintaxis OO solo para convertir una marca de tiempo).

+0

Este es FTW. –

-2
use strict; 
use warnings; 
my ($sec,$min,$hour,$day,$month,$year)=localtime(); 
$year+=1900; 
$month+=1; 
$today_time = sprintf("%02d-%02d-%04d %02d:%02d:%02d",$day,$month,$year,$hour,$min,$sec); 
print $today_time; 
+0

Este código solo imprime la hora local actual. No responde la pregunta. – nwellnhof

Cuestiones relacionadas