4

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.

Edward Brey
  • 40,302
  • 20
  • 199
  • 253
Steve A
  • 1,798
  • 4
  • 16
  • 34

2 Answers2

4

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.

Jesse Chisholm
  • 3,857
  • 1
  • 35
  • 29
  • Thanks Jesse, but I wonder if you know you're replying to my post for 2012? I guess it's still helpful for others who find this thread. – Steve A Jun 30 '14 at 14:23
  • 1
    @SteveA - :) Yes, actually, I was aware of the age of the question and its (in my opinion insufficient) previous answer. I am also aware of the age of your comment. But StackOverflow/StackExchange sent me an email that I hadn't dealt with this comment yet, so .... ;-D – Jesse Chisholm Dec 16 '14 at 16:17
2
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

Software_Designer
  • 8,490
  • 3
  • 24
  • 28
  • Thanks Null, but I'm already using the TIME_ZONE_INFORMATION structure which is how I was getting the current time zone via GetTimeZoneInformation(). And your example shows how to get the offset of the current time which I'd mention I can already do. I'm trying to get the offset from a time zone other than the one that's currently set. – Steve A Aug 24 '12 at 20:18
  • 2
    [GetSystemTime](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724390.aspx) *"[r]etrieves the current system date and time. The system time is expressed in Coordinated Universal Time (UTC)."* So the first part of your proposed answer is wrong, and the second re-iterates, what the OP is doing already. And it's doing it wrong, too (like choosing a lossy data type to represent the TZ bias). Sorry, that's a -1. – IInspectable Jan 15 '17 at 12:17