Subject: | DateTime issues at DST crossovers |
Have added a script outlining an example.
2009-03-29 01:00 - 02:00 is the transition period to DST for Europe/London.
Case 1 outlines subtracting hours where the result would lie in the
above 'non-existent' time range, this is handled fine, DateTime rolls
the time from 01:30 to 00:30.
Case 2 subtracts a month, where the result would lie in the above range,
DateTime throws an error. D=
Case 3 specifies a date in the invalid range, again DateTime throws an
error.
I understand why this happens, it's outlined in the DateTime docs :
http://search.cpan.org/~drolsky/DateTime-0.50/lib/DateTime.pm#Local_vs._UTC_and_24_hours_vs._1_day
But we only discovered this on subsequent investigation after our server
started throwing 500 errors. I guess you could argue I should have read
the docs thoroughly and spotted this but the DateTime docs are rather large!
I think the view currently taken by the maintainer on this, that the
date range doesn't actually exist so DateTime should throw an error, is
perfectly valid and arguably correct. But the problem with this
solution is that the user then has to be aware of this issue, and then
write code specifically to catch this.
As a suggestion, it might be useful to add a user settable flag to
DateTime which would cause DateTime to handle these dates safely and
return a value rather than erroring. Therefore allowing DateTime two
types of behaviour (safe/unsafe). Possibly expand these behaviour types
out so the date returned over the transition period is calculated is
various ways which again can be user-specified (round off etc..)
Subject: | timebug.pl |
#!/usr/bin/perl
use strict;
use DateTime;
print "VERSION : ".$DateTime::VERSION."\n";
my $dt;
print "=case 1=========================\n";
$dt = DateTime->new(
year => 2009,
month => 3,
day => 29,
hour => 2,
minute => 30,
time_zone => 'Europe/London'
);
print "DT : $dt\n";
eval { $dt->subtract( hours => 1 ); };
if($@) { print "ERROR\n"; } else { print "DT-1h : $dt\n"; }
print "=case 2=========================\n";
$dt = DateTime->new(
year => 2009,
month => 5,
day => 29,
hour => 1,
minute => 30,
time_zone => 'Europe/London'
);
print "DT : $dt\n";
$dt->subtract( months => 1 );
print "DT-1month : $dt\n";
eval { $dt->subtract( hours => 744); };
if($@) { print "ERROR\n"; } else { print "DT-2months : $dt\n"; }
print "=case 3=========================\n";
eval {
$dt = DateTime->new(
year => 2009,
month => 3,
day => 29,
hour => 1,
minute => 30,
time_zone => 'Europe/London'
);
};
if($@) { print "ERROR\n"; } else { print "DT : $dt\n"; }