diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h --- a/libcxx/include/__chrono/formatter.h +++ b/libcxx/include/__chrono/formatter.h @@ -100,12 +100,12 @@ // https://godbolt.org/z/6dsbnW8ba std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}.0f}"), - __fraction.count(), + chrono::duration_cast::precision>(__fraction).count(), chrono::hh_mm_ss<__duration>::fractional_width); else std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}}"), - __fraction.count(), + chrono::duration_cast::precision>(__fraction).count(), chrono::hh_mm_ss<__duration>::fractional_width); } diff --git a/libcxx/test/std/time/time.syn/formatter.duration.pass.cpp b/libcxx/test/std/time/time.syn/formatter.duration.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.duration.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.duration.pass.cpp @@ -1091,12 +1091,56 @@ test_valid_fractional_values(); } +template +static void test_pr62082() { + // Examples in https://llvm.org/PR62082 + check(SV("39.223300"), SV("{:%S}"), std::chrono::duration>{40}); + check(SV("01.4755859375"), SV("{:%S}"), std::chrono::duration>{1511}); + + // Test with all possible number of decimals [0, 18]. When it does not + // fit in 18 decimals it uses 6. + check(SV("05"), SV("{:%S}"), std::chrono::duration>{5}); // 0 + + check(SV("05.0"), SV("{:%S}"), std::chrono::duration>{10}); // 1 + check(SV("05.5"), SV("{:%S}"), std::chrono::duration>{11}); // 1 + + check(SV("01.00"), SV("{:%S}"), std::chrono::duration>{4}); // 2 + check(SV("01.50"), SV("{:%S}"), std::chrono::duration>{6}); // 2 + check(SV("01.75"), SV("{:%S}"), std::chrono::duration>{7}); // 2 + + check(SV("01.000"), SV("{:%S}"), std::chrono::duration>{8}); // 3 + check(SV("01.0000"), SV("{:%S}"), std::chrono::duration>{16}); // 4 + check(SV("01.00000"), SV("{:%S}"), std::chrono::duration>{32}); // 5 + check(SV("01.000000"), SV("{:%S}"), std::chrono::duration>{64}); // 6 + check(SV("01.0000000"), SV("{:%S}"), std::chrono::duration>{128}); // 7 + check(SV("01.00000000"), SV("{:%S}"), std::chrono::duration>{256}); // 8 + check(SV("01.000000000"), SV("{:%S}"), std::chrono::duration>{512}); // 9 + check(SV("01.0000000000"), SV("{:%S}"), std::chrono::duration>{1024}); // 10 + check(SV("01.00000000000"), SV("{:%S}"), std::chrono::duration>{2048}); // 11 + check(SV("01.000000000000"), SV("{:%S}"), std::chrono::duration>{4096}); // 12 + check(SV("01.0000000000000"), SV("{:%S}"), std::chrono::duration>{8192}); // 13 + check(SV("01.00000000000000"), SV("{:%S}"), std::chrono::duration>{16384}); // 14 + check(SV("01.000000000000000"), SV("{:%S}"), std::chrono::duration>{32768}); // 15 + check(SV("01.0000000000000000"), SV("{:%S}"), std::chrono::duration>{65536}); // 16 + check(SV("01.00000000000000000"), SV("{:%S}"), std::chrono::duration>{131072}); // 17 + check(SV("01.000000000000000000"), SV("{:%S}"), std::chrono::duration>{262144}); // 18 + check(SV("01.000000"), SV("{:%S}"), std::chrono::duration>{524288}); // 19 -> 6 + + // Infinite number of decimals will use 6 decimals. + check(SV("00.111111"), SV("{:%S}"), std::chrono::duration>{1}); + check(SV("00.111111"), SV("{:%S}"), std::chrono::duration>{1}); + check(SV("00.111111"), SV("{:%S}"), std::chrono::duration>{1}); + check(SV("00.111111"), SV("{:%S}"), std::chrono::duration>{1}); +} + template static void test() { using namespace std::literals::chrono_literals; test_no_chrono_specs(); test_valid_values(); + test_pr62082(); + check_invalid_types( {SV("H"), SV("I"), SV("j"), SV("M"), SV("n"), SV("O"), SV("p"), SV("q"), SV("Q"), SV("r"), SV("R"), SV("S"), SV("t"), SV("T"), SV("X"), SV("EX"), SV("OH"), SV("OI"), SV("OM"), SV("OS")},