Perl 日期时间截断在落入 DST 时移时失败


use DateTime;
use DateTime::TimeZone;
my $dt = DateTime->new( {
               year => 2014, month => 10,  day => 19, 
               hour => 2,  minute=> 2,  second=> 0
});
$dt->set_time_zone(DateTime::TimeZone->new( name => 'America/Sao_Paulo' ));
$dt->truncate(to => 'day');

失败,消息Invalid local time for date in time zone: America/Sao_Paulo

因为2014-10-19 00:00:00不是America/Sao_Paulo时区中的有效时间。最终结果应该是2014-10-19 01:00:00 .

我的伪代码理论

Try to truncate directly to the datetime object inside an eval
IF fails
   IF the truncation level is "day"
      -1 day 
      truncate
      + seconds of a day
   IF the truncation level is "month"
      -1 month 
      truncate
      seconds of a month. <--- Now here I need to take care of seconds of every month and even leapyear
 ELSE im happy

有什么帮助来改进我的理论或提供更简单的方法吗?

由于错误仅在小时设置为零时发生,因此更正必须始终是将小时设置为 1。除午夜外,时间变化的区域不会有问题。

这意味着您可以编写这样的简单异常处理程序。

我很想说,没有区域在一个月的第一天开始夏令时,所以截断到月份时不应该出现问题。但我不能保证这一点,所以我也为此编写了一个块。

use strict;
use warnings;
use 5.010;
use DateTime;
use DateTime::TimeZone;
use Try::Tiny;
my $dt = DateTime->new( {
    year => 2014, month => 10,  day => 19, 
    hour => 2,  minute=> 2,  second=> 0
});
my $sao_paolo = DateTime::TimeZone->new( name => 'America/Sao_Paulo' );
$dt->set_time_zone($sao_paolo);
try {
  $dt->truncate(to => 'day');
}
catch {
  die $_ unless /Invalid local time for date/;
  $dt->truncate(to => 'hour');
  $dt->set({hour => 1});
};
say $dt;
try {
  $dt->truncate(to => 'month');
}
catch {
  die $_ unless /Invalid local time for date/;
  $dt->truncate(to => 'hour');
  $dt->set({day => 1, hour => 1});
};
say $dt;

输出

2014-10-19T01:00:00
2014-10-01T00:00:00

相关内容

  • 没有找到相关文章

最新更新