tags:

views:

1508

answers:

5

I have a pretty unusual problem (for me). I am writing an application that will allow a user to change their system time forward or back either by explicit date (change my date to 6/3/1955) or by increment using buttons (go forward 1 month).

I'm writing this to help some of my users test some software that requires jumps like this in order to simulate real world usage of a billing system.

Changing the time in Delphi is of course very easy:

SetDateTime(2008,05,21,16,07,21,00);

But I'm not sure if Delphi (2006) has any built in helpers for date math, which is one of my least favorite things :)

Any suggestions for the best way to handle this? I'd prefer to stay native as the winapi datetime calls suck.

Thanks!

+2  A: 

The VCL has types (TDate and TDateTime) which are doubles and you can use in arithmetic operations.

Also see EncodeDate and DecodeDate

Richard Harrison
+10  A: 

There is plenty of helpers in the DateUtils unit.

gabr
DateUtils documentation available online http://docs.codegear.com/docs/radstudio/radstudio2007/RS2007_helpupdates/HUpdate3/EN/html/delphivclwin32/DateUtils.html
stukelly
Great! I didn't know the docs are available online!
gabr
+1  A: 

There is plenty of helpers in the SysUtils unit (and as gabr pointed out, also in DateUtils).

mliesen
+5  A: 

As mentioned by gabr and mliesen, have a look at the DateUtils and SysUtils units, useful functions include.

  • IncDay - Add a or subtract a number of days.
  • IncMonth - Add a or subtract a number of months.
  • IncWeek - Add a or subtract a number of weeks.
  • IncYear - Add a or subtract a number of years.
  • EncodeDate - Returns a TDateTime value from the Year, Month, and Day params.
stukelly
This answer was significantly more complete than the highest voted answer.
Bruce the Hoon
For those looking for something that handles time as well, DaetUtils also contains IncHour, IncMinute, IncSecond, IncMilliSecond
Chris Thornton
+2  A: 

What do you want to happen if the day of the current month doesn't exist in your future month? Say, January 31 + 1 month? You have the same problem if you increment the year and the starting date is February 29 on a leap year. So there can't be a universal IncMonth or IncYear function that will work consistantly on all dates.

For anyone interested, I heartily recommend Julian Bucknall's article on the complexities that are inherent in this type of calculation on how to calculate the number of months and days between two dates.

The following is the only generic date increment functions possible that do not introduce anomolies into generic date math. But it only accomplishes this by shifting the responsibility back onto the programmer who presumably has the exact requirements of the specific application he/she is programming.

IncDay - Add a or subtract a number of days.
IncWeek - Add or subtract a number of weeks.

But if you must use the built in functions then at least be sure that they do what you want them to do. Have a look at the DateUtils and SysUtils units. Having the source code to these functions is one of the coolest aspects of Delphi. Having said that, here is the complete list of built in functions:

IncDay - Add a or subtract a number of days.
IncWeek - Add or subtract a number of weeks.
IncMonth - Add a or subtract a number of months.
IncYear - Add a or subtract a number of years.

As for the second part of your question, how to set the system date & time using a TDatetime, the following shamelessly stolen code from another post will do the job:

procedure SetSystemDateTime(aDateTime: TDateTime);
var
  lSystemTime: TSystemTime;
  lTimeZone: TTimeZoneInformation;
 begin
  GetTimeZoneInformation(lTimeZone);
  aDateTime := aDateTime + (lTimeZone.Bias / 1440);
  DateTimeToSystemTime(aDateTime, lSystemTime);
  setSystemTime(lSystemTime);
end;