To: | bug-datetime-format-strptime [...] rt.cpan.org |
Subject: | Minor bug in DateTime::Format::Strptime v1.05 |
From: | "Dave Faraldo" <dfaraldo [...] redhat.com> |
Date: | Fri, 27 Aug 2004 18:31:21 -0700 |
Hey there, Rick (or whoever reads the bug reports :).
I'm evangalizing the use of the DateTime modules here at Red Hat,
and wanted to do a demonstration of how easily they handle time
zones by showing edge cases. But I got an error when I tried
to parse the following date in the 'Asia/Manila' time zone:
epoch => 259344000,
str => 'Wed Mar 22 01:00:00 1978',
(This is the last time Manila switched to DST.)
The parse_datetime function died with:
Invalid local time for date in time zone: Asia/Manila
Eh??? I did a little poking, and found the problem. Around
line 443, you do some validation on the day of the month:
if ($Day) {
$self->local_croak("There is no use providing a day without providing a month and year.") and return undef unless $Year and $Month;
my $dt = DateTime->new(year=>$Year, month=>$Month, day=>$Day, time_zone => $use_timezone);
$self->local_croak("There is no day $Day in $dt->month_name, $Year") and return undef
unless $dt->month == $Month;
}
That DateTime->new() call, which assumes midnight on the specified
day/month/year, works for most days in most places ... but on March 22,
1978 in Manila, there *was* no midnight -- the local time jumped
from 11:59PM standard to 1AM DST! :)
I believe the following fixes the problem:
my $dt = DateTime->new(year=>$Year, month=>$Month, day=>$Day, hour=>12, time_zone => $use_timezone);
As far as I know, nobody does DST switchovers in the middle of the day.
Attached are a patch and a sample script. Thanks!
-=< Dave >=-
*** /usr/lib/perl5/site_perl/5.8.3/DateTime/Format/Strptime.pm Wed Aug 18 00:32:50 2004
--- DateTime/Format/Strptime.pm Fri Aug 27 18:27:40 2004
***************
*** 440,446 ****
: '';
if ($Day) {
$self->local_croak("There is no use providing a day without providing a month and year.") and return undef unless $Year and $Month;
! my $dt = DateTime->new(year=>$Year, month=>$Month, day=>$Day, time_zone => $use_timezone);
$self->local_croak("There is no day $Day in $dt->month_name, $Year") and return undef
unless $dt->month == $Month;
}
--- 440,446 ----
: '';
if ($Day) {
$self->local_croak("There is no use providing a day without providing a month and year.") and return undef unless $Year and $Month;
! my $dt = DateTime->new(year=>$Year, month=>$Month, day=>$Day, hour=>12, time_zone => $use_timezone);
$self->local_croak("There is no day $Day in $dt->month_name, $Year") and return undef
unless $dt->month == $Month;
}
#!/usr/bin/perl
use strict;
use warnings;
no warnings 'uninitialized';
use DateTime::Format::Strptime;
use POSIX qw(tzset);
my $FORMAT = '%a %b %e %T %Y';
my $ZONE = 'Asia/Manila';
my $formatter = DateTime::Format::Strptime->new(
pattern => $FORMAT,
time_zone => $ZONE,
);
# The last time Manila switched to DST (actual)
my $rec = {
epoch => 259344000,
str => 'Wed Mar 22 01:00:00 1978',
};
my $dt = $formatter->parse_datetime($rec->{'str'});