为什么DateTime :: Format :: W3CDTF在英国夏令时之外的欧洲/伦敦日期返回0?

时间:2009-10-29 23:38:45

标签: perl datetime timezone

自上周英国夏令时在英国结束以来,我的应用程序一直在看到一个非常有趣的错误。这是一个孤立的Perl脚本,它演示了这个问题:

#!/usr/bin/perl

use strict; use warnings;

use DateTime::Format::W3CDTF;
use DateTime::Format::ISO8601;

my $tz = 'Europe/London';

sub print_formatted_date {
  my $date = shift;

  my $tz_date = DateTime::Format::ISO8601->new->parse_datetime( $date );
  $tz_date->set_time_zone( $tz );

  print "tz_date:  $tz_date\n";
  $tz_date->set_formatter( DateTime::Format::W3CDTF->new );

  print "tz_date with W3C formatter: $tz_date\n";
}


print_formatted_date( '2009-10-25' );
print "\n";
print_formatted_date( '2009-10-26' );

这个输出是:

tz_date:  2009-10-25T00:00:00
tz_date with W3C formatter: 2009-10-25T00:00:00+01:00

tz_date:  2009-10-26T00:00:00
tz_date with W3C formatter: 0

请注意,对于超出BST的日期,W3C格式化程序将它们渲染为“0”。

这对我来说是个问题,因为我们使用的第三方库在SOAP调用期间使用DateTime :: Format :: W3CDTF来格式化参数。由于格式化失败,因此调用失败。

任何人都有线索吗?我不是Perl大师所以任何帮助都会非常感激。这可能是DateTime :: Format :: W3CDTF库中的错误吗?

1 个答案:

答案 0 :(得分:3)

看看W3CDTF的实现,我认为这实际上可能是库中的一个错误:

sub format_datetime
{
    my ( $self, $dt ) = @_;

    my $base = sprintf( '%04d-%02d-%02dT%02d:%02d:%02d',
        $dt->year, $dt->month, $dt->day,
        $dt->hour, $dt->minute, $dt->second );


    my $tz = $dt->time_zone;

    return $base if $tz->is_floating;

    return $base . 'Z' if $tz->is_utc;

    if (my $offset = $dt->offset()) {
        return $base . offset_as_string($offset );
    }
}

请注意,如果$tz->is_utc为false,但$dt->offset()为0,那么没有return代码路径被命中,我猜在Perl中意味着隐式返回了一个nil。我认为这种情况是我的示例脚本所针对的 - “欧洲/伦敦”在技术上不是UTC,但它的偏移量仍为0。

<强>更新

经过一番研究后,我发现了同样的错误has already been reported(2年前!)。错误报告包含一个似乎可以解决问题的补丁(虽然我没有亲自测试过。)

更新2

has been released

的修复程序