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.

4627. Encoding of duration unit suffixes is incorrect for wide streams

Section: 30.5.11 [time.duration.io] Status: New Submitter: Victor Zverovich Opened: 2026-09-27 Last modified: 2026-09-27

Priority: Not Prioritized

View all other issues in [time.duration.io].

View all issues with New status.

Discussion:

30.5.11 [time.duration.io] specifies operator<< for duration as if by:

basic_ostringstream<charT, traits> s;
s.flags(os.flags());
s.imbue(os.getloc());
s.precision(os.precision());
s << d.count() << units-suffix;
return os << s.str();

For Period::type equal to micro, units-suffix is implementation-defined to be either "μs" ("\u00b5\u0073") or "us".

The type and encoding of units-suffix are not specified in terms of charT. In particular, if "μs" denotes an ordinary string literal, then for a wide stream the expression above inserts a const char* into a basic_ostream<wchar_t>. 31.7.6.3.4 [ostream.inserters.character] specifies this operation by applying out.widen() to each individual char.

This does not perform transcoding. For example, when the ordinary literal encoding is UTF-8, the micro sign is represented by multiple char code units. Widening those code units individually does not produce the corresponding micro sign in the wide literal encoding.

For example:

std::wostringstream os;
os << std::chrono::microseconds{1};

should be able to produce:

1μs

when the implementation chooses the μs representation, but the current specification does not provide semantics that produce that result.

The same problem affects %q in 30.12 [time.format], whose replacement is specified as "the duration's unit suffix as specified in 30.5.11 [time.duration.io]".

This is similar to LWG 4522(i), which clarified that formatting to wchar_t requires transcoding rather than widening narrow code units.

The unit suffix should therefore be specified directly as a sequence of charT, using the literal encoding associated with charT.

Proposed resolution:

This wording is relative to N5054.

  1. Modify 30.5.11 [time.duration.io] as indicated:

    template<class charT, class traits, class Rep, class Period>
      basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const duration<Rep, Period>& d);
    

    -1- Effects: Inserts the duration d onto the stream os as if it were implemented as follows:

    basic_ostringstream<charT, traits> s;
    s.flags(os.flags());
    s.imbue(os.getloc());
    s.precision(os.precision());
    s << d.count() << units-suffix;
    return os << s.str();
    

    where units-suffix depends onis a character sequence of charT determined by the type Period::type as follows. In the following list, each quoted character sequence denotes the corresponding STATICALLY-WIDEN<charT> character sequence: […]

    [Drafting note:

    (1) The existing list is unchanged, including:

    Otherwise, if Period::type is micro, it is implementation-defined whether units-suffix is "μs" ("\u00b5\u0073") or "us".

    (2) Since %q in 30.12 [time.format] refers to the duration's unit suffix as specified in 30.5.11 [time.duration.io], this change also specifies the appropriate charT representation for %q. ]