调整.NET中的“夏令时”(DST)选项,就像Windows

时间:2018-05-16 08:29:30

标签: c# .net windows timezone dst

我正在尝试复制Windows Date& UWP应用程序中的时间设置,我在处理夏令时(DST)设置时遇到了不好的时间。

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

起初我认为检查TimeZoneInfo.SupportsDaylightSavingTime就足够了,然后我发现我可能还需要通过执行TimeZoneInfo.IsDaylightSavingTime来检查当前所选日期/时间是否在DST范围内。

好吧,我以为我没错,但经过​​测试,我自己的“调整DST”选项与Windows设置不一样,而且由于我看不到Windows源代码,我不知道其他什么他们正在检查禁用/启用它的条件。

我的UWP申请:

Date & Time settings in my UWP app

Windows设置:

Windows Date & Time settings

我还在这里遗漏一些东西吗?对于那些感兴趣的人,可以找到关于此问题的另一个问题{/ 3}}。

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

提前谢谢!

更新

来自here的结果显示,当日期是2011年5月16日,时区是莫斯科(UTC + 3)时,使用命令tzutil /s "Russian Standard Time_dstoff"关闭DST只返回“俄罗斯标准时间”而不使用_dstoff因为DST不适用,并与Windows报告的内容对齐。

但是,为什么.NET的TimeZoneInfo类会说这个呢? tzutil 也试过:

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

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

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

更新

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

更新

决定不执行任何操作,只需检查TimeZoneInfo.SupportsDaylightSavingTime即可。完全像Windows一样,不值得任何人的时间或精力。

1 个答案:

答案 0 :(得分:2)

解决问题的一些方法:

  • 永远不要使用System.TimeZone课程。它有很多问题,还有更好的选择。对于大多数.NET代码,请改用System.TimeZoneInfo。既然您说您正在编写UWP应用程序,那么您可能也会受益于Windows.Globalization.CalendarWindows.Globalization.DateTimeFormatting.DateTimeFormatter类。像Noda Time这样的开源库也是一个不错的选择。

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

      

    "由于TimeZone类支持单个夏令时调整规则,因此IsDaylightSavingTime(DateTime)方法会将当前调整规则应用于任何日期,无论调整规则是否生效那个日期。假设操作系统本身具有准确的历史夏令时数据,则可以使用TimeZoneInfo.IsDaylightSavingTime方法获得更准确的结果。只要有可能,请使用TimeZoneInfo.IsDaylightSavingTime方法。"

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

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

另外,一些一般建议:

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

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

    虽然更改时区和/或DST设置不会影响身份验证,但它仍然是全局设置。使用本地时间的机器上的任何地方都会选择此设置 - 而不仅仅是您的应用程序。

  • 如果您确实要更改时区,请记住,您可能需要清除本地时区缓存以获取应用程序中的新设置。 See this question and answer for more details

  • 如果您的目的只是更改应用的时区,那么只需跟踪所选时区的TimeZoneInfo.Id,然后通过TimeZoneInfo.ConvertTime及相关方法应用

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

    关闭它现在只有一个合法用例,这是政府宣布时区从具有DST的用户改为没有DST(或具有"永久性DST& #34;) 没有其他现有的时区条目具有相同的基本偏移而没有DST 当政府没有提供足够的时间让微软在变更生效之前为受影响地区创建和分发新的时区条目。这样的事情确实发生了,但很少见。恕我直言,这种情况在将来的某个时刻消失是合理的。 (仅仅是我个人的意见,不是就这个问题向微软发言。)