microsoft / microsoft/STL

`<chrono>`: Improve exception messages when OS support is unavailable for time zones

Open
#4,331 2 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

chrono enhancement
Dominant language
C++
Stars
11.1k
Forks
1.7k
Avg merge
4d 15h
Merged PRs (30d)
22

Description

Overview

The STL's VS 2019 16.10 Changelog explained:

While the STL generally provides all features on all supported versions of Windows, leap seconds and time zones (which change over time) require OS support that was added to Windows 10. Specifically, updating the leap second database requires Windows 10 version 1809 or later, and time zones require icu.dll which is provided by Windows 10 version 1903/19H1 or later. This applies to both client and server OSes; note that Windows Server 2019 is based on Windows 10 version 1809.

When OS support is unavailable, we throw exceptions, as permitted by the Standard. However, if a programmer isn't already aware of the OS version dependency here, deducing "the end user's OS is too old" from the exception message can be an excessively mysterious process.

#1911 asks whether a fallback mechanism can be implemented for old OSes. There are no current plans to do so, and I believe that this will remain infeasible. However, it should be fairly simple to enhance the exception messages here.

Leap seconds require Windows 10 version 1809 or later

I believe that this happens in __std_tzdb_get_leap_seconds:

https://github.com/microsoft/STL/blob/442029c6fa37f1b6f9203357de09672d5704077c/stl/src/tzdb.cpp#L597-L601

For old OSes, I don't believe that we throw an exception:

https://github.com/microsoft/STL/blob/442029c6fa37f1b6f9203357de09672d5704077c/stl/inc/chrono#L2167-L2175

It looks like we silently say "there's no post-2018 leap second data" for old OSes. If I'm right, then there's no exception message that needs to be enhanced here. (Leap seconds are also much less "popular" than time zones.)

Time zones require Windows 10 version 1903/19H1 or later

_Init_icu_functions is the single place where we load icu.dll:

https://github.com/microsoft/STL/blob/442029c6fa37f1b6f9203357de09672d5704077c/stl/src/tzdb.cpp#L66

The only caller is the wrapper _Acquire_icu_functions:

https://github.com/microsoft/STL/blob/442029c6fa37f1b6f9203357de09672d5704077c/stl/src/tzdb.cpp#L101-L108

Which in turn has 3 callsites: __std_tzdb_get_time_zones, __std_tzdb_get_current_zone, __std_tzdb_get_sys_info:

https://github.com/microsoft/STL/blob/442029c6fa37f1b6f9203357de09672d5704077c/stl/src/tzdb.cpp#L357-L358
https://github.com/microsoft/STL/blob/442029c6fa37f1b6f9203357de09672d5704077c/stl/src/tzdb.cpp#L460-L461
https://github.com/microsoft/STL/blob/442029c6fa37f1b6f9203357de09672d5704077c/stl/src/tzdb.cpp#L501-L502

They all report __std_tzdb_error::_Win_error (because we haven't even loaded ICU yet; _Icu_error is for when we've loaded ICU but it fails later). They're all called via _Make_unique_tzdb_info:

https://github.com/microsoft/STL/blob/442029c6fa37f1b6f9203357de09672d5704077c/stl/inc/chrono#L1837-L1838
https://github.com/microsoft/STL/blob/442029c6fa37f1b6f9203357de09672d5704077c/stl/inc/chrono#L2069
https://github.com/microsoft/STL/blob/442029c6fa37f1b6f9203357de09672d5704077c/stl/inc/chrono#L2110

Which has conveniently extracted the common pattern here (thanks to #4119):

https://github.com/microsoft/STL/blob/442029c6fa37f1b6f9203357de09672d5704077c/stl/inc/chrono#L1743-L1757

Therefore, I believe that the _XGetLastError() is the single location that we need to modify. Unfortunately, _XGetLastError() was not designed to be extensible - it combines calling GetLastError() and throwing a system_error with it:

https://github.com/microsoft/STL/blob/442029c6fa37f1b6f9203357de09672d5704077c/stl/src/xonce.cpp#L21-L25

To throw a better exception here, without try-catch-rethrow, we'd need to inject a new function into the import lib. (I think we should continue to capture GetLastError(), but provide an additional message mentioning that the OS version may be relevant.)

Suggested message

Windows versioning is complicated (but not nearly as much as MSVC versioning 😹) so for clarity I suggest a message like:

"C++20 chrono time zone support requires Windows 10 version 1903/19H1, Windows 11, Windows Server 2022, or later."

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in stl/src/tzdb.cpp at _Init_icu_functions and _Acquire_icu_functions, then inspect stl/inc/chrono around _Make_unique_tzdb_info and the _XGetLastError path in stl/src/xonce.cpp. Confirm how the existing Windows error is captured and identify the supported OS-version wording needed for time-zone failures. Done means the relevant exception preserves the system error while explaining the OS requirement.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.