Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2008-12

DateTimeToUnix bug?

6 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Seth Grover

I thought I'd get feedback here before I log this as a bug:

==================================================
program Project1;

uses
Classes,
SysUtils,

  DateUtils;
var
  utime  : longword;
  currentDt : TDateTime;
  convertedDt : TDateTime;
begin
  currentDt := EncodeDateTime(1989, 9, 16, 12, 0, 0, 0);
  utime := DateTimeToUnix(currentDt);
  convertedDt := UnixToDateTime(utime);
  writeln(FormatDateTime('mm/dd/yyyy HH:nn:ss', currentDt) + ' = ' +
                         IntToStr(utime) + ' = ' +
                         FormatDateTime('mm/dd/yyyy HH:nn:ss',
convertedDt));
  currentDt := EncodeDateTime(1989, 9, 16, 12, 0, 1, 0);
  utime := DateTimeToUnix(currentDt);
  convertedDt := UnixToDateTime(utime);
  writeln(FormatDateTime('mm/dd/yyyy HH:nn:ss', currentDt) + ' = ' +
                         IntToStr(utime) + ' = ' +
                         FormatDateTime('mm/dd/yyyy HH:nn:ss',
convertedDt));
  currentDt := EncodeDateTime(1989, 9, 16, 12, 0, 2, 0);
  utime := DateTimeToUnix(currentDt);
  convertedDt := UnixToDateTime(utime);
  writeln(FormatDateTime('mm/dd/yyyy HH:nn:ss', currentDt) + ' = ' +
                         IntToStr(utime) + ' = ' +
                         FormatDateTime('mm/dd/yyyy HH:nn:ss',
convertedDt));
end.
==================================================

The output I get (fpc 2.2.2 on linux) is:

09-16-1989 12:00:00 = 621950400 = 09-16-1989 12:00:00 09-16-1989 12:00:01 = 621950400 = 09-16-1989 12:00:00 09-16-1989 12:00:02 = 621950402 = 09-16-1989 12:00:02

It seems to me that 09-16-1989 12:00:01 should be 621950401, not 621950400.

Is this broken or am I missing something?

-sg

========================
Computer over. Virus = very yes.

Seth Grover
sethdgrover[at]gmail[dot]com

John Coppens
to Seth Grover
It seems to me that 09-16-1989 12:00:01 should be 621950401, not 621950400.

This seems to be rounding error - if you put 1 ms (milisecond) in the seconds test, the result comes out right. For consecutive seconds, and ms = 0:

09-16-1989 12:00:00 = 621950400 = 09-16-1989 12:00:00 09-16-1989 12:00:01 = 621950400 = 09-16-1989 12:00:00 09-16-1989 12:00:02 = 621950402 = 09-16-1989 12:00:02 09-16-1989 12:00:03 = 621950403 = 09-16-1989 12:00:03 09-16-1989 12:00:04 = 621950403 = 09-16-1989 12:00:03 09-16-1989 12:00:05 = 621950404 = 09-16-1989 12:00:04 09-16-1989 12:00:06 = 621950406 = 09-16-1989 12:00:06 09-16-1989 12:00:07 = 621950407 = 09-16-1989 12:00:07 09-16-1989 12:00:08 = 621950407 = 09-16-1989 12:00:07 09-16-1989 12:00:09 = 621950408 = 09-16-1989 12:00:08 09-16-1989 12:00:10 = 621950410 = 09-16-1989 12:00:10 09-16-1989 12:00:11 = 621950411 = 09-16-1989 12:00:11 09-16-1989 12:00:12 = 621950411 = 09-16-1989 12:00:11 09-16-1989 12:00:13 = 621950412 = 09-16-1989 12:00:12

with ms = 1:

09-16-1989 12:00:00 = 621950400 = 09-16-1989 12:00:00 09-16-1989 12:00:01 = 621950401 = 09-16-1989 12:00:01 09-16-1989 12:00:02 = 621950402 = 09-16-1989 12:00:02 09-16-1989 12:00:03 = 621950403 = 09-16-1989 12:00:03 09-16-1989 12:00:04 = 621950404 = 09-16-1989 12:00:04 09-16-1989 12:00:05 = 621950405 = 09-16-1989 12:00:05 09-16-1989 12:00:06 = 621950406 = 09-16-1989 12:00:06 09-16-1989 12:00:07 = 621950407 = 09-16-1989 12:00:07 09-16-1989 12:00:08 = 621950408 = 09-16-1989 12:00:08 09-16-1989 12:00:09 = 621950409 = 09-16-1989 12:00:09 09-16-1989 12:00:10 = 621950410 = 09-16-1989 12:00:10 09-16-1989 12:00:11 = 621950411 = 09-16-1989 12:00:11 09-16-1989 12:00:12 = 621950412 = 09-16-1989 12:00:12

John

I slightly modified the test program:

program Project1;

uses
Classes,
SysUtils,

  DateUtils;
var
  utime  : longword;
  sec : word;
  currentDt : TDateTime;
  convertedDt : TDateTime;
begin
  for sec := 0 to 59 do begin
    currentDt := EncodeDateTime(1989, 9, 16, 12, 0, sec, 1);
    utime := DateTimeToUnix(currentDt);
    convertedDt := UnixToDateTime(utime);
    writeln(FormatDateTime('mm/dd/yyyy HH:nn:ss', currentDt) + ' = ' +
      IntToStr(utime) + ' = ' +
      FormatDateTime('mm/dd/yyyy HH:nn:ss',
      convertedDt));
  end;
end.
John Coppens
to Seth Grover: I thought I'd get feedback here before I log this as a bug:…
Is this broken or am I missing something?

I suspect the problem is in this function:

Function SecondsBetween(const ANow, AThen: TDateTime): Int64;
begin
  Result:=Trunc(Abs(ANow-AThen)*SecsPerDay);
end;

from the dateutil.inc rtl library. The trunc function is no garantee for a correct result, and can err downwards. I think it should be rounding function, or add 0.0005 seconds (1/2 milisecond). Of course this also depends on the sign of the result.

John

Michael Van Canneyt
to John Coppens: On Tue, 30 Dec 2008 09:25:29 -0700 I suspect the problem is in this function: Function…
John Coppens wrote 16 lines
On Tue, 30 Dec 2008 09:25:29 -0700 "Seth Grover" wrote: > Is this broken or am I missing something? I suspect the problem is in this function: Function SecondsBetween(const ANow, AThen: TDateTime): Int64; begin Result:=Trunc(Abs(ANow-AThen)*SecsPerDay); end; from the dateutil.inc rtl library. The trunc function is no garantee for a correct result, and can err downwards. I think it should be rounding function, or add 0.0005 seconds (1/2 milisecond). Of course this also depends on the sign of the result.

Could you test your hypothesis and provide a patch ?

Michael.

Joost van der Sluis
to John Coppens: On Tue, 30 Dec 2008 09:25:29 -0700 I suspect the problem is in this function: Function…

Op dinsdag 30-12-2008 om 21:44 uur [tijdzone -0200], schreef John Coppens:

Show quoted text 11 lines
On Tue, 30 Dec 2008 09:25:29 -0700 "Seth Grover" wrote: > Is this broken or am I missing something? I suspect the problem is in this function: Function SecondsBetween(const ANow, AThen: TDateTime): Int64; begin Result:=Trunc(Abs(ANow-AThen)*SecsPerDay); end;

This function is incorrect anyway, since it goes wrong around a datetime of 0.

Joost