dateutils.IncMinute() can give wrong results (48h too old)

Original Reporter info from Mantis: Hartmut @Hartmut2
  • Reporter name:

Description:

Depending on the parameters dateutils.IncMinute() returns results, which are wrong by 48 hours, which is much. 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:
1899-12-27 23:00:00 = -3.95833 +60 mins => -2.00000 = 1899-12-28 00:00:00 (correct)
1899-12-26 23:00:00 = -4.95833 +60 mins => -5.00000 = 1899-12-25 00:00:00 (wrong)
1899-12-23 01:00:00 = -7.04167 -60 mins => -7.00000 = 1899-12-23 00:00:00 (correct)
1899-12-22 01:00:00 = -8.04167 -60 mins => -10.00000 = 1899-12-20 00:00:00 (wrong)

Line 1 is correct: starting from 1899-12-27 23:00 we add 60 minutes and get 1899-12-28 00:00.
Line 2 is wrong: starting from 1899-12-26 23:00 we add 60 minutes and get 1899-12-25 00:00 which is 48h too old (the correct result is 1899-12-27 00:00).
Line 3 is correct: starting from 1899-12-23 01:00 we subtract 60 minutes and get 1899-12-23 00:00.
Line 4 is wrong: starting from 1899-12-22 01:00 we subtract 60 minutes and get 1899-12-20 00:00 which is 48h too old (the correct result is 1899-12-22 00:00).

Steps to reproduce:

Run the attached demo:

{$mode objfpc}{$H+}

uses sysutils,dateutils;

procedure test(year,month,day,hour,mins: word; addmins: integer);
   {adds 'addmins' minutes to timestamp(year,month,day,hour) via IncMinute()}
   var t1,t2: TDateTime;
   begin
   t1:=EncodeDateTime(year,month,day,hour,mins,0,0);
   write(FormatDateTime('yyyy-mm-dd tt',t1), ' = ', t1:0:5, ' ');
   t2:=IncMinute(t1,addmins);
   if addmins >= 0 then write('+');
   writeln(addmins, ' mins => ', t2:9:5, ' = ', FormatDateTime('yyyy-mm-dd tt',t2));
   end;

begin
   {add 60 mins to 1899-12-27 23:00 => gives 1899-12-28 00:00 = is correkt: }
test(1899,12,27, 23,0, +60);
   {add 60 mins to 1899-12-26 23:00 => gives 1899-12-25 00:00 = 48h too old: }
test(1899,12,26, 23,0, +60);

   {sub 60 mins from 1899-12-23 01:00 => gives 1899-12-23 00:00 = is correkt: }
test(1899,12,23,  1,0, -60);
   {sub 60 mins from 1899-12-22 01:00 => gives 1899-12-20 00:00 = 48h too old: }
test(1899,12,22,  1,0, -60);
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).
Soon I will add a bug in dateutils.IncDay() which maybe has a similar root cause.

Mantis conversion info:

  • Mantis ID: 38424
  • OS: Windows
  • OS Build: Windows 7 32 bit
  • Platform: i386
  • Version: 3.2.0