首页 文章

夏令时随绝对日期而变化

提问于
浏览
0

我'm trying to implement correct DST adjustment handling in my alarm clock app. So I'读取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

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

2 回答

  • 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

    .\Egypt Standard Time\Dynamic DST\

    Egypt Dynamic DST

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

    你_1613444_因为埃及几乎没有注意到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不喜欢在午夜过渡的时区 . 解决方法是,不必说"00:00 on the last Friday in September",而是在9月的最后一个星期四说“23:59:59.999” . 但是,在这里你必须要小心,因为像这样的规则有时会导致错误的派生日期 . 为了解决这个问题,有时每年都会有自己的规则 . 仍然使用重复模式格式而不是固定日期格式,主要是出于一致性目的 .

    但是,还有另一个问题 - 这种结构只能支持一年中两个夏令时的转换 . 当DST开始时,一个在 DaylightDate ,当DST结束时,一个在 StandardDate . 由于埃及除了斋月之外正在制定夏令时,所以会有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
        }
    }
    

    我认为这个答案足够长,所以如果你愿意,我会留给你推断伊朗的规则 . 不过,我要指出,伊朗的Windows数据自2009年以来一直不正确,尚未收到更新 . : - /

    作为旁注,如果要指定固定日期规则,则可以提供非零"real"年值 . 然后,day字段表示实际的日期 - 而不是发生的日期 . 但是,通常会避免这种情况,因为它仅对适用于各个年份的动态DST规则有意义 . 在根节点中的泛型 TZI 条目中使用固定日期是没有意义的 .

    UPDATE

    Microsoft已于KB2967990发布了2014年埃及的更新 .

  • 0

    伊朗是一个奇怪的国家DST转换日期不符合Microsoft注册表所期望的常规规则 . 例如:三月的第二个星期天 . 所以我同意您需要使用绝对日期,但使用注册表格式 . DST过渡日期的工作日几乎每年都有所不同 .

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

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

相关问题