夏令时更改为绝对日期

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

DaylightDate

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

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

我还在检查世界各地观察到的当前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

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


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

HKLMSOFTWAREMicrosoftWindows NTCurrentVersionTime Zones

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

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

.Egypt Standard Time

埃及

.Egypt Standard TimeDynamic DST

埃及动态DST

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

你会注意到,2014年的埃及项目不见了。 这是因为埃及几乎没有注意到即将到来的变化。 您可以预期,Microsoft即将推出可用于此更新的修补程序。

注册表中的二进制数据反序列化为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”。 但是,在这里你必须小心,因为这样的规则有时会导致错误的派生日期。 为了应对这种情况,有时每年都会有自己的规则。 重复模式格式仍然使用而不是固定日期格式,主要是为了一致性的目的。

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

我会假设微软将推出多重更新的改变,所以为了举例,我们将离开斋月。 该规则于5月2日周三23:59:59.999启动夏令时,并于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

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

链接地址: http://www.djcxy.com/p/29381.html

上一篇: Daylight Saving Time change with an absolute date

下一篇: aware DateTime when server set to UTC