How is the result of the Delphi NOW function affected by the option to “Adjust clock for daylight saving changes”

StackOverflow https://stackoverflow.com/questions/4663462

  •  10-10-2019
  •  | 
  •  

Question

I realise this question could have been answered by writing some test code. I'm not lazy, I just thought that the answer might be generally useful.

I have an app that has generated a large amount of data with records that were stamped with the local time (as returned by the NOW routine). We have run into a snag with transitions in and out of daylight savings time - namely that there is an hour missing when we change to DST, and an hour repeated when we exit from DST. This causes problems with manipulations that assume date ordered records.

The app has been altered therefore to work with all datetimes in UTC, but I will have the ability to display datetimes in UTC or in local time. I also have to deal with datetimes that were stored in local time, and make sure they are correctly shifted to UTC. This is tricky, as the datetime might have been stored while DST was in effect, so in the general case I need to be able to determine if any random date is within or outside a DST period. There is of course a period of one hour where a datetime is ambiguous and could be in the last hour before daylight savings ended, or in the first hour after it ended. There is no way of resolving this.

In coding the changes, I wondered about the result of NOW calls. Internally it calls GetLocalTime. What does GetLocalTime (and NOW) return when you are inside a DST period, but the option to "Adjust clock for daylight saving changes" is turned off?

How do I write a routine that returns the current datetime inside a DST period (with the DST bias applied) regardless of whether "Adjust clock for daylight saving changes" is off or on?

Was it helpful?

Solution

I don't think you can solve your problem easily.
There are too many variables:

  • the stored timestamp
  • the time zone you are in
  • the ever changing time zone rules
  • confirmation that these time zone rules are accurate on all the equipment you use (i.e. everyone always applied their patches)
  • the inaccuracy of your clock

There is a Delphi TZDB project that can help you with the time zone rules.

I think it is much more practical to not rely on all the above variables, but store three fields:

  • the timestamp in your local format
  • the current timezone
  • the timestamp in UTC format

You perform the sorting on the third field, and the first two fields for displaying.

--jeroen

OTHER TIPS

Use TzSpecificLocalTimeToSystemTime (and its obvious inverse). These allow you to convert between UTC and local date/time based on the daylight savings settings in effect at the local date/time. If you want your app to run on anything earlier than XP, load this (from kernel32) with the 'delayed' function attribute:

function TzSpecificLocalTimeToSystemTime(lpTimeZoneInformation: PTimeZoneInformation;
  var lpLocalTime, lpUniversalTime: TSystemTime): BOOL; stdcall;

function TzSpecificLocalTimeToSystemTime; external kernel32 name 'TzSpecificLocalTimeToSystemTime' delayed;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top