Subject: | string-to-jd followed by parse-from-jd results in a 1-second difference |
One takes a DatimeTime object and converts it into a JD real, using
DateTime::Format::Epoch::JD->parse_datetime($my_datetime_object);
Then the real is converted back to a DateTime object.
In half of cases, the resulting DateTime object is shifted by 1 second as compared to the original DateTime object.
Seen with DateTime::Format::Epoch::JD but presumably, same bugs exists on other formats, so long as they carry time information (= JD-like number has a fractional part).
I attached to this bug entry 2 files:
- The patch (.patch extension) to fix DateTime/Format/Epoch.pm file
- The test case (.t extension) to check whether or not the issue occurs
Best Regards, Sébastien Millet
Subject: | Epoch.patch |
--- Epoch.pm 2016-09-05 15:27:57.433691100 +0200
+++ Epoch_updated.pm 2016-09-05 15:47:37.011491100 +0200
@@ -149,7 +149,7 @@
$str -= $delta_days * 86_400 * $self->{unit};
# $str cannot be negative now, so int() instead of _floor()
- my $delta_secs = int( $str / $self->{unit} );
+ my $delta_secs = int( $str / $self->{unit} + 0.5 );
$str -= $delta_secs * $self->{unit};
my $delta_nano = $str / $self->{unit} * 1e9;
Subject: | usecase-DateTime-Format-Epoch-JD.t |
#!/usr/bin/perl
# usecase-DateTime-Format-Epoch-JD.t
# Use case to check the
#
# DateTime -> JD -> DateTime
#
# conversion round-trip that sometimes produces a 1-second shift due to a
# round error in DateTime/Format/Epoch.pm module code.
#
# As it is an error that occurs every time the fractional part is in the range
# [0, 0.5[, it occurs in average 50% of the time.
#
# Sébastien Millet, 5th September 2016
# milletseb@laposte.net
use strict;
use warnings;
use DateTime::Format::Epoch::JD;
use Test::More tests => 3;
my $dt_orig = DateTime->new(
year => 2016, month => 9, day => 5,
hour => 13, minute => 28, second => 31
);
is($dt_orig . '', '2016-09-05T13:28:31', 'Check original DateTime');
my $jd = DateTime::Format::Epoch::JD->format_datetime($dt_orig);
is($jd, 2457637.06146991,
'Check Julian Day real calculated from original DateTime');
my $dt_from_jd = DateTime::Format::Epoch::JD->parse_datetime($jd);
is($dt_from_jd . '', '2016-09-05T13:28:31',
'Check Julian Day real converted back to DateTime');
done_testing();