假设我的Windows服务器应用程序运行在东部时区(NY)。
我将每个日期时间事件(发生的时刻)转换并存储在UTC中,以便连接到服务器的任何客户端应用程序读取事件的UTC时间,并将其转换并显示在客户端自己的TZ中。
但这里有一个棘手的部分,一些事件以另一个州的时间报告其时间戳,并且没有明确指定夏令时信息(例如xx:xx:xx AM PT,意思是太平洋时间,但我不知道它目前是否处于夏令时)。
服务器可以检查它是否处于夏令时,但这将用于服务器自己的TZ(即东部时间)。我能想到的最好办法是读取服务器的本地夏令时信息,并将其用于PT,但我知道这不是100%准确的。特别是当ET刚刚开始(或停止)使用夏令时,PT还有几个小时的时间时,通过短窗口。
现在我的问题是,无论服务器应用程序位于哪个时区,是否有一种方法(在Windows API中)可以准确地了解另一个时区的夏令时状态?
编辑:好的,如何从运行在东部时间的Windows机器将其转换为UTC"2016年3月13日星期日上午1:15 PT"?(请注意,当正在运行的机器(在ET中)此时处于夏令时,并且要转换的日期/时间尚未处于夏令时时,特别选择此日期/时间。我有UTC转换,但不知道给定的日期/时间是否在夏令时。
Windows的时区数据实际上存储在注册表中:
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;
两个相关的结构成员是StandardDate
和DaylightDate
。
有关更多详细信息,请参阅MSDN:TIME_ZONE_INFORMATION
我不确定Windows API,但通常情况下,您要做的是使用有效的远程时间的TZ值调用mktime
,。在Unix下,您可以直接调用setenv("TZ", whatever)
来执行此操作。不确定Windows,但我认为你也可以在那里做同样的事情。
如果除了mktime
和timegm
之外,还有一个变体可以让您明确指定要使用的区域(而不是将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 = %.24sn", t, ctime(&t));
}
这告诉您洛杉矶时间12:30:15对应于Unix(UTC)时间1113334215和纽约时间15:30:15。
附录:这对Windows也没有帮助,但如果你不喜欢每次需要使用不同时区的时间时都在程序内部设置环境变量,那么看看你是否可以使用BSD函数tzalloc
、localtime_rz
和mktime_z
。