perl - 如何获取 DateTime::Format::Strptime 来解析闰秒的日期/时间?

标签 perl

我正在尝试使用 DateTime::Format::Strptime 来解析一些日期/时间,但我似乎无法让它解析闰秒的日期/时间(例如,2012-06-30T23:59:60UTC)。文档称它支持长达 60 秒的闰秒。我做错了什么?

这是我的代码:

use DateTime;
use DateTime::TimeZone;
use DateTime::Format::Strptime;

my $utc = DateTime::TimeZone->new(name => 'Etc/UTC');

my $ymdhms_parser = DateTime::Format::Strptime->new(pattern => '%F %T',
                                                    locale => 'en_US',
                                                    time_zone => $utc,
                                                    strict => 1,
                                                    on_error => 'croak');

my $date = '2012-06-30 23:59:60';
print "date: $date\n";
my $dt = $ymdhms_parser->parse_datetime($date);
print "dt: $dt\n";
print "tz: ",$dt->time_zone,"\n";

我得到的输出是:

date: 2012-06-30 23:59:60
Parsed values did not produce a valid date at /path/to/test.pl line 14.

版本:

DateTime 1.52
DateTime::LeapSecond 1.52
DateTime::Format::Strptime 1.77

最佳答案

以下内容按预期工作:

my $dt = DateTime->new(
   year      => 2012,
   month     =>    6,
   day       =>   30,
   hour      =>   23,
   minute    =>   59,
   second    =>   60,
   time_zone => $utc,
);

但是,对 parse_datetime 的调用实际上执行了以下操作:

my $dt = DateTime->new(
   year      => 2012,
   month     =>    6,
   day       =>   30,
   hour      =>   23,
   minute    =>   59,
   second    =>   60,
   time_zone => 'floating',
);

$dt->set_time_zone($utc);

上述结果导致 DateTime->new 抛出异常,从而导致收到错误消息。

但我不能责怪 DateTime::Format::Strptime。

在正在解析的字符串中找到的时区(例如,如果使用 %z )将传递给 ->new,并将时区传递给构造函数被传递到->set_time zone。这允许在两个地方都指定时区时发生时区转换。

例如,假设输入为 2020-03-25T00:00:00-05:00 (注意偏移量)。假设您向构造函数传递了 time_zone => 'UTC' 和适当的模式。生成的 DateTime 对象将是 UTC 凌晨 5 点,而不是午夜 UTC-05:00。这很好。

<小时/>

有趣的是,可以使用 60 秒的 float 时区创建 DateTime 对象。

$ perl -MDateTime -e'
   CORE::say
      DateTime
         ->new(
            year      => 2012,
            month     =>    6,
            day       =>   30,
            hour      =>   23,
            minute    =>   59,
            second    =>   60,
            time_zone => "UTC",
         )
            ->set_time_zone("floating");
'
2012-06-30T23:59:60

但是 DateTime 与允许它不一致。

$ perl -MDateTime -e'
   CORE::say
      DateTime
         ->new(
            year      => 2012,
            month     =>    6,
            day       =>   30,
            hour      =>   23,
            minute    =>   59,
            second    =>   60,
            time_zone => "floating",
         );
'
Invalid second value (60)
 at -e line 1.

Bug ticket filed.

<小时/>

作为解决方法,请在正在解析的数据中包含时区。

my $ymdhms_parser = DateTime::Format::Strptime->new(
   pattern  => '%F %T%z',
   locale   => 'en_US',
   strict   => 1,
   on_error => 'croak',
);

my $dt = $ymdhms_parser->parse_datetime($date.'Z');

关于perl - 如何获取 DateTime::Format::Strptime 来解析闰秒的日期/时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60836745/

相关文章:

perl - 为什么 $main::_ 在映射或 for 循环中使用时引用词法 $_?

perl - 如何在 Perl 中获取 Windows 上的系统用户全名?

perl - 在 DBI 准备中重用 ?

perl - 显式 "use"-ing 各种 Perl 版本的后果是什么?

perl - 如何从 Perl 设置文件权限?

javascript - 在 javascript 中使用文件名和计划函数调用

perl - 从脚本中,在远程服务器上运行脚本并获取其输出

regex - 这个 perl 正则表达式有什么问题?

perl - "use diagnostics;"有问题吗?

计算下一个 ASCII 字符的 Linux 命令或 Bash 语法