23

I'm creating a c++ project that should works on several timezone. The application receives an event, with a reference timezone, and this event is shown graphically to the user at the correct hour, in his local timezone. For example, an user working in Berlin receives an event written in Tokyo. The event from Tokyo is first converted in UTC time, then reconverted from UTC to the computer local time in Berlin, and finally shown to the user on his graphical interface.

To convert from UTC to local computer time I have several functions of the Windows API at my disposal to do the job. But in order to convert a time from another timezone to UTC, I need to get the timezone information from the Windows registry.

Now some timezone have also a Daylight Saving Time to consider. I'm able to create a recurrence rule from the Windows info without problems. However I noticed that the day the DST should occur is sometimes incorrect on several timezone. For example, the "E. South America Standard Time". With the recurrence provided by Windows, the DST start day begins 1 week sooner.

If I understood right, the recurrence rule returned by Windows for this specific timezone says "every year, on the 2nd month, on the 2nd week of the month". However this rule matches rarely with the correct date published on the internet for the time changing, whereas the dates are all correct if the rule would be "every year, on the 2nd month, on the 3nd week of the month". Furthermore, as you can see on the provided screenshot, the Windows registry data shows 2 weeks for the DST start time (highlighted in blue), but 3 weeks for the DST end time (surrounded in red), which is calculated correctly by my code. The description of the data content may be found here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx

enter image description here

I have several questions

  • Have I understood the recurrence rule correctly? (Here is what MSDN says about it: https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx)
  • Is there known issues about several timezone, especially the "E. South America Standard Time" one?
  • 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?
  • 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?

NOTE I have strongly verified if the data I read from the registry were correct before posting this message. I'm pretty sure that is not an error of this type.

NOTE I'm working with Windows 7, but the issue remains the same on Windows 10

Community
  • 1
  • 1
Jean-Milost Reymond
  • 1,833
  • 1
  • 15
  • 36
  • It is as reliable as your machine's Windows Update allows. And avoids relying on timezone and DST info from countries like Cuba and Venezuela, places that Microsoft gave up on trying to keep updated and hopped in and out of that timezone before. And won't take data from tribal areas, certain counties in Arizona and Indiana or whatever town whose mayor decided to not opt-in on the timezone's DST rules because he doesn't like anybody to tell him what to do. He can't change UTC, so be sure to only record that one. – Hans Passant Nov 03 '17 at 22:43
  • It's a no-brainer: always record all times in UTC. – Michaël Roy Nov 03 '17 at 22:59
  • 2
    @MichaëlRoy - no, not *always*. That's often stated advice that is short-sighted and cutting out many scenarios that require local time. For example, scheduling. Please refrain. Thanks. – Matt Johnson-Pint Nov 03 '17 at 23:17
  • Even scheduling. Store in UTC, input and output in local time, MUST use UTC to avoid scheduling 2 events at the same time on the day time changes, for example. Please refrain. By inpurt and output, I mean UI I/O – Michaël Roy Nov 03 '17 at 23:19
  • 3
    @HansPassant - Sorry to take offence, but I actually work with the folks on the Windows servicing team that support the maintenance of Windows time zones and though they are not ideal and we all agree that IANA time zones are the way to go, they have come a *long* way. Checkout [their blog](https://blogs.technet.microsoft.com/dst2007/), and you'll see that Microsoft has *not* given up on keeping the data updated. We just do not have the same historical range that IANA data does. You can also see [the MS tz policies here](https://support.microsoft.com/en-us/help/22803/daylight-saving-time). – Matt Johnson-Pint Nov 03 '17 at 23:22
  • 6
    @MichaëlRoy - Sorry, but no. If you have an event at 10:00 AM Pacific time every day, you cannot store that in UTC. Otherwise you'll be an hour off after a DST change. Lots more on that [here](https://stackoverflow.com/questions/19626177/how-to-store-repeating-dates-keeping-in-mind-daylight-savings-time/19627330#19627330), and [here](http://www.creativedeletion.com/2015/03/19/persisting_future_datetimes.html). You also cannot convert whole dates to UTC reliably, such as your birthday, anniversary, hire date, etc. – Matt Johnson-Pint Nov 03 '17 at 23:24
  • @HansPassant - As a Microsoft employee, I regularly participate and contribute to both the pubic IANA tz lists, and the internal Windows time zone data. Microsoft's stated mission is to "Empower every person and every organization on the planet to achieve more." From my perspective, that means everyone gets an accurate time zone. Including those in politically controversial places like Cuba, Venezuela, North Korea, Iran, Palestine, or even just in tiny places like Lord Howe Island in Australia. – Matt Johnson-Pint Nov 03 '17 at 23:28
  • Ok. since 10:00 local time is a realtive, and not absolute time. But that is not the use case of the original post, which does involve multiple time zones. @Jean-Milost; Store time in UTC + TZ information from global variable _timezone, so you can get back the original timezone as needed. – Michaël Roy Nov 03 '17 at 23:33
  • 3
    Your approach will be as reliable as is possible, assuming the system is properly maintained (updated with latest available DST information, synchronised with a correctly functioning time server, etc). Even if done (by IANA, Microsoft, etc) as well as possible that isn't 100% bullet-proof. Users can manually set time and timezone information, and get it incorrect. Daylight savings times (and even timezones, in some cases) are actually set for political reasons, and can therefore change arbitrarily - no matter how well various systems are maintained. – Peter Nov 03 '17 at 23:42
  • @Matt - After thinking about it, your 10:00 AM every sunday argument does not hold up. on days the local time goes backwards an hour or so, the local time for that one hour is repeated, and any event stored in local time may repeat. And on days when time goes forward, there is one hour missing, Should the event be skipped, in that case? Lives could be at stake! ALWAYS store time in UTC and ALWAYS use UTC times to set timers. – Michaël Roy Nov 04 '17 at 00:34
  • 1
    @MichaëlRoy - I'm happy to discuss of course, but those points are indeed addressed in the links I gave, and I feel we're usurping the original question. – Matt Johnson-Pint Nov 04 '17 at 00:44
  • To use your own words, I'll refrain. – Michaël Roy Nov 04 '17 at 00:50

2 Answers2

74

As a Microsoft employee with significant involvement with Windows time zone data, please allow me to assure you that Microsoft works very hard to ensure that it releases updates to keep Windows time zone data as accurate as it possibly can be.

There are several challenges, including the timing of time zone changes as given by governments. For example, we recently posted a notice about upcoming Windows time zone changes for Fiji, Cyprus, Sudan, Tonga, Namibia, and Turks & Caicos. In some cases, we can meet the effective-dates established by these different governments. In some cases we cannot because they don't offer enough lead time.

Consider the recent case of Sudan, who told the the IANA tz mailing list on October 17th, 2017 of a change effective November 1st 2017. IANA has processed this change, and so has Microsoft. But due to the short notice, and the time it takes to process such a change in the Windows operating system, it will be a little while before there is a new "Sudan Standard Time" time zone created in the Windows time zone data. Thus, we issue interim guidance to use a different time zone for the time being, then switch back once we have data that properly reflects the full history of time in the affected region.

With regard to the Windows time zone you mentioned, "E. South America Standard Time", the time zone data is correct. If you expand the registry entry, you'll see that there is a sub-key called "Dynamic DST" which contains the year-by-year changes to the data. For some time zones, this isn't necessary at all, and for other time zones you'll find a very small amount of data because the same rule repeats year after year. But in the case of Brazil, you'll notice Dynamic DST entries for 2009 through 2040.

Windows TZ Registry Data

(click the image to see the full resolution, and note the areas I manually marked in red that change year-over-year)

The Dynamic DST entries support the Win32 DYNAMIC_TIME_ZONE_INFORMATION structure, and corresponding APIs with "dynamic" in their name, such as GetDynamicTimeZoneInformation. (They also support the System.TimeZoneInfo class in the .NET Framework.) Most of these APIs have been in places since Windows Vista / Server 2008, with some others coming in Windows 7 / Server 2012.

Note that the TZI entry that is in the parent key is copied in from the current year's dynamic rule by internal Windows processes. This supports the APIs that work with Win32 TIME_ZONE_INFORMATION structures, which have been in place since Windows 2000.

To answer the specific questions you asked:

Have I understood the recurrence rule correctly?

The specific rule you cited is for 2017 only, and it says that DST ends on the 2nd month (February), on the 3rd Saturday, at 23:59:59.999 local time, and starts again on the 10th month (October), on the 2nd Saturday, at 23:59:59.999 local time. Keep in mind that Brazil is in the southern hemisphere, so DST starts late in the year and ends early in the next year.

Also, you may wonder why it's 23:59:59.999 on Saturday instead of 00:00:00.000 on Sunday. This is an artifact of history. There have in the past been certain programs and processes that incorrectly used <= instead of < to evaluate the transition, and thus would accidently move the clock one millisecond into the next day, back out of it, then back into it again. The events generated by the day changing erroneously could then lead to further problems. Microsoft has done their best to fix those bugs, but still opts to be 1ms off instead of risk the problem popping up in some new place one day. (This only applies for transitions that occur exactly at midnight.)

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

There are no known issues for that time zone, however there is a known issue that Windows time zones (even with the dynamic DST data) can only support a maximum of two time zone transitions in a single year. So, in places like Morocco that transition four times per year there are some internal workarounds in place that keep the current time zone data in sync such that "now" is an accurate representation of local time, but cannot represent all points of the year correctly at any given time.

We also don't currently have a time zone that maps cleanly for Troll Station, Antarctica. The reason is that from 2005 to 2015, this research station (population under 50) transitioned through three different offsets (UTC+0, UTC+1, and UTC+2) every year.

If your application is critically dependent on either of the above scenarios, then I recommend using an API with IANA data sources instead of the Win32 APIs.

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?

Yes, as mentioned above, it's due to the 1ms intentional error. DST in 2017, in the parts of Brazil that have DST, starts on Sunday October 15th at 00:00:00.000. That's the third Sunday of the month. 1ms prior is 23:59:59.999 on Saturday October 14th, which is the second Saturday of the month. This can be different every year, which is why there is Dynamic DST data.

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?

If you are using the Win32 APIs, they use the registry data themselves, so there is no need to work with the registry data directly. You should prefer the "Dynamic" versions of the APIs, as they properly account for the year-over-year changes in the Dynamic DST data. Sometimes these are labeled as "Ex". For example, the function you asked about is best handled by the TzSpecificLocalTimeToSystemTimeEx function.

...

That all said, if you are able to avoid using Windows time zone data in your application, I recommend doing so. Prefer IANA data sources, or those derived from them. There are many routes to working with IANA time zone data. Newer Windows APIs like Windows.Globalization.Calendar and Windows.Globalization.DatetimeFormatting.DateTimeFormatter in WinRT/UWP do indeed use IANA time zones, and that is clearly the path forward. In the standard C++ space, I highly recommend using Howard Hinnant's date/tz libraries, or those provided by the ICU project. There are several other viable choices as well.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • 1
    Many thanks for this excellent answer, that explain some points that I could not figure out, like e.g. why these specific changing time began on the previous day, 1ms before the real date and time mentioned on the timezone standards. Now I know what I have to do to resolve my problem, thank you one more time – Jean-Milost Reymond Nov 04 '17 at 13:48
  • 1
    The ICU C API + CLDR data is now included in Windows, so if you're OK taking a dependency on the latest OS release you can use those APIs without having to redist the (rather large) package yourself. – Peter Torr - MSFT Mar 26 '18 at 03:24
  • Please, can you clarify for me ? The time zones in registry will be updated (if needed) only If new Windows Update pack has been downloaded and installed on PC. Am I correct ? – RomanG Nov 22 '22 at 23:46
1

Great to see the level of detail in Matt’s post.

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

Nothing much more to add save that in addition to Matt’s incredibly detailed and thorough contributions to the Windows time zone data, there’s considerable vetting with different agencies, NGOs and government bodies that’s been outlined elsewhere. As an example, there are additional challenges in places like Morocco which not only transitions four times a year, but the information is subject to the government setting the official observance of DST in the region, and sometimes with little lead time, leading to additional publishing and deployment challenges. (Not to mention when a government revises a decision multiple times.)

So, for some applications with critical dependencies, an API to IANA source may be preferred, or calling the time zone data in Windows.Globalization.

All this is timely, if you’ll pardon the pun, just before we Fall Back in the northern hemisphere as well.

M3 Sweatt
  • 11
  • 3
  • 1
    It's *before* the time change in North America, like you said, but it's *after* the one in Europe. I imagine that this week, and the couple weeks in the spring with same situation, are some people's least favorite of the year. – Daniel H Nov 04 '17 at 02:38