关于datetime:如何在Perl中将日期/时间转换为纪元时间(自1970年以来的unix时间/秒)?

关于datetime:如何在Perl中将日期/时间转换为纪元时间(自1970年以来的unix时间/秒)?

How do I convert a date/time to epoch time (unix time/seconds since 1970) in Perl?

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

额外问题:如果将日期/时间作为字符串给出,您将如何首先将其解析为(y,m,d,h,m,s)数组?


如果您正在使用DateTime模块,则可以在DateTime对象上调用epoch()方法,因为这就是您认为的unix时间。

使用DateTimes可以轻松地从纪元转换为日期对象。

另外,localtime和gmtime会将一个纪元转换为一个包含日月和年的数组,而来自Time :: Local模块的timelocal和timegm将反过来,转换一组时间元素(秒,分钟,......,天) ,几个月等)进入一个时代。


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

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

请注意参数的相反顺序,1月是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)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
}


要解析日期,请在CPAN中查看Date :: Parse。


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

Time::Piece是Perl 5.9.5的核心

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

例如。:

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

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

例如

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

或者,如果您在字符串上下文中访问它:

1
2
print $t,"
"
;

你得到:

1
Wed Nov  3 00:00:00 1943

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


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

从CPAN获取日期:: Manip,然后:

1
2
3
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脚本的一个衬里。

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

只记得避免八进制值!


CPAN上有许多日期操作模块。我特别喜欢的是DateTime,您可以使用strptime模块以任意格式解析日期。 CPAN上还有许多DateTime :: Format模块用于处理专用日期格式,但strptime是最通用的。


无论是否有CPAN的帮助,可能是"有多种方式去做"的更好例子之一。

如果您可以控制作为"日期/时间"传递的内容,我建议使用DateTime路由,使用特定的Date :: Time :: Format子类,或者使用DateTime :: Format :: Strptime if没有人支持您古怪的日期格式(有关详细信息,请参阅日期时间常见问题解答)。一般来说,如果你想对结果做任何严肃的事情,Date :: Time就是要走的路:CPAN上的几个课程都非常具有肛门保持性,并且过于准确。

如果你期待奇怪的自由形式的东西,把它扔到Date :: Parse的str2time()方法,这将获得一个秒 - 自 - 纪元值,然后你可以有你的邪恶的方式,没有Date :: Manip的开销。


我最喜欢的日期时间解析器是DateTime :: Format :: ISO8601一旦你有了这个工作,你将拥有一个DateTime对象,可以使用epoch()轻松转换为纪元秒


过滤器将标准输入的标准输入转换为秒 - 从标准输出的纪元时间转换为各种ISO相关格式的任何日期(以及谁在阅读Mighty Kuhn的着作后使用其他任何东西?)可能有助于说明这两个部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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:~$


如果您只是在寻找命令行实用程序(即,不会从其他函数调用的东西),请尝试使用此脚本。它假设存在GNU日期(存在于几乎任何Linux系统上):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#! /usr/bin/perl -w

use strict;

$_ = (join ' ', @ARGV);
$_ ||= <STDIN>;

chomp;

if (/^[\d.]+$/) {
    print scalar localtime $_;
    print"
"
;
}
else {
    exec"date -d '$_' +%s";
}

以下是它的工作原理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ 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


推荐阅读

    修改linux时间的命令?

    修改linux时间的命令?,时间,系统,命令,标准,大陆,国家,网上,资料,信息,时区,l

    linux更改时间命令?

    linux更改时间命令?,时间,系统,信息,大陆,国家,命令,环境,标准,上海,电脑,LIN

    linux时间等待命令?

    linux时间等待命令?,时间,系统,周期,工具,周期性,信息,服务,标准,暂停,单位,

    linux命令设置日期?

    linux命令设置日期?,时间,系统,命令,服务,大陆,信息,国家,时钟,终端,日期,详

    修改时间命令linux?

    修改时间命令linux?,时间,系统,命令,大陆,国家,信息,时区,终端,时分,日期,如

    linux上月时间命令?

    linux上月时间命令?,时间,系统,命令,日期,时钟,硬件,选项,格式,终端,分秒,详

    显示linux时间命令?

    显示linux时间命令?,时间,系统,信息,一致,命令,文件,终端,目录,选项,参数,lin

    获取linux时间命令行?

    获取linux时间命令行?,时间,系统,信息,命令,工具,工作,代码,数据,服务,环境,L

    linux查看时间命令行?

    linux查看时间命令行?,时间,系统,标准,命令,信息,单位,数字,管理,环境,发行,l

    linux显示时间命令?

    linux显示时间命令?,时间,系统,管理,标准,信息,单位,工具,数据,中国,命令,lin

    更改时间linux命令?

    更改时间linux命令?,时间,系统,命令,环境,网上,信息,资料,概念,位置,终端,lin

    更改时间linux命令?

    更改时间linux命令?,时间,系统,命令,环境,网上,信息,资料,概念,位置,终端,lin

    linux命令中时间格式?

    linux命令中时间格式?,时间,系统,命令,信息,工具,代码,工作,服务,标准,管理,l

    linux中日期相关命令?

    linux中日期相关命令?,时间,系统,信息,命令,代码,服务,工作,工具,终端,时分,l

    linux命令查询时间?

    linux命令查询时间?,时间,系统,状态,信息,数据,标准,地址,平台,环境,命令,在w

    linux命令行改时间?

    linux命令行改时间?,时间,系统,国家,大陆,命令,信息,服务,时区,终端,时分,使

    linux设日期时间命令?

    linux设日期时间命令?,时间,系统,命令,国家,环境,数据,电脑,标准,信息,大陆,l

    linux命令的执行时间?

    linux命令的执行时间?,时间,系统,周期,信息,命令,设备,环境,地址,基础,进程,l

    linux系统改日期命令?

    linux系统改日期命令?,时间,系统,信息,命令,终端,时分,窗口,操作系统,一下

    linux命令日期修改?

    linux命令日期修改?,时间,系统,电脑,信息,命令,标准,文件,终端,日期,时分,LIN