Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get a specific TIME_ZONE_INFORMATION struct in Win32?

The Win32 GetTimeZoneInformation function returns your systems local time zone as set up in the control panel. How do I get another specific time zone? Is there a call that does this?

Tony

like image 682
AnthonyLambert Avatar asked Jan 21 '09 16:01

AnthonyLambert


2 Answers

According to this the information for the different timezones is stored in the registry, so you will have to retrieve the information from there and populate the TIME_ZONE_INFORMATION struct yourself.

Quote from the msdn article

Remarks

Settings for each time zone are stored in the following registry key:

HKEY_LOCAL_MACHINE
     SOFTWARE
          Microsoft
               Windows NT
                    CurrentVersion
                         Time Zones
                              time_zone_name
like image 109
CalvinR Avatar answered Sep 21 '22 23:09

CalvinR


code:

#include <stdio.h>
#include <windows.h>

#define pWin32Error(dwSysErr, sMsg )

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

#define REG_TIME_ZONES "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\"
#define REG_TIME_ZONES_LEN (sizeof(REG_TIME_ZONES)-1)
#define REG_TZ_KEY_MAXLEN (REG_TIME_ZONES_LEN + (sizeof(((TIME_ZONE_INFORMATION*)0)->StandardName)/2) -1)

int GetTimeZoneInformationByName(TIME_ZONE_INFORMATION *ptzi, const char StandardName[]) {
    int rc;
    HKEY hkey_tz;
    DWORD dw;
    REG_TZI_FORMAT regtzi;
    char tzsubkey[REG_TZ_KEY_MAXLEN+1] = REG_TIME_ZONES;

    strncpy(tzsubkey + REG_TIME_ZONES_LEN, StandardName, sizeof(tzsubkey) - REG_TIME_ZONES_LEN);
    if (tzsubkey[sizeof(tzsubkey)-1] != 0) {
        fprintf(stderr, "timezone name too long\n");
        return -1;
    }

    if (ERROR_SUCCESS != (dw = RegOpenKey(HKEY_LOCAL_MACHINE, tzsubkey, &hkey_tz))) {
        fprintf(stderr, "failed to open: HKEY_LOCAL_MACHINE\\%s\n", tzsubkey);
        pWin32Error(dw, "RegOpenKey() failed");
        return -1;
    }

    rc = 0;
    #define X(param, type, var) \
        do if ((dw = sizeof(var)), (ERROR_SUCCESS != (dw = RegGetValueW(hkey_tz, NULL, param, type, NULL, &var, &dw)))) { \
            fprintf(stderr, "failed to read: HKEY_LOCAL_MACHINE\\%s\\%S\n", tzsubkey, param); \
            pWin32Error(dw, "RegGetValue() failed"); \
            rc = -1; \
            goto ennd; \
        } while(0)
    X(L"TZI", RRF_RT_REG_BINARY, regtzi);
    X(L"Std", RRF_RT_REG_SZ, ptzi->StandardName);
    X(L"Dlt", RRF_RT_REG_SZ, ptzi->DaylightName);
    #undef X
    ptzi->Bias = regtzi.Bias;
    ptzi->DaylightBias = regtzi.DaylightBias;
    ptzi->DaylightDate = regtzi.DaylightDate;
    ptzi->StandardBias = regtzi.StandardBias;
    ptzi->StandardDate = regtzi.StandardDate;
ennd:
    RegCloseKey(hkey_tz);
    return rc;
}

#define ZONE "Russian Standard Time"

int main(int argc, char* argv[])
{
    DWORD dw;
    TIME_ZONE_INFORMATION tzi;
    dw = GetTimeZoneInformationByName(&tzi, ZONE);
    if (dw != 0) return 1;
    SYSTEMTIME lt;
    SYSTEMTIME ut = {
        2000, /*WORD wYear;*/
        1, /*WORD wMonth;*/
        0, /*WORD wDayOfWeek;*/
        1, /*WORD wDay;*/
        12, /*WORD wHour;*/
        0, /*WORD wMinute;*/
        0, /*WORD wSecond;*/
        0 /*WORD wMilliseconds;*/
    };
    SystemTimeToTzSpecificLocalTime(&tzi, &ut, &lt);

    printf("%d-%02d-%02d %02d:%02d:%02d UTC\n", ut.wYear, ut.wMonth, ut.wDay, ut.wHour, ut.wMinute, ut.wSecond);
    printf("=\n");
    printf("%d-%02d-%02d %02d:%02d:%02d Europe/Moscow\n", lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond);
    return 0;
}
like image 30
basin Avatar answered Sep 21 '22 23:09

basin