If I need to get a date like 12/30/2013
and add 10 days at 8pm, How can I do that in Delphi if I have a TDateTime
variable with that first date?
Asked
Active
Viewed 2.7k times
3 Answers
12
The DateUtils unit has a swath of helpers that allow you to insulate yourself from the way TDateTime is encoded. For instance:
uses
SysUtils, DateUtils;
....
var
DT: TDateTime;
....
DT := EncodeDate(2013, 12, 30); // Dec 30 2013 @ 12AM
DT := IncDay(DT, 10);
DT := IncHour(DT, 20);
This is perhaps a little long-winded but I chose that approach to illustrate both IncDay and IncHour. I do recommend studying the contents of DateUtils to familiarise yourself with all of its functionaility.
Another way to do this would be like so:
DT := EncodeDateTime(2013, 12, 30, 20, 0, 0, 0); // Dec 30 2013 @ 8PM
DT := IncDay(DT, 10);
Or even:
DT := IncDay(EncodeDateTime(2013, 12, 30, 20, 0, 0, 0), 10);

David Heffernan
- 601,492
- 42
- 1,072
- 1,490
-
Thanks for noting the DateUtils – ArieKanarie Mar 22 '17 at 13:01
9
You can use the +
operator to add an integral number of days, and use SysUtils.ReplaceTime()
to change the time, eg:
uses
..., SysUtils;
var
DT: TDateTime;
begin
DT := EncodeDate(2013, 12, 30); // Dec 30 2013 @ 12AM
DT := DT + 10; // Jan 9 2014 @ 12AM
ReplaceTime(DT, EncodeTime(20, 0, 0, 0)); // Jan 9 2014 @ 8PM
end;

Remy Lebeau
- 555,201
- 31
- 458
- 770
-
1To add to that, `TDateTime` is stored as a Double, with the date as the integral part, and time as fractional part. The date is stored as the number of days since 30 Dec 1899. Quite why it is not 31 Dec is not clear. 01 Jan 1900 has a days value of 2. That's why you're able to add days easily using '+'. – Jerry Dodge Dec 05 '13 at 01:52
-
5Also, DateUtils has sugar helper routines IncXXX for all the possible cases, all of them are listed in the documentation. – Free Consulting Dec 05 '13 at 04:56
-
@Jerry In fact it is a pain in the neck that TDateTime uses floating point. A much better choice would be Int64 milliseconds from epoch. – David Heffernan Dec 05 '13 at 07:34
-
2@David - How would that be better ? I often hear that `TDateTime` is problematic, but I have always found it to be quite convenient in my business-world-programming. – Hugh Jones Dec 05 '13 at 09:50
-
@HughJones It would avoid the vagiaries of floating point arithmetic. There have been many problems with `TDateTime` over the years, due to use of floating point rather than integer arithmetic. Large amounts of the `DateUtils` unit were re-written recently to perform the arithmetic as integer arithmetic to deal with the problems. There are plenty of QC issues on the matter. I think the bright ideas to fix things came from somebody outside Emba who was fed up with sloppy calculations using the built in routines. Floating point sucks for date/time handling. – David Heffernan Dec 05 '13 at 09:54
-
@David - I suspect that because of the type of work I do - ie business - TDateTime has never troubled me. I dont think I have ever had to concern myself with accuracy beyond 1s ... Just curious – Hugh Jones Dec 05 '13 at 10:23
-
@HughJones I think that's right. But if you push the type to the limits then it gets flaky. – David Heffernan Dec 05 '13 at 10:31
-
@David - what made me curious was the thought that if accuracy is the primary requirement then a granularity of 1 millisecond could become a serious limitation. I am also interested to know if there is a Delphi class out there anywhere that does what you suggest. Someone MUST have attempted it. – Hugh Jones Dec 05 '13 at 10:36
-
@HughJones Older versions of Delphi were not able to achieve even 1ms accuracy due to badly coded rounding – David Heffernan Dec 05 '13 at 11:02
-
1@HughJones This is the question that tells you more: http://stackoverflow.com/questions/15031706/how-do-i-work-around-delphis-inability-to-accurately-handle-datetime-manipulati Particularly read LURD's comment to the question – David Heffernan Dec 05 '13 at 11:23
-
DateUtils was rewritten because with IA-64 support f/p Double became a generic real type and errors became noticeable. – Free Consulting Dec 05 '13 at 13:23
-
@FreeConsulting That's not true at all. Errors existed just the same in x86. Double is the same in x86 and x64. The 8087 unit does, with default Delphi CW, store intermediates on the FPU stack to 80 bit precision, whereas SSE2 unit stores to 64 bit precision as it has no 80 bit type. But as soon as the values leave the FPU stack and are stored to `TDateTime` variable, they are truncated to 64 bit precision. The problems that John Herbster describes in his QC report have always been there. The QC report is for version 7 of Delphi. – David Heffernan Dec 05 '13 at 17:15
-
-
@Free Somehow you forgot to include my name in your reply. Intermediates is not the key word at all. This is nothing to do with x64 for all reasons that I already explained. John's QC report is excellent. – David Heffernan Dec 18 '13 at 07:17
-
@Free And again the strange inability to use that at symbol. So, which part is incorrect? Feel free to give in now to avoid further embarassment. – David Heffernan Dec 18 '13 at 20:47
-
-
@FreeConsulting Take this program: http://pastebin.com/nTBmT8Xh It outputs, incorrectly, 999, 999, 1000 on old Delphi (<=D2010), even 32 bit versions. Correct output of 999, 1000, 1001 on modern Delphi (>=DXE), both 32 and 64 bit. Explain that away with intermediates. Either you have not attempted to grasp the issue at hand, or you don't understand binary floating point very well. – David Heffernan Dec 18 '13 at 21:59
0
Here's how to do it:
uses
SysUtils, DateUtils;
...
procedure TForm1.Button1Click(Sender: TObject);
var
DT : TDateTime;
begin
DT := StrToDate('30/12/2013');
DT := DT + 10;
ReplaceTime(DT, EncodeTime(20, 0, 0, 0));
ShowMessage(DateTimeToStr( DT ));
end;