Search code examples
winapitimezoneutcdst

Is return value of GetTimeZoneInformation also valid for dynamic DST zones?


Following function which I have written in Delphi (however, my question is not specific to Delphi) does output the current UTC unix timestamp:

function CurrentUnixTimeUTC: int64;
var
  tzi: TTimeZoneInformation;
begin
  // Get the current unix timestamp in local time.
  Result := DateTimeToUnix(Now);
  // First, add the DST specific bias
  case GetTimeZoneInformation(tzi) of
    TIME_ZONE_ID_INVALID:
      RaiseLastOSError;
    TIME_ZONE_ID_UNKNOWN:
      ; // Unknown what to do. We simply don't apply any bias.
    TIME_ZONE_ID_STANDARD:
      Result := Result + tzi.StandardBias * 60;
    TIME_ZONE_ID_DAYLIGHT:
      Result := Result + tzi.DaylightBias * 60;
  end;
  // Now apply the region specific bias
  Result := Result + tzi.Bias * 60;
end;

The function works and has the same output in Germany as in California.

While researching MSDN, I have additionally found the function GetDynamicTimeZoneInformation .

From reading the MSDN (which has an incomplete definition of the member "Bias" btw), it is not clear to me if simply calling GetTimeZoneInformation is sufficient to have my function CurrentUnixTimeUTC also work in regions which have dynamic DST settings (i.e. the DST dates change from year to year). In other words, can GetTimeZoneInformation sucessfully tell if the system is currently in DST mode or not, or do I need to call GetDynamicTimeZoneInformation instead, if I want to be compatible with computers which are in a time zone where dynamic DST rules are applied?


Solution

  • If you're just looking to get the current UTC time from the Win32 API, you shouldn't involve time zones. The OS will handle that automatically. It's faster to simply get the UTC time directly using GetSystemTime, or GetSystemTimeAsFileTime.

    For example, in .NET, DateTime.UtcNow just makes a call to GetSystemTimeAsFileTime. But DateTime.Now first calls DateTime.UtcNow and then gets the local time zone and applies it to that time.

    Regarding the dynamic DST info that you originally asked about, I believe that it would be sufficient to call GetTimeZoneInformation, because Windows should be copying the dynamic DST rule that applies to the current date and time into the non-dynamic values in the registry. But like I said, it's better to just get the UTC time directly.

    I'm surprised there is no Delphi function for getting the UTC time directly. It must be an artifact of the ages, since many things were done locally in the time when Delphi was widely used.


    A few Delphi functions:

    function NowUTC: TDateTime;
    var
      st: TSystemTime;
    begin
      GetSystemTime(st);
      result := EncodeDateTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    end;
    
    function CurrentUnixUTCTimestamp: int64;
    begin
      result := DateTimeToUnix(NowUTC);
    end;