简体   繁体   中英

How to get timezone abbreviation under Windows

We are trying to get the timezone from std::tm with strftime :

char timezone[50];
strftime(timezone, sizeof(timezone), "%Z", &timeCreated);

On iOS, we get "EST" which is what we want. But on Windows, we get "Eastern Summer Time". Anybody know how to consistently get the current timezone in C++ in abbreviation form?

I consider making the abbreviation from the full name of the timezone by simply picking out the first character in each word. But I check the list of abbreviations and notice that we could have timezone like this one "Chuuk Time" and abbreviated as "CHUT". Which makes manually adjusting not possible.


Not the same as Question: Windows Timezone and their abbreviations? I don't need a full list of all timezones and abbreviations. But instead, I need a systematic way to the current timezone using for example strftime . I want them to use the system's current timezone and the the current local.

Time zone information under Windows is kept in registry, you can find it in the following registry key :

HKEY_LOCAL_MACHINE
   SOFTWARE
      Microsoft
         Windows NT
            CurrentVersion
               Time Zones
                  time_zone_name

you will not find there any abbreviations. The reason is mostly because it is not standardised, and also one abbreviation can be assigned to many time zone names, for more read here . Your aproach with taking first letter is fine, you can look up names also on this wiki:

https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations

Also see this thread from MSDN forums:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/3aa4420a-a5bf-48a3-af13-17a0905ce366/is-there-any-way-to-get-timezone-abbreviations?forum=csharpgeneral

Using this free, open-source library that has been ported to VS-2013 and later:

#include "tz.h"
#include <iostream>

int
main()
{
    using namespace std::chrono;
    using namespace date;
    std::cout << format("%Z\n", make_zoned(current_zone(), system_clock::now()));
}

This just output for me:

EDT

Fully documented.

This library uses the IANA timezone database , and when current_zone() is called, translates the current Windows timezone into the appropriate IANA timezone .

GetDynamicTimeZoneInformation is probably a good choice. However, the minimum supported versions are Windows Vista, Windows Server 2008 and Windows Phone 8. So for anything below that GetTimeZoneInformation is better.

However another issue is both sometimes return StandardName or DaylightName empty.

In that case you have to use the windows registry as marcinj has stated. Here is the function taken from gnu cash which was also modified from glib.

static std::string
windows_default_tzname(void)
{
    const char *subkey =
        "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
    constexpr size_t keysize{128};
    HKEY key;
    char key_name[keysize]{};
    unsigned long tz_keysize = keysize;
    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, subkey, 0,
                      KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
    {
        if (RegQueryValueExA(key, "TimeZoneKeyName", nullptr, nullptr,
                             (LPBYTE)key_name, &tz_keysize) != ERROR_SUCCESS)
        {
            memset(key_name, 0, tz_keysize);
        }
        RegCloseKey(key);
    }
    return std::string(key_name);
}

This can be done with the Windows Runtime (WinRT) API, specifically the Calendar.GetTimeZone method . I don't have the C++ code to do so, but here it is with Rust/WinRT version 0.7 from the Rust crate iana-time-zone . The C++ version will be similar.

use windows::globalization::Calendar;

let cal = Calendar::new()?;
let tz_hstring = cal.get_time_zone()?;

# convert the Windows HString to a Rust std::string::String
tz_hstring.to_string()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM