自从上周英国夏令时结束以来,我的应用程序就发现了一个非常有趣的错误。这是一个单独的 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 库中的错误吗?
最佳答案
看看 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
codepath 被命中,我猜在 Perl 中这意味着隐式返回 nil。我认为这个场景就是我的示例脚本所遇到的情况 - “欧洲/伦敦”在技术上不是 UTC,但它的偏移量仍然为 0。
更新
经过更多研究后,我发现同样的错误 has already been reported (2年前!)。该错误报告包含一个似乎可以解决该问题的补丁(尽管我还没有亲自测试过)。
更新2
修复此问题 has been released
关于perl - 为什么对于英国夏令时间之外的欧洲/伦敦日期,DateTime::Format::W3CDTF 返回 0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1647209/