夏令时更改绝对date

我正在尝试在闹钟应用程序中实施正确的DST调整处理。 所以我正在阅读DYNAMIC_TIME_ZONE_INFORMATION的描述,通过GetTimeZoneInformationForYear API检索当前的DST调整信息,并说明如下:

DaylightDate

在此操作系统上发生从标准时间到夏令时的转换时,包含date和本地时间的SYSTEMTIME结构。 如果时区不支持夏令时或呼叫者需要禁用夏令时,则SYSTEMTIME结构中的wMonth成员必须为零。 如果指定了此date,则必须指定此结构中的StandardDate成员。 否则,系统将假定时区数据无效,不会应用更改。 要select当月的正确date,请将wYear成员设置为零,将wHourwMinute成员设置为转换时间,将wDayOfWeek成员设置为适当的工作日,并将wDay成员设置为指定星期几月份(1至5,其中5表示如果一周中的某一天不发生5次,则月份中的最终发生)。

如果wYear成员不为零,则转换date是绝对的; 它只会发生一次。 否则,这是每年发生的相对date。

我也正在检查世界各地观察到的当前DST调整情况 ,如果相对DST调整看起来相当简单,我不清楚如何通过DYNAMIC_TIME_ZONE_INFORMATION传达以下调整 – 只需一个绝对的月份和一天。

例如:

Egypt ----- DST Start: May 15 DST End: Last Friday September 

或者这个:

 Iran ---- DST Start: March 21–22 DST End: September 21–22 

有谁知道如何做到这一点?

Solutions Collecting From Web of "夏令时更改绝对date"

要了解时区结构,可以使用以下键来查看Windows注册表:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\

在这里,您可以找到Microsoft时区数据库的所有内置时区, Microsoft时区数据库 由Microsoft通过Windows Updates进行维护 。

我们来看看你提到的一个例子:

.\Egypt Standard Time\

埃及

.\Egypt Standard Time\Dynamic DST\

埃及动态DST

从这里我们可以看到,2005 – 2011年定义了特定的DST规则。 在此范围之外,我们回退到根条目的TZI值。

你会注意到,2014年的埃及项目不见了。 那是因为埃及几乎没有注意到即将到来的变化 。 您可以预料,即将有微软提供的修补程序可用。

注册表中的二进制数据反序列化为REG_TZI_FORMAT结构,如下所示:

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

您应该注意的一个问题是,Windows不喜欢在午夜过渡的时区。 解决方法是不要说“9月最后一个星期五的00:00”,而是要在9月的最后一个星期四说“23:59:59.999”。 但是,在这里你必须小心,因为这样的规则有时会导致错误的派生日期。 为了反击,有时每年都会有自己的规则。 重复模式格式仍然使用,而不是固定日期格式,主要是为了一致性的目的。

但是,还有一个问题 – 这种结构只能支持一年中的两个夏令时转换。 一个在DaylightDate开始时,另一个在StandardDate DST结束时)。 由于埃及正在推行除斋月之外的 DST,因此将有四次过渡 。 这在2010年也发生在埃及 ,也经常在摩洛哥发生。 为了应对这种设计缺陷,微软传统上发布了多个更新,定时与这些更改一致。 (例如,请参阅KB2297272 。)

我会假设微软将推出多重更新的改变,所以为了举例,我们将离开斋月期间。 这条规则在5月2日星期三23:59:59.999开始了DST,并在9月的最后一个星期四23:59:59.999结束。

 "TZI" = 88ffffff 00000000 c4ffffff 000009000400050017003b003b00e703 000005000300020017003b003b00e703 

这对应于具有这些值的REG_TZI_FORMAT结构(为了清楚起见,为了JSON):

 { "Bias" : -120, // Standard offset is UTC+2 "StandardBias" : 0, "DaylightBias" : -60, // Subtract an hour for DST "StandardDate" : { "wYear" : 0, // Recurrence pattern "wMonth" : 9, // September "wDayOfWeek" : 4, // Thursday "wDay" : 5, // Last occurrence "wHour" : 23, "wMinute" : 59, "wSecond" : 59, "wMilliseconds" : 999 }, "DaylightDate" : { "wYear" : 0, // Recurrence pattern "wMonth" : 5, // May "wDayOfWeek" : 3, // Wednesday "wDay" : 2, // Second occurrence "wHour" : 23, "wMinute" : 59, "wSecond" : 59, "wMilliseconds" : 999 } } 

我想这个答案已经够长了,所以如果你愿意的话,我会留给你推断伊朗的规则。 不过,我要指出的是,自2009年以来,伊朗的Windows数据一直不正确,尚未收到更新。 : – /

作为一个方面说明,如果你想指定一个固定的日期规则,你可以提供一个非零的“真实”年价值。 然后,日期字段代表实际的日期 – 而不是事件的发生。 然而,这通常是避免的,因为它只适用于适用于个别年份的动态DST规则。 在根节点的通用TZI条目中使用固定日期是没有意义的。

UPDATE

微软在KB2967990发布了2014年埃及更新。

伊朗是一个奇怪的地方,因为DST转换日期不符合微软注册机构预期的正常规则。 例如:三月的第二个星期天。 所以我同意你需要使用绝对日期,但使用注册表格式。 DST过渡日期的平日几乎每年都有所不同。

伊朗DST过渡日期基于波斯日历https://mm.icann.org/pipermail/tz/2003-March/012053.html

所以动态注册表方法将是每一年都有很多变化的答案!