使用 C++ 在 Windows 中获取时区

Posted

技术标签:

【中文标题】使用 C++ 在 Windows 中获取时区【英文标题】:Getting timezone in Windows with C++ 【发布时间】:2011-08-15 08:31:49 【问题描述】:

我想同步 Windows 和 Linux 时钟。 Windows 获取其系统时钟(使用 GetSystemTimeAsFileTime 函数)并将其发送到 Linux。然后,Linux 相应地设置它的时钟(使用 settimeofday 函数)。

我还需要传输Windows的时区,并将其转换为Linux标准。如何在 C++ 中获取 Windows 的时区?

最好的祝愿, 穆斯塔法

【问题讨论】:

你已经尝试过什么?您的尝试有没有遇到任何问题? 当您说“linux 标准”时,您的意思是 UTC?您是否使用 UTC 时钟运行 Linux 机器? GetSystemTimeAsFileTime 不返回 UTC 吗?将两者同步到第三个 NTP 服务器或在其中一个盒子上运行 NTP 服务器并使用它不是更好吗?两种操作系统都有可用/内置的 NTP 客户端。 NTP 在许多情况下将是最佳选择。但在这种情况下,我需要将它们彼此同步,而不是实时同步。 【参考方案1】:

GetTimeZoneInformation 可能就是您要找的。​​p>

【讨论】:

谢谢,是的。它返回 TIME_ZONE_INFORMATION 结构,其中包括偏差(以分钟为单位的长整数)和区域名称。由于Linux中的时区名称不同,我认为最好使用Bias来设置Linux时区。但是,我找不到使用 Bias 设置 Linux 时区的方法。使用 GMT+x 导出 TZ 在我的 Ubuntu 上不起作用,【参考方案2】:

即使您不同步到标准时间,而是同步到机器之间的时间,您也应该使用 NTP。

NTP 是一个成熟、强大的协议,它已经解决了您将要发现或已经发现的所有问题:发现、通信传输、延迟和抖动、时区差异、管理偏差,因此您不会混淆共享同一台机器的其他进程,实际上正确设置了时间、权限等。

只需在您想要作为主控的机器上设置一个 NTP 服务器,然后在另一台机器上设置 NTP 客户端,查询主控。简单无痛。

我已经有一段时间没有设置 NTP 服务器了;我假设您可以使用操作系统标配的 NTP 实用程序以最少的配置完成这项工作,只要您对这些机器具有管理员权限。

【讨论】:

【参考方案3】:

GetDynamicTimeZoneInformation 是比较有用的功能。它还提供了时区的注册表项..

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

【讨论】:

【参考方案4】:

GetDynamicTimeZoneInformation 并不总是有效。支持的最低版本是 Windows Vista、Windows Server 2008 和 Windows Phone 8。因此,对于低于 GetTimeZoneInformation 的任何版本都更好。

但是另一个问题是有时返回 StandardNameDaylightName 为空。在这种情况下,您必须使用 Windows 注册表。这是从 gnu cash 中获取的函数,也是从 glib 中修改的。

static std::string
windows_default_tzname(void)

    const char *subkey =
        "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
    constexpr size_t keysize128;
    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);

【讨论】:

【参考方案5】:

这对我有用,也适用于 windows 和 linux 之间的端口

#include "time.h"
...
time_t now = time(NULL);
struct tm utctm;
utctm = *gmtime(&now);
utctm.tm_isdst = -1;
time_t utctt = mktime(&utctm);
// diff is the offset in seconds
long diff = now - utctt;

【讨论】:

以上是关于使用 C++ 在 Windows 中获取时区的主要内容,如果未能解决你的问题,请参考以下文章

windows进程启动设置时区限制

C++获取win10版本号为啥是6.2

如何在Win10系统内设置多时区时钟

win10 + vs2017 + vcpkg —— VC++ 打包工具

在 windows 中使用互斥锁进行进程间同步(win32 或 C++)

如何使用 C++ 获取 Windows 用户配置文件路径的父文件夹