I'm experiencing some very odd behavior with DateTime, which I'm at a
loss to understand...
I have a subroutine that uses two DateTime objects. It calls delta_ms()
to get the delta between the two objects, does a bit of math, then calls
add() to add the delta to one of the objects. Although both objects are
created with time_zone => local, occasionally the result is 4 hours
ahead of what I expect (which would correspond to UTC).
Suppose the current date/time is 2009-10-23 13:15:43.
I call next_delivery_date('2009-10-23 13:15:00', 'every 1 minutes').
I would expect to get back '2009-10-23 13:16:00'. However, sometimes, I
get '2009-10-23 17:16:00' instead, four hours in the future.
Here's the code (minus the handling for other schedule formats):
sub next_delivery_date {
my ($current_delivery_date, $schedule) = @_;
my %tmp;
@tmp{qw/ year month day hour minute second /} =
$current_delivery_date =~ /(\d+)/g;
my $dt = DateTime->new(%tmp, time_zone => 'local');
# determine the date/time for the next delivery,
# based on the existing delivery date/time and the schedule
my ($quantity, $unit);
if ($schedule =~ /^every (\d+) ([a-z]+)\z/) {
# at the specified duration
($quantity, $unit) = ($1, $2);
} else {
die "Unrecognized delivery schedule '$schedule'";
}
my $now = DateTime->now(time_zone => 'local');
# jump ahead rather than doing repeated adds,
# in case the current delivery date is far in the past
my $delta = 0;
if ($unit eq 'minutes') {
$delta = $now->delta_ms($dt)->{$unit};
} elsif ($unit eq 'days') {
$delta = $now->delta_days($dt)->{$unit};
}
my $add = 0;
if ($delta > $quantity) {
$add = $delta - ($delta % $quantity);
}
$dt->add($unit => $add);
# make sure the new delivery date is in the future
while ($dt < $now) {
$dt->add($unit => $quantity);
}
$dt->set(second => 0);
return $dt->ymd . ' ' . $dt->hms;
}
Some background on the program: I have various delivery events that
happen on specific schedules, such as 'every 1 minutes' or 'daily
08:00'. My program runs as a daemon, checking for delivery events that
need to be run. For each one, it forks off a child process. The child
process runs the delivery event, then calculates the next date/time that
event should be run.
Anyone have any ideas what could be causing this?
Ronald