Kristian Flint wrote:
>This outputs "31-12-2008", which is in my mind is wrong.
This is about timezones. Look at other fields of the DateTime:
$ perl -lwe 'use Date::Manip; use DateTime::Format::DateManip;
$date=ParseDate("1st January 2009"); print $date; my $dt =
DateTime::Format::DateManip->parse_datetime($date); print $dt->dmy; print
$dt->hms; print $dt->time_zone_long_name'
2009010100:00:00
31-12-2008
23:00:00
Europe/London
$
This is what happens if your $TZ (or system default timezone) is
Europe/London. You can change it:
$ TZ=UTC perl -lwe 'use Date::Manip; use DateTime::Format::DateManip;
$date=ParseDate("1st January 2009"); print $date; my $dt =
DateTime::Format::DateManip->parse_datetime($date); print $dt->dmy; print
$dt->hms; print $dt->time_zone_long_name'
2009010100:00:00
01-01-2009
00:00:00
UTC
$
But it's more complicated than it looks, and downright weird in some
cases:
$ TZ=America/New_York perl -lwe 'use Date::Manip; use
DateTime::Format::DateManip; $date=ParseDate("1st January 2009"); print $date;
my $dt = DateTime::Format::DateManip->parse_datetime($date); print $dt->dmy;
print $dt->hms; print $dt->time_zone_long_name'
2009010100:00:00
31-12-2008
23:00:00
America/New_York
$ TZ=Australia/Sydney perl -lwe 'use Date::Manip; use
DateTime::Format::DateManip; $date=ParseDate("1st January 2009"); print $date;
my $dt = DateTime::Format::DateManip->parse_datetime($date); print $dt->dmy;
print $dt->hms; print $dt->time_zone_long_name'
2009010100:00:00
01-01-2009
00:00:00
America/New_York
$
What's happening is complicated.
DateTime::Format::DateManip->parse_datetime looks up the abbreviation that
the environmental timezone has now. Ultimately it tags the generated
DateTime object with a timezone that it works out (backwards) from this
abbreviation, which is why Australia/Sydney, with abbreviation "EST",
gets mapped to America/New_York. There's one bug.
The DateTime isn't created with that timezone to start with, though.
It's initially created with a fixed-offset timezone, for an offset worked
out (again backwards) from the timezone abbreviation. This offset is
what determines the interpretation of the (zoneless) calendar time that
you input. The DateTime then gets switched to its final timezone,
retaining the same absolute point in time. If the timezone has a
different offset now from what the current abbreviation suggested, this
causes a change in how the point in time is expressed. Second bug here.
Part of this is actually the fault of Date::Manip, which
DateTime::Format::DateManip calls out to. For example, this is utterly
the wrong timezone:
$ TZ=Australia/Sydney perl -MDate::Manip=UnixDate -lwe 'print
UnixDate("2009010100:00:00", "%Y-%m-%d %T %z %Z")'
2009-01-01 00:00:00 -0500 EST
$
And here the offset and abbreviation are for the current time, not the
time being displayed:
$ TZ=Europe/London perl -MDate::Manip=UnixDate -lwe 'print
UnixDate("2009010100:00:00", "%Y-%m-%d %T %z %Z")'
2009-01-01 00:00:00 +0100 BST
$
DateTime::Format::DateManip shares some of the blame, though, for
going through such complicated gyrations with timezones. Using the two
timezones and shifting between them is a definite bug. It looks like it
would work correctly if it just told DateTime to use the local timezone
and didn't ask Date::Manip about timezones at all.
>I suppose I should go look at the internals and submit a patch?
Go patch DT::F::DM, yes. Date::Manip seems to be beyond help.
-zefram