2009-01-04 22 views
26

我在Perl中使用了localtime函数来获取当前日期和时间,但需要解析现有日期。我有以下格式的GMT日期:“20090103 12:00”我想将它解析成我可以使用的日期对象,然后将GMT时间/日期转换为当前时区,即当前的东部标准时间。所以我想将“20090103 12:00”转换为“20090103 7:00”,关于如何做到这一点的任何信息将不胜感激。如何解析日期并在Perl中转换时区?

+0

另见:http:// stackoverflow。问题/ 95492 /我怎么做 - 我 - 转换日期 – dreeves 2009-01-05 20:53:18

+0

检查这些: [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 2011-12-08 05:14:39

回答

44

因为内置在日期处理接口中的Perl有点笨拙,你最终会传递大约六个变量,所以更好的方法是使用DateTimeTime::Piece。 DateTime是全部歌曲,全部跳舞的Perl日期对象,并且您可能最终想要使用它,但Time :: Piece更简单且完全适合此任务,具有5.10版本的优势,并且该技术是两者基本相同。

下面是使用Time :: Piece和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; 

这就是对比的方式。

由于格式是固定的,正则表达式可以做得很好,但是如果格式发生变化,您必须调整正则表达式。

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

然后将其转换为Unix时代时间(自1月1秒钟,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); 

然后回本地时间。

(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

即使在自己编译时,也可以在Unix和Windows系统上使用POSIX qw(strftime)`,至少从Perl 5.6.0开始。这样可以让最终的“roll-your-own”变得既简短又可维护:`my $ local_date = strftime“%y%m%d%H:%M \ n”,localtime($ time);`。 – pjf 2009-01-04 23:39:25

+3

$ time-> localtime-> tzoffset AFAICT返回当前时间的偏移量,而不是给定的时间。 – ysth 2009-01-05 00:44:00

4

任你选:

还有数不胜数的人,毫无疑问,但他们可能是最有力的竞争者。

+0

Date:Calc在2009年有相当多的活动。 – rlandster 2012-10-15 15:41:42

+0

但我不认为活动发生在2009年1月4日,当时我写了评论。但是,知道它正在维护是很好的。随着Perl的进步,良好的稳定模块并不一定需要太多工作。 – 2012-10-15 15:44:36

21

下面是一个例子,使用DateTime及其strptime格式模块。

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 


如果你本来想本地时间分析,这里是你会怎么办呢:)

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"; 
5

这就是我想要做的......

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

$orig = "20090103 12:00"; 

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

你也可以使用Time::ParseDateparsedate()而不是Date::Parsestr2time()。请注意,事实上的标准atm。似乎是DateTime(但您可能不想使用OO语法来转换时间戳)。

-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;