Recent

Author Topic: TDateTime to number  (Read 41950 times)

Edson

  • Hero Member
  • *****
  • Posts: 1328
TDateTime to number
« on: October 05, 2016, 05:52:18 am »
Are there some lazarus/FP functions to convert a TDateTime to integer numbers and back again?

I need to compact a TDateTime to a string, before to save to a file.

I have tested DateTimeToFileDate() and FileDateToDateTime(), but FileDateToDateTime() not always restore the same date-time coded by DateTimeToFileDate().
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

Thaddy

  • Hero Member
  • *****
  • Posts: 18963
  • Glad to be alive.
Re: TDateTime to number
« Reply #1 on: October 05, 2016, 06:12:59 am »
Those functions you used are for a very different purpose.
What you are looking for is probably  DateTimeToStr or DateTimeToStrFmt and StrToDateTime.

Note TDateTime is a Double, not an integer.
If you really want to use integers, use the unix time functions. Unix time is integer. (Int64)
DateTimeToUnix
UnixToDateTime

These functions are in the unit DateUtils.
« Last Edit: October 05, 2016, 06:16:31 am by Thaddy »
Recovered from removal of tumor in tongue following tongue reconstruction with a part from my leg.

Edson

  • Hero Member
  • *****
  • Posts: 1328
Re: TDateTime to number
« Reply #2 on: October 05, 2016, 06:24:02 am »
If you really want to use integers, use the unix time functions. Unix time is integer. (Int64)
DateTimeToUnix
UnixToDateTime

I didn't know those functions. But after tested, they behave worse than DateTimeToFileDate() and FileDateToDateTime(). They are not reversible.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.TestDate;
  2. var
  3.    fec: TDateTime;
  4.    n: LongInt;
  5. begin
  6.    fec := now;
  7.    n := DateTimeToUnix(fec);
  8.    writeln(DateTimeToStr(fec), '=', n);
  9.    fec := UnixToDateTime(n);
  10.    writeln(DateTimeToStr(fec), '=', n);
  11.    writeln('');
  12. end;
  13.  

Executing this code at several times, give a difference of one second:

Code: Pascal  [Select][+][-]
  1. 04/10/2016 23:21:47=1475623307
  2. 04/10/2016 23:21:47=1475623307
  3.  
  4. 04/10/2016 23:21:47=1475623308
  5. 04/10/2016 23:21:48=1475623308
  6.  
  7. 04/10/2016 23:21:47=1475623308
  8. 04/10/2016 23:21:48=1475623308
  9.  
  10. 04/10/2016 23:21:47=1475623308
  11. 04/10/2016 23:21:48=1475623308
  12.  
  13. 04/10/2016 23:21:47=1475623308
  14. 04/10/2016 23:21:48=1475623308
  15.  
  16. 04/10/2016 23:21:48=1475623308
  17. 04/10/2016 23:21:48=1475623308
  18.  
  19. 04/10/2016 23:21:48=1475623308
  20. 04/10/2016 23:21:48=1475623308
  21.  
  22. 04/10/2016 23:21:48=1475623308
  23. 04/10/2016 23:21:48=1475623308
  24.  
  25. 04/10/2016 23:21:48=1475623308
  26. 04/10/2016 23:21:48=1475623308
  27.  
  28. 04/10/2016 23:21:48=1475623309
  29. 04/10/2016 23:21:49=1475623309
  30.  
  31. 04/10/2016 23:21:48=1475623309
  32. 04/10/2016 23:21:49=1475623309
  33.  
  34. 04/10/2016 23:21:48=1475623309
  35. 04/10/2016 23:21:49=1475623309
  36.  

Maybe I'm doing something bad  %)
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

Thaddy

  • Hero Member
  • *****
  • Posts: 18963
  • Glad to be alive.
Re: TDateTime to number
« Reply #3 on: October 05, 2016, 06:31:24 am »
What version are you using? FPC and Laz version plz.
I get right now:
5-10-16 06:29:25=1475648966
5-10-16 06:29:26=1475648966
Based on:
Code: Pascal  [Select][+][-]
  1. uses sysutils,dateutils;
  2. var
  3.    fec: TDateTime;
  4.    n: LongInt;
  5. begin
  6.    fec := now;
  7.    n := DateTimeToUnix(fec);
  8.    writeln(DateTimeToStr(fec), '=', n);
  9.    fec := UnixToDateTime(n);
  10.    writeln(DateTimeToStr(fec), '=', n);
  11.    writeln('');
  12. end.
There may be a rounding error. I will look into it.
[edit]
I filed a bug report. 0030697 on Mantis.
 

« Last Edit: October 05, 2016, 06:41:42 am by Thaddy »
Recovered from removal of tumor in tongue following tongue reconstruction with a part from my leg.

Edson

  • Hero Member
  • *****
  • Posts: 1328
Re: TDateTime to number
« Reply #4 on: October 05, 2016, 06:50:49 am »
What version are you using? FPC and Laz version plz.
Lazarus 1.6 - FPC 3.0.0 - x86_64-win64 on  Windows 7

I have written these functions:

Code: Pascal  [Select][+][-]
  1.  
  2. function DT2Number(const dt: TDateTime): Int64;
  3.   var
  4.     hh, nn, ss, MilliSecond: word;
  5.   begin
  6.     DecodeTime(dt, hh, nn, ss, MilliSecond);
  7.     Result := trunc(dt)*86400 + hh * 3600 + nn * 60 + ss;
  8.   end;
  9.  
  10. function Number2DT(n: Int64): TDateTime;
  11. var
  12.     day, hh, nn, ss: Int64;
  13. begin
  14.     day := n div 86400;
  15.     n := n mod 86400;
  16.     hh := n div 3600;
  17.     n := n mod 3600;
  18.     nn := n div 60;
  19.     ss := n mod 60;
  20.     Result := EncodeTime(hh,nn,ss,0) + day;
  21. end;
  22.  

And they never fail  :D, except dates before 1900  :o.
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: TDateTime to number
« Reply #5 on: October 05, 2016, 07:10:27 am »
I filed a bug report. 0030697 on Mantis.
afaik it is standard behaviour, not an error. If i remember correctly, it has something to do with the resolution. I got something similar with dates from files and got completely confused until someone explained that the date time function uses this resolution (converting NTFS filedates to unixtime and vice verse). Sorry no solid backup for my words but should be easy to find.

edit:
Ah, here something:
Write time has a resolution of 2 seconds.

« Last Edit: October 05, 2016, 07:25:14 am by molly »

Thaddy

  • Hero Member
  • *****
  • Posts: 18963
  • Glad to be alive.
Re: TDateTime to number
« Reply #6 on: October 05, 2016, 07:35:35 am »
I filed a bug report. 0030697 on Mantis.
afaik it is standard behaviour, not an error. If i remember correctly, it has something to do with the resolution. I got something similar with dates from files and got completely confused until someone explained that the date time function uses this resolution (converting NTFS filedates to unixtime and vice verse). Sorry no solid backup for my words but should be easy to find.

edit:
Ah, here something:
Write time has a resolution of 2 seconds.

That resolution refers to IO, not to calculation.
Imo it is a bug if the reverse output reversed on itself obtains a different result. That should not happen. It's a defined calculation both ways. Not an approximation ;)
Let's see what the dev's do with the bug report.
« Last Edit: October 05, 2016, 07:37:38 am by Thaddy »
Recovered from removal of tumor in tongue following tongue reconstruction with a part from my leg.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: TDateTime to number
« Reply #7 on: October 05, 2016, 08:12:23 am »
@Thaddy:
Oh, sorry. i was too quick, i only noticed the initial concern regarding file dates.

Uhmz....

I've placed the routines that DateTimeToUnix and UnixToDateTime uses in a test program. Good heavens !

Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. {$MODE OBJFPC}
  4.  
  5. uses
  6.   Math, SysUtils;
  7.  
  8.  
  9. ///////////////////////////////////////////////////////////////////////////////
  10.  
  11.  
  12. const
  13.    HoursPerDay = 24;
  14.    MinsPerHour = 60;
  15.    SecsPerMin  = 60;
  16.    MSecsPerSec = 1000;
  17.    MinsPerDay  = HoursPerDay * MinsPerHour;
  18.    SecsPerDay  = MinsPerDay * SecsPerMin;
  19.    MSecsPerDay = SecsPerDay * MSecsPerSec;
  20.  
  21. {TDateTime holds the date as the number of days since 30 Dec 1899, known as
  22. Microsoft Excel epoch}
  23.    JulianEpoch = TDateTime(-2415018.5);
  24.    UnixEpoch   = JulianEpoch + TDateTime(2440587.5);
  25.  
  26. const
  27.   TDateTimeEpsilon = 2.2204460493e-16;
  28.  
  29.  
  30. { TDateTime is not defined in the interval [-1.0..0.0[. Additionally, when
  31.   negative the time part must be treated using its absolute value (0.25 always
  32.   means "6 a.m.") -> skip the gap and convert the time part when crossing the
  33.   gap -- and take care of rounding errors }
  34. Procedure MaybeSkipTimeWarp(OldDate: TDateTime; var NewDate: TDateTime);
  35. begin
  36.   if (OldDate>=0) and (NewDate<-TDateTimeEpsilon) then
  37.     NewDate:=int(NewDate-1.0+TDateTimeEpsilon)-frac(1.0+frac(NewDate))
  38.   else if (OldDate<=-1.0) and (NewDate>-1.0+TDateTimeEpsilon) then
  39.     NewDate:=int(NewDate+1.0-TDateTimeEpsilon)+frac(1.0-abs(frac(1.0+NewDate)));
  40. end;
  41.  
  42.  
  43. function IncNegativeTime(AValue, Addend: TDateTime): TDateTime;
  44. var
  45.   newtime: tdatetime;
  46. begin
  47.   newtime:=-frac(Avalue)+frac(Addend);
  48.   { handle rounding errors }
  49.   if SameValue(newtime,int(newtime)+1,TDateTimeEpsilon) then
  50.     newtime:=int(newtime)+1
  51.   else if SameValue(newtime,int(newtime),TDateTimeEpsilon) then
  52.     newtime:=int(newtime);
  53.   { time underflow -> previous day }
  54.   if newtime<-TDateTimeEpsilon then
  55.     begin
  56.       newtime:=1.0+newtime;
  57.       avalue:=int(avalue)-1;
  58.     end
  59.   { time overflow -> next day }
  60.   else if newtime>=1.0-TDateTimeEpsilon then
  61.     begin
  62.       newtime:=newtime-1.0;
  63.       avalue:=int(avalue)+1;
  64.     end;
  65.   Result:=int(AValue)+int(Addend)-newtime;
  66. end;
  67.  
  68.  
  69. Function DateTimeDiff(const ANow, AThen: TDateTime): TDateTime;
  70. begin
  71.   Result:= ANow - AThen;
  72.   if (ANow>0) and (AThen<0) then
  73.     Result:=Result-0.5
  74.   else if (ANow<-1.0) and (AThen>-1.0) then
  75.     Result:=Result+0.5;
  76. end;
  77.  
  78.  
  79. Function IncSecond(const AValue: TDateTime; const ANumberOfSeconds: Int64): TDateTime;
  80. begin
  81.   if AValue>=0 then
  82.     Result:=AValue+ANumberOfSeconds/SecsPerDay
  83.   else
  84.     Result:=IncNegativeTime(Avalue,ANumberOfSeconds/SecsPerDay);
  85.   MaybeSkipTimeWarp(AValue,Result);
  86. end;
  87.  
  88.  
  89. Function DateTimeToUnix(const AValue: TDateTime): Int64;
  90. begin
  91.   Result:=Round(DateTimeDiff(AValue,UnixEpoch)*SecsPerDay);
  92. end;
  93.  
  94.  
  95. Function UnixToDateTime(const AValue: Int64): TDateTime;
  96. begin
  97.   Result:=IncSecond(UnixEpoch, AValue);
  98. end;
  99.  
  100.  
  101. ///////////////////////////////////////////////////////////////////////////////
  102.  
  103. procedure TestDate;
  104. var
  105.   fec1: TDateTime;
  106.   fec2: TDateTime;
  107.   feca1: int64 absolute fec1;
  108.   feca2: int64 absolute fec2;
  109.  
  110.   n: LongInt;
  111. begin
  112.   fec1 := now;
  113.   n := DateTimeToUnix(fec1);
  114.   writeln(DateTimeToStr(fec1), ' = ', n, ' (',feca1,')');
  115.   fec2 := UnixToDateTime(n);
  116.   writeln(DateTimeToStr(fec2), ' = ', n, ' (',feca2,')');
  117.   writeln;
  118. end;
  119.  
  120. var
  121.   i : Integer;
  122. begin
  123.   for i := 1 to 10 do
  124.   begin
  125.     TestDate;
  126.     sleep(1000);
  127.   end;
  128. end.
  129.  

Quote
{ ---------------------------------------------------------------------
    Period functions.
  ---------------------------------------------------------------------}

{
  These functions are declared as approximate by Borland.
  A bit strange, since it can be calculated exactly ?

  -- No, because you need rounding or truncating (JM)
}

Oh, i did not notice  ;)

Code: [Select]
5-10-2016 7:31:36 = 1475652697 (4676094353174180557)
5-10-2016 7:31:37 = 1475652697 (4676094353174851845)

5-10-2016 7:31:37 = 1475652698 (4676094353175771286)
5-10-2016 7:31:38 = 1475652698 (4676094353176442574)

5-10-2016 7:31:38 = 1475652699 (4676094353177362015)
5-10-2016 7:31:39 = 1475652699 (4676094353178033302)

5-10-2016 7:31:39 = 1475652700 (4676094353178952743)
5-10-2016 7:31:40 = 1475652700 (4676094353179624031)

5-10-2016 7:31:40 = 1475652701 (4676094353180543472)
5-10-2016 7:31:41 = 1475652701 (4676094353181214759)

5-10-2016 7:31:41 = 1475652702 (4676094353182134201)
5-10-2016 7:31:42 = 1475652702 (4676094353182805488)

5-10-2016 7:31:42 = 1475652703 (4676094353183724929)
5-10-2016 7:31:43 = 1475652703 (4676094353184396217)

5-10-2016 7:31:43 = 1475652704 (4676094353185315658)
5-10-2016 7:31:44 = 1475652704 (4676094353185986945)

5-10-2016 7:31:44 = 1475652705 (4676094353186906386)
5-10-2016 7:31:45 = 1475652705 (4676094353187577674)

5-10-2016 7:31:45 = 1475652706 (4676094353188497115)
5-10-2016 7:31:46 = 1475652706 (4676094353189168403)
« Last Edit: October 05, 2016, 08:35:06 am by molly »

Thaddy

  • Hero Member
  • *****
  • Posts: 18963
  • Glad to be alive.
Re: TDateTime to number
« Reply #8 on: October 05, 2016, 08:46:58 am »
I appreciate the comment by Jonas, but rounding and/or truncating implies the result and its inverse are supposed to be exact by definition..... They have the same rounding error.
Recovered from removal of tumor in tongue following tongue reconstruction with a part from my leg.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: TDateTime to number
« Reply #9 on: October 05, 2016, 09:11:30 am »
Yups, i understand Thaddy.

Two more logs.

non equal:
Code: [Select]
05-10-2016 07:59:26.562 <> 5-10-2016 7:59:26 = 1475654367 (4676094355830671915)
05-10-2016 07:59:27.000 =  5-10-2016 7:59:27 = 1475654367 (4676094355831368654)

05-10-2016 07:59:27.562 <> 5-10-2016 7:59:27 = 1475654368 (4676094355832262643)
05-10-2016 07:59:28.000 =  5-10-2016 7:59:28 = 1475654368 (4676094355832959383)

05-10-2016 07:59:28.562 <> 5-10-2016 7:59:28 = 1475654369 (4676094355833853372)
05-10-2016 07:59:29.000 =  5-10-2016 7:59:29 = 1475654369 (4676094355834550111)

05-10-2016 07:59:29.562 <> 5-10-2016 7:59:29 = 1475654370 (4676094355835444101)
05-10-2016 07:59:30.000 =  5-10-2016 7:59:30 = 1475654370 (4676094355836140840)

05-10-2016 07:59:30.562 <> 5-10-2016 7:59:30 = 1475654371 (4676094355837034829)
05-10-2016 07:59:31.000 =  5-10-2016 7:59:31 = 1475654371 (4676094355837731568)

05-10-2016 07:59:31.562 <> 5-10-2016 7:59:31 = 1475654372 (4676094355838625558)
05-10-2016 07:59:32.000 =  5-10-2016 7:59:32 = 1475654372 (4676094355839322297)

05-10-2016 07:59:32.562 <> 5-10-2016 7:59:32 = 1475654373 (4676094355840216287)
05-10-2016 07:59:33.000 =  5-10-2016 7:59:33 = 1475654373 (4676094355840913026)

05-10-2016 07:59:33.562 <> 5-10-2016 7:59:33 = 1475654374 (4676094355841807015)
05-10-2016 07:59:34.000 =  5-10-2016 7:59:34 = 1475654374 (4676094355842503754)

05-10-2016 07:59:34.562 <> 5-10-2016 7:59:34 = 1475654375 (4676094355843397744)
05-10-2016 07:59:35.000 =   5-10-2016 7:59:35 = 1475654375 (4676094355844094483)

05-10-2016 07:59:35.562 <> 5-10-2016 7:59:35 = 1475654376 (4676094355844988472)
05-10-2016 07:59:36.000 =  5-10-2016 7:59:36 = 1475654376 (4676094355845685212)


equal:
Code: [Select]
05-10-2016 07:59:37.234 <> 5-10-2016 7:59:37 = 1475654377 (4676094355847648171)
05-10-2016 07:59:37.000 =  5-10-2016 7:59:37 = 1475654377 (4676094355847275940)

05-10-2016 07:59:38.234 <> 5-10-2016 7:59:38 = 1475654378 (4676094355849238899)
05-10-2016 07:59:38.000 =  5-10-2016 7:59:38 = 1475654378 (4676094355848866669)

05-10-2016 07:59:39.234 <> 5-10-2016 7:59:39 = 1475654379 (4676094355850829628)
05-10-2016 07:59:39.000 =  5-10-2016 7:59:39 = 1475654379 (4676094355850457397)

05-10-2016 07:59:40.234 <> 5-10-2016 7:59:40 = 1475654380 (4676094355852420357)
05-10-2016 07:59:40.000 =  5-10-2016 7:59:40 = 1475654380 (4676094355852048126)

05-10-2016 07:59:41.234 <> 5-10-2016 7:59:41 = 1475654381 (4676094355854011085)
05-10-2016 07:59:41.000 =  5-10-2016 7:59:41 = 1475654381 (4676094355853638855)

05-10-2016 07:59:42.234 <> 5-10-2016 7:59:42 = 1475654382 (4676094355855601814)
05-10-2016 07:59:42.000 =  5-10-2016 7:59:42 = 1475654382 (4676094355855229583)

05-10-2016 07:59:43.234 <> 5-10-2016 7:59:43 = 1475654383 (4676094355857192542)
05-10-2016 07:59:43.000 =  5-10-2016 7:59:43 = 1475654383 (4676094355856820312)

05-10-2016 07:59:44.234 <> 5-10-2016 7:59:44 = 1475654384 (4676094355858783271)
05-10-2016 07:59:44.000 =  5-10-2016 7:59:44 = 1475654384 (4676094355858411041)

05-10-2016 07:59:45.234 <> 5-10-2016 7:59:45 = 1475654385 (4676094355860374000)
05-10-2016 07:59:45.000 =  5-10-2016 7:59:45 = 1475654385 (4676094355860001769)

05-10-2016 07:59:46.234 <> 5-10-2016 7:59:46 = 1475654386 (4676094355861964728)
05-10-2016 07:59:46.000 =  5-10-2016 7:59:46 = 1475654386 (4676094355861592498)

DateTimeToStr seem to truncate/disregard/ignore milli's ?
« Last Edit: October 05, 2016, 09:13:58 am by molly »

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: TDateTime to number
« Reply #10 on: October 05, 2016, 10:59:05 am »
Ok, in that case let me try put it another way:

1) DateTimeToUnix converts a TDateTime value to a epoch time (i.e. the number of seconds elapsed since 1/1/1970).

The resolution of epoch time is 1 second

2) TDateTime is effectively type double and stores combined date+time

The truncated part of a datetime value has a resolution of days.
The fractional part of a datetime value has a resolution of milliseconds

Conclusion:
Before using DateTimeToStr you would have to compensate for the difference in resolutions by 'zero'ing' the number of milliseconds before handing it over to function DateTimeToStr as DateTimeToStr does not automatically 'round' its results.

function UnixToDateTime is never ever able to return a combined datetime value that contains milliseconds (it will always be zero) unless it sticks its finger in the air and randomly comes up with a number for that.

rvk

  • Hero Member
  • *****
  • Posts: 6989
Re: TDateTime to number
« Reply #11 on: October 05, 2016, 11:26:11 am »
f.y.i. Delphi does the DateTimeToUnix() and UnixToDateTime() correctly.
(It uses milliseconds in DateTimeToUnix to calculate the difference before dividing it by MSecsPerSec.)

So I think the problem is in DateTimeToUnix().

When using a fixed datetime of 42648,4578198843 (05-10-2016 10:59:15) I get:

Code: [Select]
// FPC
// 42648,4578198843 05-10-2016 10:59:15 = 1475665156 (4676094372993163985)
// 42648,4578240741 05-10-2016 10:59:16 = 1475665156 (4676094372993739823)

// Delphi
// 42648,4578198843 05-10-2016 10:59:15 = 1475665155 (4676094372993163985)
// 42648,4578125    05-10-2016 10:59:15 = 1475665155 (4676094372992149094)

Edit:
Wouldn't this function be better for DateTimeToUnix()?
It first truncates the milliseconds from AValue before calculating the seconds.

Code: Pascal  [Select][+][-]
  1. Function DateTimeToUnix(const AValue: TDateTime): Int64;
  2. begin
  3.   Result:=Round(DateTimeDiff(trunc(AValue*SecsPerDay)/SecsPerDay,UnixEpoch)*SecsPerDay);
  4. end;

FPC:
Code: [Select]
42648,4887077894 05-10-2016 11:43:44 = 1475667824 (4676094377238365330)
42648,4887037037 05-10-2016 11:43:44 = 1475667824 (4676094377237803803)

42648,488719375  05-10-2016 11:43:45 = 1475667825 (4676094377239957649)
42648,4887152778 05-10-2016 11:43:45 = 1475667825 (4676094377239394532)

42648,4887309606 05-10-2016 11:43:46 = 1475667826 (4676094377241549969)
42648,4887268519 05-10-2016 11:43:46 = 1475667826 (4676094377240985260)

42648,4887425463 05-10-2016 11:43:47 = 1475667827 (4676094377243142288)
42648,4887384259 05-10-2016 11:43:47 = 1475667827 (4676094377242575989)

42648,4887541319 05-10-2016 11:43:48 = 1475667828 (4676094377244734608)
42648,48875      05-10-2016 11:43:48 = 1475667828 (4676094377244166717)

42648,4887657176 05-10-2016 11:43:49 = 1475667829 (4676094377246326927)
42648,4887615741 05-10-2016 11:43:49 = 1475667829 (4676094377245757446)

42648,4887773032 05-10-2016 11:43:50 = 1475667830 (4676094377247919246)
42648,4887731482 05-10-2016 11:43:50 = 1475667830 (4676094377247348175)

42648,4887888889 05-10-2016 11:43:51 = 1475667831 (4676094377249511566)
42648,4887847222 05-10-2016 11:43:51 = 1475667831 (4676094377248938903)

42648,4888004745 05-10-2016 11:43:52 = 1475667832 (4676094377251103885)
42648,4887962963 05-10-2016 11:43:52 = 1475667832 (4676094377250529632)

42648,4888120833 05-10-2016 11:43:53 = 1475667833 (4676094377252699386)
42648,4888078704 05-10-2016 11:43:53 = 1475667833 (4676094377252120361)
« Last Edit: October 05, 2016, 11:44:52 am by rvk »

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: TDateTime to number
« Reply #12 on: October 05, 2016, 11:58:31 am »
f.y.i. Delphi does the DateTimeToUnix() and UnixToDateTime() correctly.
Argh! i forgot to check Delphi  (i simply assumed fpc was right in the conversion) :-[

Thanks for the heads up.

Quote
(It uses milliseconds in DateTimeToUnix to calculate the difference before dividing it by MSecsPerSec.)

So I think the problem is in DateTimeToUnix().

Edit:
Wouldn't this function be better for DateTimeToUnix()?
It first truncates the milliseconds from AValue before calculating the seconds.
I'm trying to read up on what would be considered normal for handling msecs (usually fpc follows Delphi in that regards ?)

rvk

  • Hero Member
  • *****
  • Posts: 6989
Re: TDateTime to number
« Reply #13 on: October 05, 2016, 12:18:24 pm »
I'm trying to read up on what would be considered normal for handling msecs (usually fpc follows Delphi in that regards ?)
Well, the UnixTime is seconds only so you could either round them (up or down) or truncate them.

But because DateTimeToStr only shows the truncated (to seconds) of a TDateTime you could end up with a difference if you don't truncate it the same way for DateTimeToUnix.

For a truncated to second-TDateTime the current FPC-function works correctly
Code: [Select]
42648,4578125 05-10-2016 10:59:15 = 1475665155 (4676094372992149094)
42648,4578125 05-10-2016 10:59:15 = 1475665155 (4676094372992149094)

But when you have a second > .5 you'll get a higher UnixTime of 1475665156. If you translate that back you get 10:59:16.

You could say 10:59:15.6 = 10:59:16 in which case it works fine... But because the UnixTime is whole seconds I think truncating them is more appropriate.

When 1234.6 seconds have elapsed you don't/shouldn't give 1235 as a result of the whole number of seconds which elapsed. It should be 1234 whole seconds.

And since the function DateTimeToUnix() means number of whole seconds passed since (x) you should get the truncated seconds (not the rounded seconds).
« Last Edit: October 05, 2016, 12:20:50 pm by rvk »

Thaddy

  • Hero Member
  • *****
  • Posts: 18963
  • Glad to be alive.
Re: TDateTime to number
« Reply #14 on: October 05, 2016, 12:26:53 pm »
Well, given that any mathematically proven reversable calculation should be reversable, I add this topic as a link to the bug report. :o O:-)
Recovered from removal of tumor in tongue following tongue reconstruction with a part from my leg.

 

TinyPortal © 2005-2018