如何在Perl中将date/时间转换为纪元时间(又名unix time – 1970年以来的秒数)?

给定date/时间作为(年,月,日,时,分,秒)数组,将如何将其转换为纪元时间,即自1970-01-01 00:00:00 GMT以来的秒数?

奖金问题:如果将date/时间作为一个string给出,您将如何首先将其parsing为(y,m,d,h,m,s)数组?

如果你使用的是DateTime模块,你可以调用DateTime对象的epoch()方法,因为这就是你所想象的unix时间。

使用DateTimes可以让你很容易地从纪元转换到date对象。

另外, localtime和gmtime会将一个纪元转换为一个包含日月和年的数组, Time :: Local模块中的 timelocal和timegm将做相反的处理,将时间元素(秒,分,…,天) ,月等)进入一个时代。

这是获取unix时间最简单的方法:

use Time::Local; timelocal($second,$minute,$hour,$day,$month-1,$year); 

请注意参数的相反顺序,1月份是月份0.有关更多选项,请参阅CPAN中的DateTime模块。

至于parsing,请参阅CPAN中的Date :: Parse模块。 如果你真的需要用dateparsing, Date :: Manip可能会有所帮助,虽然它自己的文档警告你远离它,因为它带有很多的包袱(它知道像普通的商业假期等)和其他解决scheme要快得多。

如果您碰巧知道date/时间的格式,那么可以使用一个简单的正则expression式,但是您最好使用适当的CPAN模块。 例如,如果您知道date将始终处于YMDHMS顺序,请使用CPAN模块DateTime :: Format :: ISO8601 。


对于我自己的参考,如果没有别的,下面是一个函数,我使用的应用程序,我知道date将始终在YMDHMS顺序全部或部分“HMS”部分可选。 它接受任何分隔符(例如“2009-02-15”或“2009.02.15”)。 它会返回相应的unix时间(自1970-01-01 00:00:00 GMT以来的秒数),如果无法parsing,则返回-1(这意味着您最好确保永远不会合法地parsingdate1969- 12-31 23:59:59)。 它也假定两位数的年份XX到69是指“20XX”,否则“19XX”(例如,“50-02-15”是指2050-02-15,但“75-02-15”是指1975- 02-15)。

 use Time::Local; sub parsedate { my($s) = @_; my($year, $month, $day, $hour, $minute, $second); if($s =~ m{^\s*(\d{1,4})\W*0*(\d{1,2})\W*0*(\d{1,2})\W*0* (\d{0,2})\W*0*(\d{0,2})\W*0*(\d{0,2})}x) { $year = $1; $month = $2; $day = $3; $hour = $4; $minute = $5; $second = $6; $hour |= 0; $minute |= 0; $second |= 0; # defaults. $year = ($year<100 ? ($year<70 ? 2000+$year : 1900+$year) : $year); return timelocal($second,$minute,$hour,$day,$month-1,$year); } return -1; } 

要parsing一个date,请看CPAN中的Date :: Parse 。

 $ENV{TZ}="GMT"; POSIX::tzset(); $time = POSIX::mktime($s,$m,$h,$d,$mo-1,$y-1900); 

从CPAN获取date:: Manip ,然后:

 use Date::Manip; $string = '18-Sep-2008 20:09'; # or a wide range of other date formats $unix_time = UnixDate( ParseDate($string), "%s" ); 

编辑:

Date :: Manip很大很慢,但parsing非常灵活,而且是纯粹的perl。 如果您在编写代码时很匆忙,可以使用它,并且您知道在运行代码时不会太急。

例如,使用它在启动时parsing命令行选项,但不要使用它在繁忙的Web服务器上parsing大量数据。

看作者的评论 。

(感谢下面第一条评论的作者)

我知道这是一个古老的问题,但我想我会提供另一个答案。

Time::Piece是Perl 5.9.5的核心

这允许通过strptime方法parsing任意格式的时间。

例如:

 my $t = Time::Piece->strptime("Sunday 3rd Nov, 1943", "%A %drd %b, %Y"); 

有用的部分是 – 因为它是一个重载的对象,你可以用它来进行数字比较。

例如

 if ( $t < time() ) { #do something } 

或者,如果您在string上下文中访问它:

 print $t,"\n"; 

你得到:

 Wed Nov 3 00:00:00 1943 

有一堆访问器方法允许一些其他有用的基于时间的变换。 https://metacpan.org/pod/Time::Piece

我最喜欢的date时间分析器是DateTime :: Format :: ISO8601一旦你有了这个工作,你将有一个DateTime对象,可以很容易地转换为时代秒(epoch)

CPAN上有许多Date操作模块。 我最喜欢的是DateTime ,你可以使用strptime模块以任意格式parsingdate。 CPAN上还有很多用于处理专用date格式的DateTime :: Format模块,但是strptime是最通用的。

为了进一步的参考,可以应用在例如!#/bin/sh脚本中。

 EPOCH="`perl -e 'use Time::Local; print timelocal('${SEC}','${MIN}','${HOUR}','${DAY}','${MONTH}','${YEAR}'),\"\n\";'`" 

只要记住要避免八进制值!

可能是“有更多的方法去做”的更好的例子之一,有或没有CPAN的帮助。

如果你可以控制你作为一个'date/时间'传递的东西,我会build议去DateTime路由,要么使用特定的Date :: Time :: Format子类,要么使用DateTime :: Format :: Strptime if没有一个支持你古怪的date格式(查看date时间常见问题的更多细节)。 一般来说,如果你想做一些严重的事情,Date :: Time就是要走的路,结果是:CPAN上的几门课非常具有肛门保守性和迷幻精确性。

如果你期望奇怪的自由格式的东西,把它扔在Date :: Parse的str2time()方法,这将给你一个秒钟以来的时代价值,你可以有你的邪恶的方式,没有date的开销: :Manip 。

在标准input上将各种ISO相关格式中的任何date(以及在阅读Mighty Kuhn 的着作之后使用什么其他内容)转换为标准输出中的时间为秒的时间的filter可以用于说明这两个部分:

 martind@whitewater:~$ cat `which isoToEpoch` #!/usr/bin/perl -w use strict; use Time::Piece; # sudo apt-get install libtime-piece-perl while (<>) { # date --iso=s: # 2007-02-15T18:25:42-0800 # Other matched formats: # 2007-02-15 13:50:29 (UTC-0800) # 2007-02-15 13:50:29 (UTC-08:00) s/(\d{4}-\d{2}-\d{2}([T ])\d{2}:\d{2}:\d{2})(?:\.\d+)? ?(?:\(UTC)?([+\-]\d{2})?:?00\)?/Time::Piece->strptime ($1, "%Y-%m-%d$2%H:%M:%S")->epoch - (defined ($3) ? $3 * 3600 : 0)/eg; print; } martind@whitewater:~$ 

如果你只是在寻找一个命令行工具(即不会从其他函数调用的东西),试试这个脚本。 它假定存在GNUdate(几乎存在于任何Linux系统上):

 #! /usr/bin/perl -w use strict; $_ = (join ' ', @ARGV); $_ ||= <STDIN>; chomp; if (/^[\d.]+$/) { print scalar localtime $_; print "\n"; } else { exec "date -d '$_' +%s"; } 

这是如何工作的:

 $ Time now 1221763842 $ Time yesterday 1221677444 $ Time 1221677444 Wed Sep 17 11:50:44 2008 $ Time '12:30pm jan 4 1987' 536790600 $ Time '9am 8 weeks ago' 1216915200