Daylight Saving Time change with an absolute date
我正在尝试在我的闹钟应用程序中实现正确的DST调整处理。所以我正在阅读动态时区信息的描述,我使用它通过GetTimeZoneInformationForYear API检索当前DST调整信息,它说:
DaylightDate:
A SYSTEMTIME structure that contains a date and local
time when the transition from standard time to daylight saving time
occurs on this operating system. If the time zone does not support
daylight saving time or if the caller needs to disable daylight saving
time, the wMonth member in the SYSTEMTIME structure must be zero. If
this date is specified, the StandardDate member in this structure must
also be specified. Otherwise, the system assumes the time zone data is
invalid and no changes will be applied. To select the correct day in
the month, set the wYear member to zero, the wHour and wMinute members
to the transition time, the wDayOfWeek member to the appropriate
weekday, and the wDay member to indicate the occurrence of the day of
the week within the month (1 to 5, where 5 indicates the final
occurrence during the month if that day of the week does not occur 5
times).If the wYear member is not zero, the transition date is
absolute; it will only occur one time. Otherwise, it is a relative
date that occurs yearly.
我还检查了目前在世界各地观察到的DST调整,如果相对DST调整看起来非常直接,我不清楚如何通过动态的时区信息来传递以下调整——只有一个月和一天。
例如:
1 2 3 4 | Egypt ----- DST Start: May 15 DST End: Last Friday September |
或者这个:
1 2 3 4 | Iran ---- DST Start: March 21–22 DST End: September 21–22 |
有人知道怎么做吗?
要了解时区结构,可以查看以下项下的Windows注册表:
在这里,您将找到Microsoft时区数据库的所有内置时区,该数据库由Microsoft通过Windows更新进行维护。
让我们看看您提到的一个示例案例:
由此我们可以看出,2005-2011年有特定的DST规则。在这个范围之外,我们回到根条目的
你会注意到2014年埃及的入境记录不见了。这是因为埃及几乎没有注意到即将发生的变化。您可以预料,很快将有一个热修复程序从微软与更新可用。
注册表中的二进制数据反序列化为
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; |
您应该注意的一个问题是,Windows不喜欢在午夜转换的时区。解决方法是,不要说"9月最后一个星期五的00:00",而是说"9月最后一个星期四的23:59:59.999"。但是,在这里您必须小心,因为像这样的规则有时会导致错误的派生日期。为此,有时每年都有自己的规则。定期模式格式仍在使用,而不是固定日期格式,主要用于一致性目的。
然而,还有另一个问题——这种结构一年只能支持两次夏令时转换。DST开始时一个在
我假设微软将推出多个更新更改,因此为了举例,我们将省略斋月时期。此规则从5月的第2个星期三23:59:59.999开始,到9月的最后一个星期四23:59:59.999结束。
1 | "TZI" = 88ffffff 00000000 c4ffffff 000009000400050017003b003b00e703 000005000300020017003b003b00e703 |
对应于具有这些值的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | { "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 } } |
我认为这个答案足够长,所以如果你愿意的话,我将留给你来推断伊朗的规则。不过,我要指出的是,伊朗的Windows数据自2009年以来一直不正确,至今尚未收到更新。- -
作为补充说明,如果要指定固定日期规则,可以提供非零的"实际"年份值。然后day字段表示实际日期,而不是事件。然而,这通常是避免的,因为它只对适用于个别年份的动态DST规则有意义。在根节点的通用
更新
微软发布了2014年埃及KB296790的更新。
伊朗是一个奇怪的国家,因为DST的过渡日期不符合微软注册表所期望的正常规则。三月的第二个星期天。所以我同意您需要使用绝对日期,但是要使用注册表格式。DST过渡日期的工作日几乎每年都不同。
伊朗夏令时过渡日期以波斯历为基础https://mm.icann.org/pipermail/tz/2003-3月/012053.html
因此,动态注册方法将是一个每年都有很多变化的答案!