Getting Windows Time Zone Information (C++/MFC)

21.2k views Asked by At

I’m trying to:

  1. Get a list of the time zone names as they appear in when the user selects a time zone from the Windows Control Panel (e.g., “(UTC-08:00) Pacific Time (US & Canada)”).

I’m doing that by reading “CurrentVersion\Time Zones” section of the registry which works well.

  1. Get the currently selected time zone as a string.

I can get the current time zone using GetTimeZoneInformation(), but the names don’t match the list of time zones retrieved from “CurrentVersion\Time Zones” section of the registry. For example, Pacific time appears as “(UTC-08:00) Pacific Time (US & Canada)” in the list of time zones, but GetTimeZoneInformation() contains the strings “Pacific Standard Time” and “Pacific Daylight Time”. I need to find a name that corresponds to the “CurrentVersion\Time Zones” names so I can select it from a list.

  1. Get the current offset (in minutes) between UTC and any other time zone based on the string name.

I can retrieve the offset from UTC in timeZoneInformation.Bias, but that’s only for the currently selected time zone. I need to know the “bias” from any zone as listed in the registry (e.g., “(UC-07:00) Mountain Time (US & Canada)” while adjusting for the daylight savings if in effect.

2

There are 2 answers

2
Jesse Chisholm On

Microsoft chooses to put the string you want in a different area, some strings are non trivial to retrieve. But parts of your question can be answered with the information you have already.

In CurrentVersion\Time Zones, yes are the names of the zones. Inside that key are the values for some of the parts you want.

re: “(UTC-08:00) Pacific Time (US & Canada)”

This is in the registry value "Display" under the zone name you have.

There are more strings in a resource DLL, specified by the values "MUI_Display", "MUI_Std" and "MUI_Dlt". It is usually something like "@tzres.dll,-220"

To get these strings you will need to load that resource DLL into memory and fetch those specific resources as UNICODE strings.

re: Offset in minutes of any timezone.

Also inside the registry key you have (the time zone name) is a value called "TZI". This is a binary blob that (according to the MSDN) looks like this:

typedef struct _REG_TZI_FORMAT
{
    LONG Bias;
    LONG StandardBias;
    LONG DaylightBias;
    SYSTEMTIME StandardDate;
    SYSTEMTIME DaylightDate;
} REG_TZI_FORMAT;

Where the various BIAS are in minutes, using the equation UTC = local + theBias and theBias is either Bias + StandardBias or Bias + DaylightBias depending on the date in question. The two SYSTEMTIME values describe the transition dates.

2
Software_Designer On
TimeZoneInfo.Bias

TIME_ZONE_INFORMATION structure - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx

SetTimeZoneInformation function - http://msdn.microsoft.com/en-us/library/windows/desktop/ms724944(v=vs.85).aspx

  // Get the local system time.
SYSTEMTIME LocalTime = { 0 };
GetSystemTime( &LocalTime );

// Get the timezone info.
TIME_ZONE_INFORMATION TimeZoneInfo;
GetTimeZoneInformation( &TimeZoneInfo );

// Convert local time to UTC.
SYSTEMTIME GmtTime = { 0 };
TzSpecificLocalTimeToSystemTime( &TimeZoneInfo,
                                 &LocalTime,
                                 &GmtTime );

// GMT = LocalTime + TimeZoneInfo.Bias
// TimeZoneInfo.Bias is the difference between local time
// and GMT in minutes.

// Local time expressed in terms of GMT bias.
float TimeZoneDifference = -( float(TimeZoneInfo.Bias) / 60 );
CString csLocalTimeInGmt;
csLocalTimeInGmt.Format( _T("%ld:%ld:%ld + %2.1f Hrs"),
                         GmtTime.wHour,
                         GmtTime.wMinute,
                         GmtTime.wSecond,
                         TimeZoneDifference );

TimeZoneInfo Class - http://msdn.microsoft.com/en-us/library/bb396389 Determine Daylight Savings Time - http://www.metatrader4.com/forum/2155