STL icon indicating copy to clipboard operation
STL copied to clipboard

`<chrono>` `<format>`: `duration` formatting ignores precision

Open StephanTLavavej opened this issue 1 year ago • 3 comments

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::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.

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 with 0. 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?

StephanTLavavej avatar Nov 15 '23 18:11 StephanTLavavej

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.

mordante avatar Nov 15 '23 19:11 mordante

As a data point, {fmt} does apply the precision (https://godbolt.org/z/3vdYzeGEG):

  double: 3.14
duration: 3.142

CaseyCarter avatar Nov 15 '23 20:11 CaseyCarter

The issue seems previously discovered in #1901.

frederick-vs-ja avatar Nov 16 '23 01:11 frederick-vs-ja