c++ - Windows时区写入注册表是否可靠?

标签 c++ date time timezone dst

我正在创建一个应该在多个时区工作的c++项目。应用程序接收到一个带有引用时区的事件,并且该事件以图形方式向用户显示在其本地时区的正确时间。例如,在柏林工作的用户收到在东京写的事件。来自东京的事件首先在UTC时间转换,然后从UTC重新转换为柏林的计算机本地时间,最后在其图形界面上显示给用户。
要将UTC转换为本地计算机时间,我可以使用Windows API的多个功能来完成这项工作。但是为了将时间从另一个时区转换为UTC,我需要从Windows注册表中获取时区信息。
现在,某些时区也需要考虑夏令时。我可以从Windows信息中创建重复规则,而不会出现问题。但是,我注意到DST应该发生的日期有时在几个时区都是不正确的。例如,“E。南美标准时间”。由于Windows提供了重复发生的功能,因此DST开始的时间提前1周开始。
如果我理解正确,Windows针对该特定时区返回的重复规则将显示为“每年的第二个月,第二个月的第二周”。但是,此规则很少与更改时间在Internet上发布的正确日期匹配,而如果规则为“每年的第二个月,每月的第三周”,则日期都是正确的。此外,如您所提供的屏幕截图所示,Windows注册表数据显示DST开始时间为2周(以蓝色突出显示),而DST结束时间为3周(以红色包围),这由我的代码正确计算。数据内容的描述可以在这里找到:http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx
enter image description here
我有几个问题

  • 我是否正确理解重复规则? (这是MSDN所说的:https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx)
  • 是否存在关于多个时区的已知问题,尤其是“E.南美标准时间”?
  • 是否有DST开始日期(显然每年每年定期发生)在第10个月的第3周有一个在第2周设置值的原因吗?
  • 如果不是,在Windows注册表中编写的时区是否可靠,我应该使用Windows API的哪个功能来将DST时区转换为与在本地计算机上设置的时区不同的时区中写入的日期?

  • 注意在发布此消息之前,我已强烈验证我从注册表读取的数据是否正确。我很确定这不是此类型的错误。
    注意我正在使用Windows 7,但是在Windows 10上问题仍然相同

    最佳答案

    作为一名与Windows时区数据密切相关的Microsoft员工,请允许我向您保证,Microsoft会非常努力地确保其发布更新以保持Windows时区数据的准确性。

    存在一些挑战,包括政府提供的the timing of time zone changes。例如,我们最近posted a notice about upcoming Windows time zone changes for Fiji, Cyprus, Sudan, Tonga, Namibia, and Turks & Caicos。在某些情况下,我们可以满足这些不同政府规定的生效日期。在某些情况下,我们不能这样做,因为他们没有提供足够的交货时间。

    考虑一下最近发生的苏丹一案,他告诉IANA tz mailing list on October 17th, 2017一项变更于2017年11月1日生效。IANA已处理此更改,微软也已处理。但是由于通知时间短,以及在Windows操作系统中处理此类更改所花费的时间,在Windows时区数据中创建新的"Sudan Standard Time"时区还需要一段时间。因此,我们发布临时指南以暂时使用不同的时区,然后在获得正确反射(reflect)受影响区域中整个时间历史的数据后再切换回去。

    关于您提到的Windows时区"E. South America Standard Time",时区数据正确。如果展开注册表项,则会看到有一个名为“Dynamic DST”的子项,其中包含数据的逐年更改。对于某些时区,这根本不是必需的,而对于其他时区,您会发现很少的数据,因为同一条规则会年复一年地重复。但是在巴西,您会注意到2009年到2040年的动态DST条目。

    Windows TZ Registry Data

    (单击图像可查看完整分辨率,并注意我手动标记为红色的区域逐年更改)

    动态DST条目支持Win32 DYNAMIC_TIME_ZONE_INFORMATION结构以及名称中带有“dynamic”的相应API,例如GetDynamicTimeZoneInformation。 (它们还支持.NET Framework中的System.TimeZoneInfo类。)这些API中的大多数自Windows Vista/Server 2008起就已经存在,而其他一些API则来自Windows 7/Server 2012。

    请注意,父键中的TZI条目是由内部Windows进程从当年的动态规则复制而来的。它支持与Win32 TIME_ZONE_INFORMATION结构一起使用的API,该API自Windows 2000以来就已经存在。

    要回答您提出的特定问题:

    Have I understood the recurrence rule correctly?



    您引用的特定规则仅适用于2017年,它说DST在本地时间的第二个月(二月)第二个月的3月6日结束,并在第十个月(十月)再次开始。第二个星期六,当地时间23:59:59.999。请记住,巴西位于南半球,因此DST在今年下半年开始,并在明年年初结束。

    另外,您可能想知道为什么周六是23:59:59.999,而不是周日00:00:00.000。这是历史的产物。过去,某些程序和过程会错误地使用<=而不是<来评估转换,因此会不小心将时钟移至第二天,即从毫秒移出第二天,然后又移回第二天。一天错误地更改所产生的事件可能会导致进一步的问题。微软已尽力修复了这些错误,但仍然选择了1毫秒的距离,而不是冒险一天之内在某个新地方弹出问题。 (这仅适用于恰好在午夜发生的过渡。)

    Is there known issues about several timezone, especially the "E. South America Standard Time" one?



    该时区没有已知问题,但是存在一个已知问题,即Windows时区(即使具有动态DST数据)在一年中最多只能支持两个时区转换。因此,在摩洛哥that transition four times per year之类的地方,存在一些内部变通办法,这些办法可以使当前时区数据保持同步,从而“现在”可以准确表示本地时间,但不能在任何给定时间正确表示一年中的所有时间点。

    我们目前还没有时区可以为Troll Station, Antarctica清晰地映射。原因是从2005年到2015年,这个research station(50岁以下的人口)每年都要转换三个不同的偏移量(UTC + 0,UTC + 1和UTC + 2)。

    如果您的应用程序严重依赖于上述两种情况,那么我建议使用具有IANA数据源的API,而不要使用Win32 API。

    Is there a reason why a DST start date, that obviously occurs regularly every year, on the 3rd week of the 10th month, have a value set on the 2nd week?



    是的,如上所述,这是由于1ms的故意错误造成的。巴西部分地区已实行DST的2017年DST将于10月15日星期日00:00:00.000开始。那是一个月的第三个星期日。提前1毫秒是10月14日(星期六)的23:59:59.999,这是该月的第二个星期六。每年可能会有所不同,这就是为什么有动态DST数据的原因。

    Are timezone written in Windows registry reliable, if not, which function of the Windows API should I use to convert a timezone with DST from a date written in a different timezone than the one set on the local machine?



    如果您使用的是Win32 API,它们将自己使用注册表数据,因此无需直接使用注册表数据。您应该首选API的“动态”版本,因为它们正确地说明了动态DST数据的逐年变化。有时这些被标记为“Ex”。例如,您询问的函数最好由 TzSpecificLocalTimeToSystemTimeEx 函数处理。

    ...

    综上所述,如果您能够避免在应用程序中使用Windows时区数据,我建议您这样做。优先使用IANA数据源或从中得出的数据源。有许多使用IANA时区数据的途径。 WinRT/UWP中的较新的Windows API(例如Windows.Globalization.CalendarWindows.Globalization.DatetimeFormatting.DateTimeFormatter)确实使用IANA time zones,这显然是前进的道路。在标准C++空间中,我强烈建议使用Howard Hinnant's date/tz librariesICU project提供的那些。还有其他几种可行的选择。

    关于c++ - Windows时区写入注册表是否可靠?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47104967/

    相关文章:

    c++如果它们共享一个数字,则组合 vector

    c++ - 将 string 转换为 char ,空格字符未正确转换

    r - R中日期之间的差异

    php - 在php中找到特定日期/时间的最大和最小可能值

    javascript - 在JavaScript中,如何在特定时间运行函数?

    java - 在linux中模拟 "faster time"

    c++ - 如何将文件用作现有 C++ 程序的输入流?

    c++ - 我可以返回 std::thread

    jquery - 计算点击提交按钮之前所花费的时间

    JavaScript 不会解析 GMT 日期/时间格式