Zefram schreef:
> It ought to be possible to do the interval calculation using
> DateTime::Duration instead of ->epoch, but the behaviour of DT::D is
> unreasonably confusing and I couldn't get it to work. (Strangely, I got
> a version that worked fine for America/New_York, where all the days are
> integer numbers of hours, but lost the fractional hour of 2007-12-09 in
> America/Caracas, which was 24.5 hours long.)
DateTime cannot handle fractional leap hours.
See the source code of subtract_datetime(), section "This is a gross
hack", where the length of the leap hour is hardcoded in the lines
$bigger_min -= 60
$bigger_min += 60
This should probably be changed, but datetime math is scary.
As a workaround, convert the time to UTC. (This does not work in all
cases, but for this purpose, it does.
use DateTime;
for my $doy (340..345) {
# The default time is 00:00:00
my $day = DateTime->from_day_of_year(
year => 2007, day_of_year => $doy,
time_zone => 'America/Caracas') or die;
# To find the end of the day, add 1 day to get 00:00:00 tomorrow
my $end_of_day = $day->clone->add( days => 1 );
# Workaround for Venezuela.
$day->set_time_zone('UTC');
$end_of_day->set_time_zone('UTC');
# Standard subtraction would result in a duration of 1 day, so we
# use delta_ms() which results in a duration without the "days"
# component. It is expressed entirely in minutes, which can be
# converted to hours.
my $hours = $end_of_day->delta_ms($day)->delta_minutes / 60;
print $day, " has $hours hours.\n";
}
Eugene