【问题标题】:How to get timezone abbreviation under WindowsWindows下如何获取时区缩写
【发布时间】:2016-04-14 18:05:58
【问题描述】:

我们正在尝试从std::tmstrftime 获取时区:

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

在 iOS 上,我们得到了我们想要的“EST”。但在 Windows 上,我们得到“东部夏令时间”。有人知道如何以缩写形式始终如一地获取 C++ 中的当前时区吗?

我考虑通过简单地挑选每个单词中的第一个字符来从时区的全名中制作缩写。但我检查了abbreviations 的列表,并注意到我们可以有像“Chuuk Time”这样的时区,缩写为“CHUT”。这使得手动调整是不可能的。


与问题不同:Windows Timezone and their abbreviations? 我不需要所有时区和缩写的完整列表。但相反,我需要一个系统的方法来使用例如strftime 来访问当前时区。我希望他们使用系统的当前时区和当前本地。

【问题讨论】:

标签: c++ windows datetime


【解决方案1】:

使用已移植到 VS-2013 及更高版本的 free, open-source library

#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()));
}

这只是为我输出:

EDT

Fully documented.

这个库使用IANA timezone database,当current_zone()被调用时,将当前的Windows时区转换成合适的IANA timezone

【讨论】:

  • 还有其他不使用你的开源库的吗??
  • 这是另一个时区开源库:github.com/google/cctz 我不确定它是否解决了 OP 的问题。
【解决方案2】:

Windows下的时区信息保存在注册表中,可以在以下registry key找到:

HKEY_LOCAL_MACHINE
   SOFTWARE
      Microsoft
         Windows NT
            CurrentVersion
               Time Zones
                  time_zone_name

您不会在其中找到任何缩写词。原因主要是因为它没有标准化,而且一个缩写可以分配给许多时区名称,更多阅读here。您使用第一个字母的方法很好,您也可以在此 wiki 上查找名称:

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

另请参阅 MSDN 论坛中的此主题:

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

【讨论】:

  • +1 获取有用的链接!!它可能不会直接回答问题,但知道知道这个时区实际上不是那么标准,我可能会考虑在代码中不使用这个值。
【解决方案3】:

GetDynamicTimeZoneInformation 可能是一个不错的选择。但是,支持的最低版本是 Windows Vista、Windows Server 2008 和 Windows Phone 8。因此,对于低于 GetTimeZoneInformation 的任何版本都更好。

但另一个问题是有时返回 StandardNameDaylightName 为空。

在这种情况下,您必须按照 marcinj 的说明使用 Windows 注册表。这是从 gnu cash 中获取的函数,也是从 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);
}

【讨论】:

    【解决方案4】:

    这可以通过 Windows 运行时 (WinRT) API,特别是 Calendar.GetTimeZone method 来完成。我没有执行此操作的 C++ 代码,但这里使用的是来自 Rust crate iana-time-zone 的 Rust/WinRT 版本 0.7。 C++ 版本将类似。

    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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-12
      • 2020-07-20
      • 2013-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-20
      • 2022-01-08
      相关资源
      最近更新 更多