首页 文章

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

提问于
浏览
40

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

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

12 回答

  • 2

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

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

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

  • 7

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

    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) .

    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;
    }
    
  • 19

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

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

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

    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

  • 6

    Get Date::Manip from CPAN,然后:

    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服务器上解析大量数据 .

    the authors comments .

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

  • 2

    我最喜欢的日期时间解析器是DateTime::Format::ISO8601一旦你've got that working, you'将有一个DateTime对象,可以使用epoch()轻松转换为纪元秒

  • 7

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

  • -3

    为了进一步参考,可以应用于例如 !#/bin/sh 脚本的单个衬垫 .

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

    只记得避免八进制值!

  • 2

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

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

    如果你期待奇怪的自由形式的东西,把它扔到Date::Parse 's str2time() method, which' ll得到一个秒 - 自 - 纪元的 Value 你可以用你的邪恶方式,而没有Date::Manip的开销 .

  • -4

    在标准输入上将标准输入上的任何日期(以及在使用Mighty Kuhn的the writings之后使用其他任何东西?)转换为标准输出的自纪元时间之后的过滤器可能用于说明这两个部分:

    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:~$
    
  • 2

    如果您只是在寻找命令行实用程序(即,不是可以从其他函数调用的东西),请尝试使用此脚本 . 它假设存在GNU日期(存在于几乎任何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
    

相关问题