5

I need to convert a historical timestamp from GMT to BST in Delphi (Win32). I can't use the current regional settings in the OS to do the conversion because it won't have the correct daylight saving (DST) offset for the historical time.

Is there a VCL API or Win32 API I can use?

John
  • 53
  • 3
  • Welcome to StackOverflow. Can you be more specific about what you mean by "historical timestamp"? What does "historical" mean? A year ago? Ten years ago? A hundred? Five hundred? A thousand? (Remember when asking questions that we only have the information you provide to go on. The more specific you are about what you need, the more likely it is you'll get an answer quickly.) :) – Ken White Oct 12 '11 at 00:39
  • Good point, Ken. I need to cater for dates from 2011 onwards. – John Oct 12 '11 at 01:07

1 Answers1

13

Delphi TZDB may be of use. It's main feature is that has a class that handles times using the tz database, which, if it contains "historical enough" data, would let you use UTC as an intermediary. The tz database aims to have rules for all the time zones throughout the world and the various time shifts for things like leap years, daylight savings time, calendar changes, etc. as they relate to UTC since the Unix epoch (Midnight, Jan 1, 1970).

Once you have the package installed, usage would be along the lines of the following:

function ConvertFromGMTToBST(const AGMTTime: TDateTime): TDateTime;
var
   tzGMT, tzBST: TTimeZone;
   UTCTime: TDateTime;
begin
    tzGMT := TBundledTimeZone.GetTimeZone('GMT');
    tzBST := TBundledTimeZone.GetTimeZone('BST');
    UTCTime := tzGMT.ToUniversalTime(AGMTTime);
    Result := tzBST.ToLocalTime(UTCTime);
end;

The above relies on a few assumptions. First of all, that GMT and BST are valid aliases in the tz database. If not, then you'll need to find the closest cities. (e.g. America/New_York). The second one is that I'm pretty sure my code is Delphi XE+ specific. TZDB claims to work on Delphi 6 and newer (and FreePascal) though, so the adjustments to work should be minor.

Unfortunately regional dates and times are very complex, especially if you stretch back much before the 20th century.

afrazier
  • 4,784
  • 2
  • 27
  • 30
  • @afrazier Does this solution adjust for DST for the local time eg EST vs EDT – Hogan Mar 23 '16 at 21:08
  • @Hogan: I'm not 100% sure, but it appears not. If you're using the zone EST or EDT, they're going be -5 UTC or -4 UTC directly. Use America/New_York for handling transitions. – afrazier Mar 24 '16 at 02:16
  • @afrazier - Right, but it should be the case that any given local is DST or not. The other examples I've seen don't solve that even when they are using a local like America/New_York. Still looking for a working example. – Hogan Mar 24 '16 at 15:11
  • @Hogan: My understanding of things is that by using a local, the TZDB API can tell you what the UTC offset of a particular timestamp is. If that's not the case, then you might be better off submitting a new question showcasing the problem you're trying to solve and what you've done so far that hasn't worked. I've been out of Delphi for a couple years now, but I'd use something similar to my answer in C#. – afrazier Mar 24 '16 at 15:57
  • @afrazier - Actually I'm not using Delphi, I was working with other systems using TZDB -- thanks for your help, I've gotten it under control now. (I hope). – Hogan Mar 24 '16 at 16:34