我正在尝试在闹钟应用中实施正确的DST调整处理。所以我正在阅读DYNAMIC_TIME_ZONE_INFORMATION的说明,用于通过GetTimeZoneInformationForYear API检索当前的DST调整信息,并说明如下:
DaylightDate :
包含日期和本地的SYSTEMTIME结构 从标准时间过渡到夏令时的时间 发生在此操作系统上。如果时区不支持 夏令时或者呼叫者需要禁用夏令时 时间,SYSTEMTIME结构中的 wMonth 成员必须为零。如果 指定此日期,此结构中的StandardDate成员必须 也可以指定。否则,系统假定时区数据为 无效,不会应用任何更改。选择正确的日期 月份,将 wYear 成员设置为零, wHour 和 wMinute 成员 到了过渡时间, wDayOfWeek 成员要适当 工作日和 wDay 成员表示当天的发生 月内的一周(1到5,其中5表示最终 如果一周的那一天没有发生,则在月内发生5 次)。
如果 wYear 成员不为零,则转换日期为 绝对;它只会发生一次。否则,它是一个亲戚 每年发生的日期。
我也正在查看世界各地观察到的current DST adjustments,如果相对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
有谁知道怎么做?
答案 0 :(得分:3)
要了解时区结构,有助于在以下密钥下查看Windows注册表:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\
在这里,您可以找到the Microsoft time zone database的所有内置时区,即maintained by Microsoft via Windows Updates。
让我们看看你提到的一个例子:
.\Egypt Standard Time\
.\Egypt Standard Time\Dynamic DST\
由此可以看出,2005 - 2011年定义了特定的DST规则。在此范围之外,我们回退到根条目的TZI
值。
您会注意到埃及的2014年参赛作品遗失了。这是因为埃及几乎没有注意到the upcoming change。您可以预期很快就会有Microsoft的修补程序随更新一起提供。
注册表中的二进制数据被反序列化为REG_TZI_FORMAT
结构,如下所示:
typedef struct _REG_TZI_FORMAT
{
LONG Bias;
LONG StandardBias;
LONG DaylightBias;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
} REG_TZI_FORMAT;
您应该注意的一个问题是,Windows并不喜欢在午夜过渡的时区。解决方法是在9月的最后一个星期五和#34;而不是说" 00:00,而不是在9月的最后星期四" 23:59:59.999& #34 ;.但是,在这里你必须要小心,因为像这样的规则有时会导致错误的派生日期。为了解决这个问题,有时每年都会有自己的规则。仍然使用重复模式格式而不是固定日期格式,主要是出于一致性目的。
但是,还有另一个问题 - 这种结构只能支持一年内两个夏令时的转换。 DST开始时DaylightDate
,DST结束时StandardDate
一个。由于埃及正在制定DST ,除了斋月,因此会有four transitions。这也发生在Egypt in 2010中,并且也定期发生在Morocco中。为了解决这个设计缺陷,微软传统上发布了多个更新,时间恰好与变化相吻合。 (例如,请参阅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数据一直不正确,尚未收到更新。 : - /
作为旁注,如果要指定固定日期规则,则可以提供非零"真实"年价值。然后,day字段表示实际的日期 - 而不是发生的日期。但是,通常会避免这种情况,因为它仅对适用于各个年份的动态DST规则有意义。在根节点中的通用TZI
条目中使用固定日期是没有意义的。
<强>更新强>
Microsoft已在KB2967990发布了2014年埃及的更新。
答案 1 :(得分:0)
伊朗是一个奇怪的问题,因为DST过渡日期不符合Microsoft注册管理机构预期的正常规则。例如:三月的第二个星期天。所以我同意您需要使用绝对日期,但使用注册表格式。 DST过渡日期的工作日几乎每年都有所不同。
伊朗DST过渡日期基于波斯日历 https://mm.icann.org/pipermail/tz/2003-March/012053.html
因此,动态注册表方法将是每一年都有很多变化的答案!