Subject: | DateTime->from_epoch loses precision when used with Time::HiRes |
Date: | Sat, 14 Jun 2014 21:06:14 +0400 |
To: | bug-DateTime [...] rt.cpan.org |
From: | Alexey Borzenkov <snaury [...] gmail.com> |
DateTime->from_epoch uses regexes to match floating point numbers and
this causes it to lose a lot of precision (tested on 64-bit Ubuntu
14.04). For example:
use DateTime;
use Time::HiRes;
foreach (1..10) {
printf("%09d\n", DateTime->from_epoch(epoch =>
Time::HiRes::time)->nanosecond);
}
This code would show that only the first 5 numbers are non-zero.
However, if the code is changed to:
use DateTime;
use Time::HiRes;
foreach (1..10) {
printf("%09d\n", DateTime->from_epoch(epoch => sprintf("%.9f",
Time::HiRes::time))->nanosecond);
}
Then it will show the full nanosecond precision, as expected.
I suspect that perl uses very little precision when stringifying
floating point numbers (can't seem to find how it does it in the
code), so by using regexes a lot of that precision is just lost. I
think DateTime should only use regexes for the integer part, but to
get to nanoseconds it should just substract the integer part from the
given epoch, e.g. something like this:
$args{nanosecond} = int(abs($p{epoch} - $int) * MAX_NANOSECONDS) if $dec;