dateutils.IncDay() can give wrong results (24h too old)
Original Reporter info from Mantis: Hartmut @Hartmut2
-
Reporter name:
Original Reporter info from Mantis: Hartmut @Hartmut2
- Reporter name:
Description:
Depending on it's parameters dateutils.IncDay() returns results, which are wrong by 24 hours, which is much, especially if the time part is zero (which normally should reduce the risk of rounding errors).
Here I give 2 examples which fail, but there exist many more. Please look at the attached demo, which includes 4 tests: 2 which give correct results (only to demonstrate how the test works) and 2 tests, which give wrong results.
The output of the demo shows 4 tests:
1.00000 -8192 days => -8.1910000000000000E+003 fault= 0.0000000000000000E+000 (correct)
1.00000 -8193 days => -8.1930000000000000E+003 fault=-1.0000000000000000E+000 (wrong)
55.00000 -8246 days => -8.1910000000000000E+003 fault= 0.0000000000000000E+000 (correct)
55.00000 -8247 days => -8.1930000000000000E+003 fault=-1.0000000000000000E+000 (wrong)
Line 1 is correct: starting from TDateTime(1.0) wie subtract 8192 days and get -8191.0
Line 2 is wrong: starting from TDateTime(1.0) wie subtract 8193 days and get -8193.0 which is 24h too old (the correct result is -8192.0)
Line 3 is correct: starting from TDateTime(55.0) wie subtract 8246 days and get -8191.0
Line 4 is wrong: starting from TDateTime(55.0) wie subtract 8247 days and get -8193.0 which is 24h too old (the correct result is -8192.0)
From what I've seen until now it can be, that this bug occurs predominantly,
- if IncDay() has to "add" negative days and
- if the starting timestamp is positive and
- if the resulting timestamp is negative
Steps to reproduce:
Run the attached demo:
{$mode objfpc}{$H+}
uses dateutils;
procedure test(t1: TDateTime; days: longint);
{adds 'days' days to 't1' via IncDay()}
var t2,fault: TDateTime;
begin
write(t1:8:5, ' '); if days >= 0 then write('+');
write(days, ' days => ');
t2:=IncDay(t1,days);
fault:=t2-t1-days; {check if result is correct}
writeln(t2, ' fault=', fault);
end;
begin
{subs 8192 days from '1.0' => gives -8191.0 = is correkt: }
test( 1.0, -8192);
{subs 8193 days from '1.0' => gives -8193.0 = 24h too old: }
test( 1.0, -8193);
{subs 8246 days from '55.0' => gives -8191.0 = is correkt: }
test(55.0, -8246);
{subs 8247 days from '55.0' => gives -8193.0 = 24h too old: }
test(55.0, -8247);
end.
Additional information:
This bug is reproduceable with FPC 3.2.0 on Windows 7 32-bit and Linux Ubuntu 18.04 64-bit.
My CPU is an Intel Core i3-3220 (if that could matter for rounding errors).
I recently added a bug in dateutils.IncMinute() = https://bugs.freepascal.org/view.php?id=38424 which maybe has a similar root cause.
Mantis conversion info:
- Mantis ID: 38425
- OS: Windows
- OS Build: 7 (32 bit)
- Platform: i386
- Version: 3.2.0