2009-01-04 59 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;