如何将一个日期/时间数组(year, month, day, hour, minute, second)转换成epoch时间,即1970-01-01 00:00:00 GMT以来的秒数?
附加问题:如果给出日期/时间字符串,如何首先解析为(y,m,d,h,m,s)数组?
如何将一个日期/时间数组(year, month, day, hour, minute, second)转换成epoch时间,即1970-01-01 00:00:00 GMT以来的秒数?
附加问题:如果给出日期/时间字符串,如何首先解析为(y,m,d,h,m,s)数组?
如果你正在使用 DateTime 模块,你可以在 DateTime 对象上调用 epoch() 方法,因为它就是你想要的 Unix 时间。
使用 DateTimes 可以相对容易地从 Unix 时间转换为日期对象。
或者,使用 localtime 和 gmtime 可以将 Unix 时间转换为一个包含日期、月份和年份的数组,而来自 Time::Local 模块 的 timelocal 和 timegm 则可以执行相反的操作,将时间元素(秒、分、...、日、月等)的数组转换为 Unix 时间。
获取Unix时间最简单的方法如下:
use Time::Local;
timelocal($second,$minute,$hour,$day,$month-1,$year);
注意参数的反向顺序,以及一月是第0个月。 如需更多选项,请参见来自CPAN的DateTime模块。
至于解析,请参见来自CPAN的Date::Parse模块。如果您确实需要在日期解析方面变得复杂,则Date::Manip可能会有所帮助,尽管其自身的文档警告您远离它,因为它包含许多功能(例如,它知道常见的商业假期),而其他解决方案要快得多。
如果您碰巧了解要解析的日期/时间格式,则简单的正则表达式可能足够了,但最好使用适当的CPAN模块。例如,如果您知道日期始终按YMDHMS顺序排列,请使用CPAN模块DateTime::Format::ISO8601。
对于我自己的参考,以下是我用于应用程序的函数,其中我知道日期始终按YMDHMS顺序排列,并且“HMS”部分全部或部分可选。它接受任何定界符(例如,“2009-02-15”或“2009.02.15”)。它返回相应的Unix时间(自1970-01-01 00:00:00 GMT以来的秒数),如果无法解析,则返回-1(这意味着您最好确定您永远不需要合法地解析日期1969-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;
}
虽然这已经是一个老问题了,但我想提供另一个答案。
Time::Piece
是 Perl 5.9.5 的核心模块。
通过 strptime
方法,可以解析任意格式的时间。
例如:
my $t = Time::Piece->strptime("Sunday 3rd Nov, 1943",
"%A %drd %b, %Y");
有用的部分是——由于它是一个重载对象,您可以将其用于数字比较。
例如:
if ( $t < time() ) { #do something }
如果您在字符串上下文中访问它:
print $t,"\n";
您将获得:
Wed Nov 3 00:00:00 1943
有一堆访问方法可以进行其他有用的基于时间的转换。 https://metacpan.org/pod/Time::Piece
$ENV{TZ}="GMT";
POSIX::tzset();
$time = POSIX::mktime($s,$m,$h,$d,$mo-1,$y-1900);
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很大而且速度较慢,但在解析方面非常灵活,并且它是纯perl编写的。如果你写代码时赶时间并且知道运行时不会赶时间,那么请使用它。
例如:在启动时仅使用它来解析命令行选项,但不要在繁忙的Web服务器上解析大量数据。
请参见作者的评论。
(感谢下面第一条评论的作者)
为了进一步参考,可以在例如!#/ bin / sh
脚本中应用的一行代码。
EPOCH="`perl -e 'use Time::Local; print timelocal('${SEC}','${MIN}','${HOUR}','${DAY}','${MONTH}','${YEAR}'),\"\n\";'`"
请记住避免使用八进制数值!
date -d "STRING" +%s
几乎可以接受任何东西,从“昨天”到“现在之后90天”,甚至更传统的日期格式如“2016年3月15日”,也可以输出到几乎任何格式(+%s
是时代,参见date --help
获取更多信息)。 (很遗憾,Perl DateTime
没有这个功能。) - Adam Katz我最喜欢的日期时间解析器是DateTime::Format::ISO8601。一旦你使用它,你就会得到一个DateTime对象,可以轻松地通过epoch()方法转换为epoch秒。
这是“有多种方法可以做到”的最好例子之一,无论是否使用CPAN的帮助。
如果你能控制传递给你的“日期/时间”内容,我建议使用DateTime,可以通过使用特定的Date::Time::Format子类或者使用DateTime::Format::Strptime(如果没有支持你的怪异日期格式的子类,请参阅datetime FAQ获取更多详细信息)。总的来说,如果你想在结果上做任何严肃的事情,那么Date::Time是正确的选择:CPAN上很少有类像它一样如此苛刻和精确。
如果你期望奇怪的自由形式内容,请将其传递给Date::Parse的str2time()方法,它会为你提供一个从时代开始的秒数值,你可以随心所欲地处理它,而不需要使用Date::Manip。
CPAN上有许多日期操作模块。我特别喜欢的是DateTime,你可以使用strptime模块来解析任意格式的日期。此外,在CPAN上还有许多DateTime::Format模块可用于处理专门的日期格式,但strptime是最通用的。