STL
STL copied to clipboard
`<chrono>` `<format>`: `duration` formatting ignores precision
When formatting a duration
, we parse but appear to totally ignore precision:
C:\Temp>type meow.cpp
#include <chrono>
#include <format>
#include <iostream>
#include <string>
using namespace std;
int main() {
cout << format(" double: {:.3}", 3.14159) << "\n";
cout << format("duration: {:.3%Q}", 3.14159s) << "\n";
}
C:\Temp>cl /EHsc /nologo /W4 /std:c++latest /MTd /Od meow.cpp && meow
meow.cpp
double: 3.14
duration: 3.14159
Curiously, libstdc++ and libc++ exhibit the same behavior: https://godbolt.org/z/15cYchz9q
Precision is allowed for floating-point duration
s by WG21-N4964 [time.format]/1:
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-namerep
denotes a floating-point type. For all other types, an exception of typeformat_error
is thrown if the chrono-format-spec contains a precision specification.
Then [tab:time.format.spec] says:
Specifier Replacement ... ... %Q
The duration’s numeric value (as if extracted via .count()
).... ... %S
Seconds as a decimal number. If the number of seconds is less than 10
, the result is prefixed with0
. If the precision of the input cannot be exactly represented with seconds, then the format is a decimal floating-point number with a fixed format and a precision matching that of the precision of the input (or to a microseconds precision if the conversion to floating-point decimal seconds cannot be made within 18 fractional digits). The character for the decimal point is localized according to the locale. The modified command%OS
produces the locale’s alternative representation.
I don't know what an explicitly specified precision is supposed to do for %S
but ignoring it for %Q
seems wrong. Why is it allowed in the chrono-format-spec if it's never used?
Am I right, or are three independent implementations right?
While implementing chrono formatting in libc++ I found no wording specifying the effect of precision option; so libc++ accepts it and ignores it. I agree it feels wrong. Investigating why it's specified like this is still on my todo list.
As a data point, {fmt}
does apply the precision (https://godbolt.org/z/3vdYzeGEG):
double: 3.14
duration: 3.142
The issue seems previously discovered in #1901.