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.

4560. Explicitly specify effects of precision specification in duration formatter

Section: 30.12 [time.format] Status: New Submitter: Liang Jiaming Opened: 2026-03-27 Last modified: 2026-04-04

Priority: Not Prioritized

View other active issues in [time.format].

View all other issues in [time.format].

View all issues with New status.

Discussion:

Currently, the formatter for chrono types handles fill-align-width-precision besides chrono specifications. On the one hand, the standard regulates in the second paragraph of 30.12 [time.format] p1 that:

The productions fill-and-align, width, and precision are described in 28.5.2 [format.string].

and in 30.12 [time.format] p7:

Unless otherwise specified, if the chrono-specs is omitted, the chrono object is formatted as if by streaming it to basic_ostringstream<charT> os with the formatting locale imbued and copying os.str() through the output iterator of the context with additional padding and adjustments as specified by the format specifiers.

[Example 3:

string s = format("{:=>8}", 42ms);      // value of s is "====42ms"

end example]

which imply that the precision specification takes effects on the final formatted string. On the other hand, the next two statements in 30.12 [time.format] p1 say that:

Giving a precision specification in the chrono-format-spec is valid only for types that are specializations of std::chrono::duration for which the nested typedef-name rep denotes a floating-point type. For all other types, an exception of type format_error is thrown if the chrono-format-spec contains a precision specification.

which imply that the precision specification takes effects on the underlying floating-point representation.

These two contradictory intentions make unnecessary confusion and divergence in different implementations. Given code example below:

std::chrono::duration<float> s = 10ms + 10us + 123ns;
std::print("from chrono {:.3} | from count {:.3%Q}\n", s);

It gives four different outputs in libstdc++, libc++, MS-STL and FMT (i.e. fmtlib/fmt; though it doesn't need to be standard-compliant, we list it here for comparison):

Implementation {0:.3} {0:.3%Q}
libc++ "0.0" "0.010010123"
libstdc++ "0.0100101s" "0.010010123"
MS-STL "0.0100101s" "0.0100101"
FMT "0.010s" "0.010"

To be specific, the current implementations are as follows:

  1. No chrono-spec, with precision:

  2. %Q spec, with precision:

To bridge the gap among implementations, the standard should explicitly specify the effects of precision. Since the current wording says that precision is only allowed for duration with floating-point representation, an intuitive solution is just applying precision on that representation. Otherwise (i.e. the precision is applied on the streamed string), other chrono types like time_point should be capable of handling that too, making current constraint seemingly unnecessary.

Proposed resolution:

This wording is relative to N5032.

  1. Modify 30.12 [time.format] as indicated:

    -1- Each formatter (28.5.6 [format.formatter]) specialization in the chrono library (30.2 [time.syn]) meets the Formatter requirements (28.5.6.1 [formatter.requirements]). The parse member functions of these formatters interpret the format specification as a chrono-format-spec according to the following syntax:

    […]

    The productions fill-and-align, width, and precision are described in 28.5.2 [format.string]. Giving a precision specification in the chrono-format-spec is valid only for types that are specializations of std::chrono::duration for which the nested typedef-name rep denotes a floating-point type, and the precision specification doesn't take effects unless explicitly specified. For all other types, an exception of type format_error is thrown if the chrono-format-spec contains a precision specification. All ordinary multibyte characters represented by literal-char are copied unchanged to the output.

    […]

    -7- Unless otherwise specified, if the chrono-specs is omitted, the chrono object is formatted as if by streaming it to basic_ostringstream<charT> os with the formatting locale imbued and copying os.str() through the output iterator of the context with additional padding and adjustments as specified by the format specifiers.

  2. Modify Table 133 — "Meaning of conversion specifiers" [tab:time.format.spec] as indicated:

    Table 133 — Meaning of conversion specifiers [tab:time.format.spec]
    Specifier Replacement
    […]
    %Q The duration's numeric value (as if extracted via .count()).
    The precision specification is applied on that numeric value.
    […]