`<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 durations 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::durationfor which the nested typedef-namerepdenotes a floating-point type. For all other types, an exception of typeformat_erroris thrown if the chrono-format-spec contains a precision specification.
Then [tab:time.format.spec] says:
Specifier Replacement ... ... %QThe duration’s numeric value (as if extracted via .count()).... ... %SSeconds 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%OSproduces 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.