Como posso analisar datas e converter fusos horários em Perl?
Pergunta
Eu usei o horário local Funcionar no Perl para obter a data e hora atuais, mas precisam analisar nas datas existentes. Eu tenho uma data de GMT no seguinte formato: "20090103 12:00" Eu gostaria de analisá -lo em um objeto de data com quem posso trabalhar e depois converter a hora/data GMT no meu fuso horário atual, que atualmente é o horário padrão do leste . Então, eu gostaria de converter "20090103 12:00" para "20090103 7:00" Qualquer informação sobre como fazer isso seria muito apreciada.
Solução
Como as interfaces de manuseio de data embutidas do Perl são meio desajeitadas e você acaba passando cerca de meia dúzia de variáveis, a melhor maneira é usar Data hora ou Relógio. O DateTime é o objeto de data prel de todos os quedas e todos os quesá-lo, e você provavelmente vai acabar por usá-lo, mas o tempo :: a peça é mais simples e perfeitamente adequada para esta tarefa, tem a vantagem de enviar com 5.10 e a técnica é Basicamente, o mesmo para ambos.
Aqui está a maneira simples e flexível usando o tempo :: peça e 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;
E aqui está o caminho da mão, por contraste.
Como o formato é corrigido, uma expressão regular se sairá bem, mas se o formato mudar, você precisará ajustar a regex.
my($year, $mon, $day, $hour, $min) =
$date =~ /^(\d{4}) (\d{2}) (\d{2})\ (\d{2}):(\d{2})$/x;
Em seguida, converta -o para o tempo da Epoch (segundos desde 1º de janeiro de 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);
E depois de volta à sua 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;
Outras dicas
Aqui está um exemplo, usando Data hora e os seus strptime Módulo de 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
Se você quisesse analisar a hora local, eis como você faria :)
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";
Isso é o que eu faria ...
#!/usr/bin/perl
use Date::Parse;
use POSIX;
$orig = "20090103 12:00";
print strftime("%Y%m%d %R", localtime(str2time($orig, 'GMT')));
Você também pode usar Time::ParseDate
e parsedate()
ao invés de Date::Parse
e str2time()
. Observe que o atm padrão de fato. Parece ser o DateTime (mas você pode não querer usar a sintaxe OO apenas para converter um registro de data e hora).
Faça sua escolha:
- Data hora::* (alternativamente, em DateTime.perl.org)
- Data :: Manip
- Data :: Calc (última atualização em 2004)
Há um zilhão de outros, sem dúvida, mas provavelmente são os principais candidatos.
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;