调整 .NET 中的 "Daylight Saving Time" (DST) 选项,就像 Windows

Adjust "Daylight Saving Time" (DST) option in .NET, just like Windows

我正在尝试在 UWP 应用程序中复制 Windows 日期和时间设置,但我在处理夏令时 (DST) 设置时遇到了麻烦。

我设法让一切正常工作,我可以从我的应用程序中很好地更改系统时间和时区,但是自动调整夏令时选项让我感到困惑。

起初我认为检查TimeZoneInfo.SupportsDaylightSavingTime就足够了,然后我发现我可能还需要通过[=14=检查当前选择的date/time是否在DST范围内].

嗯,我以为我做对了,但是经过测试,我自己的"Adjust DST"选项和Windows设置不一样,而且由于我看不到[=74] =] 源代码,我不知道他们正在检查 disable/enable 它的其他条件。

我的 UWP 应用程序:

Windows 设置:

我还遗漏了什么吗?感兴趣的人可以在 找到我关于此的其他问题。

也许一些有内部消息的 MS 开发人员可以告诉我这个切换开关背后的逻辑:-)

提前致谢!

更新:

tzutil 的结果表明,当日期为 2011 年 5 月 16 日且时区为莫斯科 (UTC+3) 时,只需使用命令 tzutil /s "Russian Standard Time_dstoff" 即可关闭夏令时 returns "Russian Standard Time" 没有 _dstoff 因为 DST 不适用,这与 Windows 报告的一致。

但是,为什么 .NET 的 TimeZoneInfo class 会这样说? 还尝试过:

var currentDateTime = new DateTime(2011, 5, 16, 0, 0, 0, DateTimeKind.Local);
var isDst = TimeZoneInfo.Local.IsDaylightSavingTime(currentDateTime); //True

因此,.NET 表示当前日期在夏令时范围内,但无法使用 TZUTIL 或 Windows 设置关闭夏令时?

也许我在这里遗漏了一些非常明显的东西,但我没有看到...

更新:

由于调整规则,将月份更改为 2 月,在 Windows 中打开调整 DST 开关?但是,在赫尔辛基,我们也有这些转换,并且切换没有被禁用?有什么不同?

更新:

决定不做任何这些,只是检查 TimeZoneInfo.SupportsDaylightSavingTime。像 Windows 那样完全不值得任何人花费时间或精力去做。

一些事情来解决你的问题:

  • 永远不要使用 System.TimeZone class。它有很多问题,并且有更好的选择。对于大多数 .NET 代码,使用 System.TimeZoneInfo instead. Since you said you are writing a UWP application, you might also benefit from Windows.Globalization.Calendar and Windows.Globalization.DateTimeFormatting.DateTimeFormatter classes. Open source libraries such as Noda Time 也是一个不错的选择。

    在您显示的第一个代码块中,您使用的是 System.TimeZone.IsDaylightSavingTime。文档中的注释解释了您看到的结果:

    "Because the TimeZone class supports a single daylight saving time adjustment rule, the IsDaylightSavingTime(DateTime) method applies the current adjustment rule to any date, regardless of whether the adjustment rule was in effect on that date. Assuming that the operating system itself has accurate historic daylight saving time data, a more accurate result is available by using the TimeZoneInfo.IsDaylightSavingTime method. Whenever possible, use the TimeZoneInfo.IsDaylightSavingTime method."

  • 在您展示的第二个代码块中,您正确地使用了 System.TimeZoneInfo.IsDaylightSavingTime,并且在您预期 False 时得到了 True。虽然这令人困惑,而且可以说是不正确的,但它是可以解释的:

    • 2011 年,莫斯科在 UTC+3 开始日历年。然后它在 3 月 27 日 2:00 AM (reference here) 将其偏移量更改为 UTC+4。这是 标准时间 的更改,而不是 DST 相关更改。
    • Windows(TIME_ZONE_INFORMATIONDYNAMIC_TIME_ZONE_INFORMATION,更具体地说,REG_TZI_FORMAT)中的数据结构不支持在a中间改变标准偏移量公历年。它们在设计时并没有考虑到这种变化 - 很久以前。
    • 为了适应当地时间的变化,在Windows中建模为夏令时变化,其中夏令时开始于3月27日2:00 上午,一直持续到年底。这使本地时间在转换过程中保持准确,但代价是从 API 返回不准确的信息,这些信息声明或推断其结果与 DST 明确相关(例如 System.TimeZoneInfo.IsDaylightSavingTime)。
    • 因此,想像这样的方法可以告诉您某个时间段的本地时间与 UTC 的偏移量是否高于一年中的其他时间点。它可能与夏令时有关,也可能与标准时间的变化有关。
  • 据我所知,Windows 确实会查看此数据以确定是否显示该选项。如果当前日历年有转换(由系统时钟确定),则将显示该选项 - 无论此转换是否与 DST 相关或由于其他原因。

此外,一些一般性建议:

  • 大多数应用程序应该不会尝试更改系统时间、时区或 DST 设置。虽然确实有办法做到这一点,但它可能会产生严重的后果。这些是系统范围 全局设置,它们将影响计算机上的所有内容 - 而不仅仅是您的应用程序。

    特别是,将 time 更改得太大可能会影响与其他系统正确验证的能力。例如,Windows 身份验证(Active Directory、SSPI 等)使用 Kerberos - 它与 UTC 有 5 分钟的容差。此外,根据系统时钟,如果证书过期或尚未颁发,访问使用安全证书(HTTPS、SSL、TLS 等)的网站可能会失败。因此,最安全的成功途径是自动设置时间,并且不允许用户偏离。

    虽然更改时区and/or夏令时设置不会影响身份验证,它仍然是全局设置。机器上任何使用本地时间的地方都会接受这个设置——而不仅仅是你的应用程序。

  • 如果您确实要更改时区,请记住您可能需要清除本地时区缓存才能在应用程序中获取新设置。 .

  • 如果您的意图只是更改应用程序的时区,那么只需跟踪所选时区的 TimeZoneInfo.Id 并通过 TimeZoneInfo.ConvertTime 应用它,然后需要的相关方法。

  • 您可能不需要设置来禁用自动 DST 调整。 Windows 中存在此设置,是早期 WinNT 和 Win9x 时区设置的原始实现的遗留工件。大多数用户应该保留它。

    现在关闭它只有一个合法的用例,即当政府宣布将时区从有 DST 的时区更改为没有 DST 的时区(或 "permanent DST") and 没有其他现有时区条目具有相同的基准偏移量但没有 DST and 当上述政府没有提供足够的时间让 Microsoft 在更改生效之前为受影响的区域创建和分发新的时区条目。这样的事情确实会发生,但很少见。恕我直言,此设置在未来某个时候消失是合理的。 (仅代表个人观点,不代表微软。)