CC: | datetime [...] perl.org |
Subject: | [PATCH] sub-second precision and rounding |
Maintainers of DateTime,
DateTime goes to some lengths to be consistent when doing
"mathematics". This is very helpful. At one point, however,
I see it breaking a pattern for no good reason.
The pattern I am referring to is that dates and durations are
split into units and sub-units (of various sizes) where units
are *truncated* to whole numbers, and sub-units represent the
finer-grained remainder if there is any. For example, a time
"shortly before noon" is modeled with an hour value of 11,
not 12, as the fractional part of the hour will be stored in
(non-negative) minutes, seconds etc.
Starting with DateTime-0.67, this pattern is broken where
fractions of seconds are involved. $dt->millisecond gives a
*rounded* value for the 1000th part of a second, which is not
documented but checked in the test suite, and $dt->microsecond
gives a *rounded* value for the millionth part of a second,
which is documented but not less strange.
It seems that this weirdness was introduced in an attempt to
fix a rounding error in from_epoch, pointed out by Michael
R. Davis in RT #66744. The root cause of this error made a
second appearance in RT #67736 (reported by Zefram) and was
properly taken care of soon after in DateTime-0.68.
I would like to encourage you to revert the rounding behaviour
of milli- and microseconds back to truncating (patch enclosed).
It is funny that DateTime math should achieve consistency
dealing with the most messy details of our calendar and fail
to do so with its only metric component. Rectifying this also
relieves DateTime from a non-core dependency.
To demonstrate that the current rounding behaviour is not
quite thought through, try:
use DateTime 0.76;
my $d = DateTime->new(
year => 2012,
month => 9,
day => 25,
hour => 12,
minute => 39,
second => 59,
nanosecond => 999876000,
time_zone => 'Europe/Berlin',
);
print $d->strftime('%H:%M:%S.%3N'), "\n";
This will print "12:39:59.1000" rather than "12:39:59.999".
And no, please don't make it print "12:40:00.000" either.
Rounding is just not the right thing to do by default.
-Martin
[Cc to the mailing list as this might call for some discussion]