🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.delphi.nativeapi.win32
8 messages
8 total messages Started by D-Fan Mon, 04 Aug 2008 07:27
Adding time to the a tdatetime
#20
Author: D-Fan
Date: Mon, 04 Aug 2008 07:27
2 lines
990 bytes
What is the best way to add  minutes, hours, and or days to a tdatetime 
variable?
Re: Adding time to the a tdatetime
#21
Author: Descartes
Date: Mon, 04 Aug 2008 07:41
21 lines
1235 bytes
"D-Fan" wrote:
> What is the best way to add  minutes, hours, and or days to a 
> tdatetime variable?

D-Fan,

Check out

IncMilliSecond
IncSecond
IncMinute
IncHour
IncDay
IncWeek
IncYear

in unit DateUtils

Regards
Descartes
Re: Adding time to the a tdatetime
#22
Author: John Herbster
Date: Mon, 04 Aug 2008 11:01
43 lines
2261 bytes
> "D-Fan" wrote:
>> What is the best way to add  minutes, hours, 
>> and or days to a TDateTime variable?
 
"Descartes" wrote
> Check out
>   IncMilliSecond
>   IncSecond
>   IncMinute
>   IncHour
>   IncDay
>   IncWeek
>   IncYear
> in unit DateUtils

D-Fan and Descartes,

Of course many of the routines are sub-optimal or broken
(at least in D7).  Many of the Inc* functions accumulate 
errors. For example
  procedure TForm1.Button3Click(Sender: TObject);
  var DT: TDateTime; i: integer;
  begin
    DT := 40000;
    For i := 1 to 24 do DT := IncHour(DT,1);
    If DT = 40001
      then ShowMessage('EQ')
      else ShowMessage(FloatToStr(DT-40001));
  end;
will increment DT to a little *less* than a day.

A better way is to convert and round the DT to milliseconds, 
add the increment and convert back to DT.  

You can find code for converting to DT to milliseconds 
and back in this QualityCentral report: 
  Report No: 56957            Status: Open
  A Fix for DateUtils Date-Time Compare Functions
  http://qc.codegear.com/wc/qcmain.aspx?d=56957
  QCWIN:Defect_No=56957
(Look in the comments or attachments.)

Rgds, JohnH
Re: Adding time to the a tdatetime
#27
Author: D-Fan
Date: Mon, 04 Aug 2008 14:46
43 lines
2298 bytes
John Herbster wrote:
>> "D-Fan" wrote:
>>> What is the best way to add  minutes, hours, and or days to a 
>>> TDateTime variable?
> 
> "Descartes" wrote
>> Check out
>>   IncMilliSecond
>>   IncSecond
>>   IncMinute
>>   IncHour
>>   IncDay
>>   IncWeek
>>   IncYear
>> in unit DateUtils
> 
> D-Fan and Descartes,
> 
> Of course many of the routines are sub-optimal or broken
> (at least in D7).  Many of the Inc* functions accumulate errors. For 
> example
>  procedure TForm1.Button3Click(Sender: TObject);
>  var DT: TDateTime; i: integer;
>  begin
>    DT := 40000;
>    For i := 1 to 24 do DT := IncHour(DT,1);
>    If DT = 40001
>      then ShowMessage('EQ')
>      else ShowMessage(FloatToStr(DT-40001));
>  end;
> will increment DT to a little *less* than a day.
> 
> A better way is to convert and round the DT to milliseconds, add the 
> increment and convert back to DT. 
> You can find code for converting to DT to milliseconds and back in this 
> QualityCentral report:  Report No: 56957            Status: Open
>  A Fix for DateUtils Date-Time Compare Functions
>  http://qc.codegear.com/wc/qcmain.aspx?d=56957
>  QCWIN:Defect_No=56957
> (Look in the comments or attachments.)
> 
> Rgds, JohnH
Thanks for your response.
Re: Adding time to the a tdatetime
#29
Author: Descartes
Date: Mon, 04 Aug 2008 16:40
58 lines
3142 bytes
John,

I have a great respect for your thoughts about TDateTime and 
calculations in general with floats.
Reading your writings, I've learned at least to be cautios and to take 
into consideration the limits and the inexactness of floats.

However, I would like to put the OPs question in perspective to avoid 
that he or anybody else gets scared and goes into unnecessary 
complicated measures in trying to achieve their goal.

> Of course many of the routines are sub-optimal or broken
> (at least in D7).

"Of course"? ;-)

> Many of the Inc* functions accumulate errors.

Of course! Adding inexact values repeatedly will do just that (except 
in the rare case when the errors cancel out each other).

> will increment DT to a little *less* than a day.

Your example produces an error of -5 nanoseconds

I made a test using IncMinute 365 * 24 * 60 times (1 year).
The error was 103 milliseconds.
But why would somebody want to do that?

> A better way is to convert and round the DT to milliseconds, add the 
> increment and convert back to DT.


OP wanted to add minutes, hours and days. Although he did not say so, 
one can assume that he deals with ordinary dates and times with a 
resolution down to seconds, but not milliseconds.

Looking at the errors produced with the standard inc* routines in this 
perspective, I don't think it's worth to bother with conversion 
to/from milliseconds.

A more severe problem with TDateTime is that the pitfalls with 
negative values (datetimes before 31.12.1899) are not documented at 
all!

> You can find code for converting to DT to milliseconds and back in 
> this QualityCentral report: Report No: 56957            Status: Open
>  A Fix for DateUtils Date-Time Compare Functions
>  http://qc.codegear.com/wc/qcmain.aspx?d=56957
>  QCWIN:Defect_No=56957
> (Look in the comments or attachments.)

Seems to be a very good report. I'll check it later in depth and vote 
for it (maybe ;-))

No offence, best regards
Descartes
1794744326139 milliseconds old a few minutes ago ;-)
Re: Adding time to the a tdatetime
#31
Author: John Herbster
Date: Mon, 04 Aug 2008 18:32
95 lines
4611 bytes
>> Of course many of the routines are sub-optimal or broken
>> (at least in D7).

"Descartes" wrote
> "Of course"? ;-)

Descartes,

Yes,  DateUtils.pas has had many problems, most of
which are still not fixed.  Check QualityCentral!

>> Many of the Inc* functions *accumulate* errors.

> Of course! Adding inexact values repeatedly will do
> just that (except in the rare case when the errors
> cancel out each other).

>> will increment DT to a little *less* than a day.

> Your example produces an error of -5 nanoseconds

Which is more than enough to throw the final increment
into the wrong day.

What we need, of course, is a way to do exact arithmetic
with days, hour, minutes, and seconds.  This would be
easily possible with time variables of that could store
time exactly to the minute, second, thousandth of a
second. But as long as programmers are happy with inexact
time measurement and arithmetic, it will not happen.

My
>>  A Fix for DateUtils Date-Time Compare Functions
>>  http://qc.codegear.com/wc/qcmain.aspx?d=56957
is a attempt to at least allow time calculations that
will be as exact as possible.

>> A better way is to convert and round the DT to milliseconds,
>> add the increment and convert back to DT.

> OP wanted to add minutes, hours and days. Although he did not
> say so, one can assume that he deals with ordinary dates and
> times with a resolution down to seconds, but not milliseconds.
> Looking at the errors produced with the standard inc* routines
> in this perspective, I don't think it's worth to bother with
> conversion to/from milliseconds.

But if he follows your advice, when he discovers that adding
a minutes 60 times does not give the same result as adding
an hour, he will be back to the well again asking what's wrong.

> A more severe problem with TDateTime is that the pitfalls
> with negative values (datetimes before 31.12.1899) are not
> documented at all!

TDateTime type is documented in D7's Help, though not
very well.

My conversions to and from milliseconds hide all of the
pre-31.12.1899 nastiness by using the nearly perfect
DateTimeToTimeStamp and TimeStampToDateTime routines.

>> You can find code for converting to DT to milliseconds and
>> back in this QualityCentral report:
>> Report No: 56957            Status: Open
>>  A Fix for DateUtils Date-Time Compare Functions
>>  http://qc.codegear.com/wc/qcmain.aspx?d=56957
>>  QCWIN:Defect_No=56957
>> (Look in the comments or attachments.)

> Seems to be a very good report. I'll check it later in depth
> and vote for it (maybe ;-))

Thank you.

Regards, JohnH

PS: D7's DateUtils gives wrong result for the last call to
EncodeDateTime in this test (time part got wrong sign):
  procedure TForm1.Button4Click(Sender: TObject);
  var s: string; dt: TDateTime;
  begin
    s := FormatDateTime('yyyy-mm-dd_HH:nn:ss.zzz', 0.00);
      Memo1.Lines.Add(s);
    s := FormatDateTime('yyyy-mm-dd_HH:nn:ss.zzz', 2.75);
      Memo1.Lines.Add(s);
    s := FormatDateTime('yyyy-mm-dd_HH:nn:ss.zzz',-1.25);
      Memo1.Lines.Add(s);
    s := FormatDateTime('yyyy-mm-dd_HH:nn:ss.zzz',35065);
      Memo1.Lines.Add(s);
    dt := EncodeDateTime(1899,12,29,06,00,00,000);
      Memo1.Lines.Add('EncodeDateTime(1899,12,29,06,00,00,000) =');
    s := FormatDateTime(' yyyy-mm-dd_HH:nn:ss.zzz',dt);
      Memo1.Lines.Add(s); {D7's DateUtils.EncodeDateTime has error.}
  end; 
Re: Adding time to the a tdatetime
#32
Author: Pieter Zijlstra
Date: Mon, 04 Aug 2008 19:38
49 lines
2421 bytes
John Herbster wrote:

>  procedure TForm1.Button4Click(Sender: TObject);
>  var s: string; dt: TDateTime;
>  begin
>    s := FormatDateTime('yyyy-mm-dd_HH:nn:ss.zzz', 0.00);
>      Memo1.Lines.Add(s);
>    s := FormatDateTime('yyyy-mm-dd_HH:nn:ss.zzz', 2.75);
>      Memo1.Lines.Add(s);
>    s := FormatDateTime('yyyy-mm-dd_HH:nn:ss.zzz',-1.25);
>      Memo1.Lines.Add(s);
>    s := FormatDateTime('yyyy-mm-dd_HH:nn:ss.zzz',35065);
>      Memo1.Lines.Add(s);
>    dt := EncodeDateTime(1899,12,29,06,00,00,000);
>      Memo1.Lines.Add('EncodeDateTime(1899,12,29,06,00,00,000) =');
>    s := FormatDateTime(' yyyy-mm-dd_HH:nn:ss.zzz',dt);
>      Memo1.Lines.Add(s); {D7's DateUtils.EncodeDateTime has error.}
> end;

Can't remember if I already tested this one before, but here we go :)

D7
1899-12-30_00:00:00.000
1900-01-01_18:00:00.000
1899-12-29_06:00:00.000
1996-01-01_00:00:00.000
EncodeDateTime(1899,12,29,06,00,00,000) =
 1899-12-30_18:00:00.000

D2006
1899-12-30_00:00:00.000
1900-01-01_18:00:00.000
1899-12-29_06:00:00.000
1996-01-01_00:00:00.000
EncodeDateTime(1899,12,29,06,00,00,000) =
 1899-12-29_06:00:00.000

D2007
1899-12-30_00:00:00.000
1900-01-01_18:00:00.000
1899-12-29_06:00:00.000
1996-01-01_00:00:00.000
EncodeDateTime(1899,12,29,06,00,00,000) =
 1899-12-29_06:00:00.000

Seems to be fixed in the later versions.

-- 
Pieter
Re: Adding time to the a tdatetime
#33
Author: John Herbster
Date: Mon, 04 Aug 2008 19:56
1 lines
1232 bytes
Pieter, Thanks, JohnH
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads