This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4211. IANA time zone database allows links to refer to links

Section: 30.11.2.1 [time.zone.db.tzdb] Status: New Submitter: Jonathan Wakely Opened: 2025-02-22 Last modified: 2025-02-22

Priority: Not Prioritized

View all issues with New status.

Discussion:

Since October 2022 the IANA Time Zone Database's tzfile data format allows a Link to refer to another Link, instead of referring directly to a Zone. The zic(8) man page says:

The TARGET field should appear as the NAME field in some zone line or as the LINK-NAME field in some link line. The LINK-NAME field is used as an alternative name for that zone; it has the same syntax as a zone line's NAME field. Links can chain together, although the behavior is unspecified if a chain of one or more links does not terminate in a Zone name.
Because chains of links were introduced to tzfile after chrono::tzdb was standardized, C++ does not properly support chains of links.

The time_zone_link::target() member function is required to return "The name of the time_zone for which this time_zone_link provides an alternative name." This doesn't allow returning the name of another time_zone_link, which implies that the implementation should flatten a series of links so that the target is a time_zone. However, this discards information which is present in the tzdb, so that the information exposed to a C++ program does not preserve the original structure of a chain of links.

The standard could be adjusted to support chains of links by allowing time_zone_link::target() to refer to another link, and then altering the algorithm used by tzdb::locate_zone(string_view) to find a time_zone from a name that might be a zone or a link.

Proposed resolution:

This wording is relative to N5001.

  1. Modify 30.11.2.1 [time.zone.db.tzdb] as indicated:
    
    const time_zone* locate_zone(string_view tz_name) const;
    

    -2- Returns:

    1. (2.1) — If zones contains an element tz for which tz.name() == tz_name, a pointer to tz;
    2. (2.2) — otherwise, if links contains an element tz_l for which tz_l.name() == tz_name, then a pointer to the element tz of zones for which tz.name() == tz_l.target() the result of locate_zone(tz_l.target()). .

    [Note 1: A time_zone_link specifies an alternative name for a time_zone. — end note]

    -3- Throws: If a const time_zone* cannot be found as described in the Returns: element, throws a runtime_error.

    [Note 2: On non-exceptional return, the return value is always a pointer to a valid time_zone. — end note]

    -?- Remarks: If both zones and links contain elements that match tz_name then it is unspecified whether &tz or locate_zone(tz_l.target()) is returned.

    [Drafting note: This gives flexibility how to implement the lookup in locate_zone. ]

  2. Modify 30.11.9.1 [time.zone.link.overview] as indicated:

    -1- A time_zone_link specifies an alternative name for a time_zone. time_zone_links are constructed when the time zone database is initialized. The name of a time_zone_link can be used as an argument to tzdb::locate_zone (30.11.2.1 [time.zone.db.tzdb]). A time_zone_link can refer directly to a time_zone, or to another time_zone_link, forming a chain of links.

  3. Modify 30.11.9.2 [time.zone.link.members] as indicated:
    
    string_view name() const noexcept;
    
    -1- Returns: The alternative name for the time zone.
    
    string_view target() const noexcept;
    

    -2- Returns: The name of the time_zone for which this time_zone_link provides an alternative name or the name of another time_zone_link.

    [Note 1: tzdb::locate_zone follows a chain of links formed when a link's target is the name of a time_zone_link, throwing an exception if the chain of links does not terminate in a time_zone. — end note]