如何获取其他时区的夏令时状态

时间:2016-04-15 16:56:08

标签: c datetime winapi timezone dst

假设我的Windows服务器应用程序在东部时区(NY)运行。

我以UTC格式转换并存储每个日期时间事件(它们发生的那一刻),以便连接到服务器的任何客户端应用程序读取事件的UTC时间并转换并在客户端自己的TZ中显示它。

但这是一个棘手的部分,一些事件在另一个州的时间报告他们的时间戳,并没有明确指定夏令时信息(例如xx:xx:xx AM PT,意思是太平洋时间,但我不知道它目前是否在夏令时)。

服务器可以检查它是否在夏令时期间,但这将是服务器自己的TZ(这是东部时间)。我能想到的最好的方法是阅读服务器的本地夏令时信息并将其用于PT,但我知道这不是100%准确。特别是当ET刚刚启动(或停止)使用夏令时时,短窗口仍然需要数小时才能完成。

现在我的问题是,有没有办法(在Windows API中)准确地找出另一个时区的夏令时状态,无论服务器应用程序驻留在哪个时区?

编辑好,如何将其转换为UTC“Sun,Mar 13,2016 1:15 AM PT”,来自在东部时间运行的Windows计算机? (请注意,当正在运行的机器(在ET中)当前处于DST状态时,特别选择的日期/时间和要转换的日期/时间在DST中尚未。我已涵盖UTC转换但无法确定给定的日期/时间是否在DST中。

2 个答案:

答案 0 :(得分:2)

视窗'时区数据实际存储在注册表中:

HKLM
  SOFTWARE
    Microsoft
      Windows NT
        CurrentVersion
          Time Zones

"时区"实际上是两个字。

每个时区都有自己的子项,每个子项的TZI值都是二进制REG_TZI_FORMAT结构:

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

两个相关的结构成员是StandardDateDaylightDate

有关详细信息,请参阅MSDN:TIME_ZONE_INFORMATION

答案 1 :(得分:1)

我不确定Windows API,但一般来说,您要做的是使用远程有效时间的TZ值来调用mktime。在Unix下,您可以直接调用setenv("TZ", whatever)来执行此操作。不确定Windows,但我认为你也可以做同样的事情。

除了mktimetimegm之外,还有一个变体允许您明确指定要使用的区域(而不是将TZ环境变量视为全局变量),这肯定会很好。 ,但这种变体不是标准的。

当您不知道DST是否生效时转换本地时间时,请记住将tm_isdst设置为-1,以便库可以为您解决。

以下是一个例子:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    struct tm tm = {0};
    time_t t;
    tm.tm_hour = 12; tm.tm_min = 30, tm.tm_sec = 15;            /* 12:30:15 */
    tm.tm_year = 2005-1900; tm.tm_mon = 4-1; tm.tm_mday = 12;   /* 2005-04-12 */
    tm.tm_isdst = -1;
    setenv("TZ", "America/Los_Angeles", 1);
    t = mktime(&tm);
    setenv("TZ", "America/New_York", 1);
    printf("%ld = %.24s\n", t, ctime(&t));
}

这告诉你洛杉矶时间12:30:15对应于Unix(UTC)时间1113334215和纽约时间15:30:15。

附录:这对Windows也无济于事,但是如果你不喜欢每次需要在不同的时区工作时从程序内部设置环境变量,看看你是否可以使用BSD功能tzalloclocaltime_rzmktime_z