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.

4541. Unclear behavior for parsing locale-dependent format

Section: 28.3.4.6.2.3 [locale.time.get.virtuals], 30.13 [time.parse] Status: New Submitter: S. B. Tam Opened: 2026-03-14 Last modified: 2026-03-15

Priority: Not Prioritized

View other active issues in [locale.time.get.virtuals].

View all other issues in [locale.time.get.virtuals].

View all issues with New status.

Discussion:

Both time_get::do_get and chrono::from_stream can take format specifiers that depend on locale-specific information.

For example, the %c specifier corresponds to "the locale's date and time representation." It is unclear how the locale's date and time format is determined for the purpose of parsing, and this format may vary among implementations. The format may also depend on the operating system, the C runtime, and the user's preference.

In practice, locale-specific information is rarely used for parsing. If people want to get a time point from a string, they would require the string to be in a specific locale-independent format (e.g. %F %T).

Nonetheless, since locale-dependent specifiers are permitted, I believe the standard should clarify what they mean.

The proposed wording makes them implementation-defined, which matches time_put::do_put (28.3.4.6.4.3 [locale.time.put.virtuals] p1) and also matches the proposed resolution of LWG 4285(i).

Proposed resolution:

This wording is relative to N5032.

  1. Modify 28.3.4.6.2.3 [locale.time.get.virtuals] as indicated:

    iter_type do_get(iter_type s, iter_type end, ios_base& f,
                     ios_base::iostate& err, tm* t, char format, char modifier) const;
    

    -11- Preconditions: t points to an object.

    -12- Effects: The function starts by evaluating err = ios_base::goodbit. It then reads characters starting at s until it encounters an error, or until it has extracted and assigned those tm members, and any remaining format characters, corresponding to a conversion specification appropriate for the POSIX function strptime, formed by concatenating '%', the modifier character, when non-NUL, and the format character, except that the sequence of characters extracted for those specifiers that are described as depending on the C locale are instead implementation-defined. When the concatenation fails to yield a complete valid directive the function leaves the object pointed to by t unchanged and evaluates err |= ios_base::failbit. When s == end evaluates to true after reading a character the function evaluates err |= ios_base::eofbit.

    -13- For complex conversion specifications such as %c, %x, or %X, or conversion specifications that involve the optional modifiers E or O, when the function is unable to unambiguously determine some or all tm members from the input sequence [s, end), it evaluates err |= ios_base::eofbit. In such cases the values of those tm members are unspecified and may be outside their valid range.

    -14- Returns: An iterator pointing immediately beyond the last character recognized as possibly part of a valid input sequence for the given format and modifier.

    -15- Remarks: It is unspecified whether multiple calls to do_get() with the address of the same tm object will update the current contents of the object or simply overwrite its members. Portable programs should zero out the object before invoking the function.

  2. Modify 30.13 [time.parse] as indicated:

    -1- Each parse overload specified in this subclause calls from_stream unqualified, so as to enable argument-dependent lookup (6.5.4 [basic.lookup.argdep]). In the following paragraphs, let is denote an object of type basic_istream<charT, traits> and let I be basic_istream<charT, traits>&, where charT and traits are template parameters in that context.

    -2- Recommended practice: Implementations should make it difficult to accidentally store or use a manipulator that may contain a dangling reference to a format string, for example by making the manipulators produced by parse immovable and preventing stream extraction into an lvalue of such a manipulator type.

    […]

    -17- If the from_stream overload fails to parse everything specified by the format string, or if insufficient information is parsed to specify a complete duration, time point, or calendrical data structure, setstate(ios_base::failbit) is called on the basic_istream.

    -?- The sequence of characters extracted for those specifiers that are described as depending on a locale are implementation-defined.

    Table 134 — Meaning of parse flags [tab:time.parse.spec]

    […]