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
有助于改进我的理论或提供更简单的方法吗?
答案 0 :(得分:0)
由于仅在小时设置为零时才发生错误,因此必须始终将小时设置为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