关于C#:如何获取另一个时区的夏令时状态

How to get daylight saving status of another time zone

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

我将每个日期时间事件(发生的时刻)转换并存储为UTC格式,这样任何连接到服务器的客户机应用程序都可以读取事件的UTC时间,并将其转换并显示在客户机自己的TZ中。

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

服务器可以检查它是否在夏令时,但这将是服务器自己的TZ(东部时间)。我能想到的最好办法是读取服务器的本地日光节约信息,并将其用于PT,但我知道这不是100%准确。尤其是当ET刚刚开始(或停止)使用日光节约时,PT还有几个小时可以这样做时,通过短窗口。

现在我的问题是,有没有一种方法(在Windows API中)可以准确地了解另一个时区的夏令时状态,无论服务器应用程序位于哪个时区?

编辑:好的,我如何将它从东部时间运行的Windows计算机转换为UTC"Sun,Mar 13,2016,1:15 am pt"?(注意,当正在运行的机器(在ET中)在此时处于DST中,并且要转换的日期/时间不只是在DST中时,特别选择的日期/时间。我已经介绍了UTC转换,但无法确定给定的日期/时间是否为DST。


Windows的时区数据实际存储在注册表中:

1
2
3
4
5
6
HKLM
  SOFTWARE
    Microsoft
      Windows NT
        CurrentVersion
          Time Zones

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

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

1
2
3
4
5
6
7
8
typedef struct _REG_TZI_FORMAT
{
    LONG Bias;
    LONG StandardBias;
    LONG DaylightBias;
    SYSTEMTIME StandardDate;
    SYSTEMTIME DaylightDate;
} REG_TZI_FORMAT;

两个相关的结构成员是StandardDateDaylightDate

有关详细信息,请参阅msdn:时区信息


我不确定Windows API,但一般来说,您要做的是调用mktime,远程时间的Tz值有效。在UNIX下,您可以直接调用setenv("TZ", whatever)来完成此操作。对窗户不太确定,但我想你也可以在那里做同样的事情。

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

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

下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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
"
, t, ctime(&t));
}

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

附录:这对Windows也没有帮助,但是如果您不喜欢每次需要在不同时区处理时间时从程序内部设置一个环境变量,请查看是否可以使用BSD函数tzalloclocaltime_rzmktime_z