From 85a4cefd86b8596fbccf3fc31b5d394ea8ad4857 Mon Sep 17 00:00:00 2001 From: Stepan Ponomarev Date: Wed, 28 Sep 2022 13:48:09 +0300 Subject: [PATCH 1/7] Reuse precision modifier in seconds specification --- include/fmt/chrono.h | 85 ++++++++++++++++++++++++++++++++++++++------ test/chrono-test.cc | 14 +++++++- 2 files changed, 88 insertions(+), 11 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index ef6a29903d07..680d1cb7c7b6 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1056,6 +1056,43 @@ void write_fractional_seconds(OutputIt& out, Duration d) { } } +template +void write_fractional_seconds(OutputIt& out, Duration d, int precision) { + constexpr auto num_fractional_digits = + count_fractional_digits::value; + + using subsecond_precision = std::chrono::duration< + typename std::common_type::type, + std::ratio<1, detail::pow10(num_fractional_digits)>>; + if (precision > 0) { + *out++ = '.'; + auto fractional = + detail::abs(d) - std::chrono::duration_cast(d); + auto subseconds = + std::chrono::treat_as_floating_point< + typename subsecond_precision::rep>::value + ? fractional.count() + : std::chrono::duration_cast(fractional) + .count(); + uint32_or_64_or_128_t n = + to_unsigned(to_nonnegative_int(subseconds, max_value())); + int num_digits = detail::count_digits(n); + int zeroes = std::min(num_fractional_digits - num_digits, precision); + if (num_fractional_digits > num_digits) out = std::fill_n(out, zeroes, '0'); + int remaining = precision - (zeroes > 0 ? zeroes : 0); + if (remaining < num_digits) { + n /= to_unsigned(detail::pow10(to_unsigned(num_digits - remaining))); + out = format_decimal(out, n, remaining).end; + return; + } + out = format_decimal(out, n, num_digits).end; + remaining -= num_digits; + out = std::fill_n(out, remaining, '0'); + } +} + // Format subseconds which are given as a floating point type with an appropiate // number of digits. We cannot pass the Duration here, as we explicitly need to // pass the Rep value in the chrono_formatter. @@ -1081,6 +1118,25 @@ void write_floating_seconds(memory_buffer& buf, Duration duration) { num_fractional_digits); } +template +void write_floating_seconds(memory_buffer& buf, Duration duration, int precision) { + if (precision < 0) { + write_floating_seconds(buf, duration); + return; + } + + FMT_ASSERT(std::is_floating_point::value, ""); + auto val = duration.count(); + + format_to( + std::back_inserter(buf), runtime("{:.{}f}"), + std::fmod(val * + static_cast(Duration::period::num) / + static_cast(Duration::period::den), + static_cast(60)), + precision); +} + template class tm_writer { @@ -1518,6 +1574,9 @@ class tm_writer { }; struct chrono_format_checker : null_chrono_spec_handler { + bool is_floating_point = false; + bool has_precision = false; + FMT_NORETURN void unsupported() { FMT_THROW(format_error("no date")); } template @@ -1530,7 +1589,11 @@ struct chrono_format_checker : null_chrono_spec_handler { FMT_CONSTEXPR void on_24_hour_time() {} FMT_CONSTEXPR void on_iso_time() {} FMT_CONSTEXPR void on_am_pm() {} - FMT_CONSTEXPR void on_duration_value() {} + FMT_CONSTEXPR void on_duration_value() const { + if (has_precision && !is_floating_point) { + FMT_THROW(format_error("precision not allowed for this argument type")); + } + } FMT_CONSTEXPR void on_duration_unit() {} }; @@ -1831,14 +1894,17 @@ struct chrono_formatter { if (ns == numeric_system::standard) { if (std::is_floating_point::value) { auto buf = memory_buffer(); - write_floating_seconds(buf, std::chrono::duration(val)); + write_floating_seconds(buf, std::chrono::duration(val), precision); if (negative) *out++ = '-'; if (buf.size() < 2 || buf[1] == '.') *out++ = '0'; out = std::copy(buf.begin(), buf.end(), out); } else { write(second(), 2); - write_fractional_seconds( - out, std::chrono::duration(val)); + if (precision >= 0) { + write_fractional_seconds(out, std::chrono::duration(val), precision); + } else { + write_fractional_seconds(out, std::chrono::duration(val)); + } } return; } @@ -1999,18 +2065,17 @@ struct formatter, Char> { if (begin == end) return {begin, begin}; begin = detail::parse_width(begin, end, handler); if (begin == end) return {begin, begin}; + auto checker = detail::chrono_format_checker(); + checker.is_floating_point = std::is_floating_point::value; if (*begin == '.') { - if (std::is_floating_point::value) - begin = detail::parse_precision(begin, end, handler); - else - handler.on_error("precision not allowed for this argument type"); + checker.has_precision = true; + begin = detail::parse_precision(begin, end, handler); } if (begin != end && *begin == 'L') { ++begin; localized = true; } - end = detail::parse_chrono_format(begin, end, - detail::chrono_format_checker()); + end = detail::parse_chrono_format(begin, end, checker); return {begin, end}; } diff --git a/test/chrono-test.cc b/test/chrono-test.cc index d53ad56b8a4e..e75d77f5e821 100644 --- a/test/chrono-test.cc +++ b/test/chrono-test.cc @@ -466,7 +466,7 @@ TEST(chrono_test, format_default_fp) { TEST(chrono_test, format_precision) { EXPECT_THROW_MSG( - (void)fmt::format(runtime("{:.2}"), std::chrono::seconds(42)), + (void)fmt::format(runtime("{:.2%Q}"), std::chrono::seconds(42)), fmt::format_error, "precision not allowed for this argument type"); EXPECT_EQ("1ms", fmt::format("{:.0}", dms(1.234))); EXPECT_EQ("1.2ms", fmt::format("{:.1}", dms(1.234))); @@ -611,12 +611,23 @@ TEST(chrono_test, cpp20_duration_subsecond_support) { EXPECT_EQ(fmt::format("{:%S}", std::chrono::nanoseconds{-13420148734}), "-13.420148734"); EXPECT_EQ(fmt::format("{:%S}", std::chrono::milliseconds{1234}), "01.234"); + // Check subsecond presision modifier. + EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::nanoseconds{1234}), "00.000001"); + EXPECT_EQ(fmt::format("{:.18%S}", std::chrono::nanoseconds{1234}), "00.000001234000000000"); + EXPECT_EQ(fmt::format("{:.{}%S}", std::chrono::nanoseconds{1234}, 6), "00.000001"); + EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{1234}), "01.234000"); + EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{-1234}), "-01.234000"); + EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::seconds{1234}), "34.000"); + EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::hours{1234}), "00.000"); + EXPECT_EQ(fmt::format("{:.5%S}", dms(1.234)), "00.00123"); + EXPECT_EQ(fmt::format("{:.8%S}", dms(1.234)), "00.00123400"); { // Check that {:%H:%M:%S} is equivalent to {:%T}. auto dur = std::chrono::milliseconds{3601234}; auto formatted_dur = fmt::format("{:%T}", dur); EXPECT_EQ(formatted_dur, "01:00:01.234"); EXPECT_EQ(fmt::format("{:%H:%M:%S}", dur), formatted_dur); + EXPECT_EQ(fmt::format("{:.6%H:%M:%S}", dur), "01:00:01.234000"); } using nanoseconds_dbl = std::chrono::duration; EXPECT_EQ(fmt::format("{:%S}", nanoseconds_dbl{-123456789}), "-00.123456789"); @@ -630,6 +641,7 @@ TEST(chrono_test, cpp20_duration_subsecond_support) { auto formatted_dur = fmt::format("{:%T}", dur); EXPECT_EQ(formatted_dur, "-00:01:39.123456789"); EXPECT_EQ(fmt::format("{:%H:%M:%S}", dur), formatted_dur); + EXPECT_EQ(fmt::format("{:.3%H:%M:%S}", dur), "-00:01:39.123"); } // Check that durations with precision greater than std::chrono::seconds have // fixed precision, and print zeros even if there is no fractional part. From 21a828cd1c461df08fa32a36b9f8470072778d42 Mon Sep 17 00:00:00 2001 From: Stepan Ponomarev Date: Thu, 20 Oct 2022 10:21:56 +0200 Subject: [PATCH 2/7] Apply clang-format --- include/fmt/chrono.h | 12 ++++++++---- test/chrono-test.cc | 15 ++++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 680d1cb7c7b6..451bc482d815 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1119,7 +1119,8 @@ void write_floating_seconds(memory_buffer& buf, Duration duration) { } template -void write_floating_seconds(memory_buffer& buf, Duration duration, int precision) { +void write_floating_seconds(memory_buffer& buf, Duration duration, + int precision) { if (precision < 0) { write_floating_seconds(buf, duration); return; @@ -1894,16 +1895,19 @@ struct chrono_formatter { if (ns == numeric_system::standard) { if (std::is_floating_point::value) { auto buf = memory_buffer(); - write_floating_seconds(buf, std::chrono::duration(val), precision); + write_floating_seconds(buf, std::chrono::duration(val), + precision); if (negative) *out++ = '-'; if (buf.size() < 2 || buf[1] == '.') *out++ = '0'; out = std::copy(buf.begin(), buf.end(), out); } else { write(second(), 2); if (precision >= 0) { - write_fractional_seconds(out, std::chrono::duration(val), precision); + write_fractional_seconds( + out, std::chrono::duration(val), precision); } else { - write_fractional_seconds(out, std::chrono::duration(val)); + write_fractional_seconds( + out, std::chrono::duration(val)); } } return; diff --git a/test/chrono-test.cc b/test/chrono-test.cc index e75d77f5e821..26591496744d 100644 --- a/test/chrono-test.cc +++ b/test/chrono-test.cc @@ -612,11 +612,16 @@ TEST(chrono_test, cpp20_duration_subsecond_support) { "-13.420148734"); EXPECT_EQ(fmt::format("{:%S}", std::chrono::milliseconds{1234}), "01.234"); // Check subsecond presision modifier. - EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::nanoseconds{1234}), "00.000001"); - EXPECT_EQ(fmt::format("{:.18%S}", std::chrono::nanoseconds{1234}), "00.000001234000000000"); - EXPECT_EQ(fmt::format("{:.{}%S}", std::chrono::nanoseconds{1234}, 6), "00.000001"); - EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{1234}), "01.234000"); - EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{-1234}), "-01.234000"); + EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::nanoseconds{1234}), + "00.000001"); + EXPECT_EQ(fmt::format("{:.18%S}", std::chrono::nanoseconds{1234}), + "00.000001234000000000"); + EXPECT_EQ(fmt::format("{:.{}%S}", std::chrono::nanoseconds{1234}, 6), + "00.000001"); + EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{1234}), + "01.234000"); + EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{-1234}), + "-01.234000"); EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::seconds{1234}), "34.000"); EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::hours{1234}), "00.000"); EXPECT_EQ(fmt::format("{:.5%S}", dms(1.234)), "00.00123"); From 6ecde30513ba0a00acc54feb5d229cb57e1a50f6 Mon Sep 17 00:00:00 2001 From: Stepan Ponomarev Date: Fri, 21 Oct 2022 11:48:32 +0200 Subject: [PATCH 3/7] Make write_fractional_seconds more readable --- include/fmt/chrono.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 451bc482d815..cff225c4908e 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1079,9 +1079,10 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision) { uint32_or_64_or_128_t n = to_unsigned(to_nonnegative_int(subseconds, max_value())); int num_digits = detail::count_digits(n); - int zeroes = std::min(num_fractional_digits - num_digits, precision); + int zeroes = + std::min(std::max(0, num_fractional_digits - num_digits), precision); if (num_fractional_digits > num_digits) out = std::fill_n(out, zeroes, '0'); - int remaining = precision - (zeroes > 0 ? zeroes : 0); + int remaining = precision - zeroes; if (remaining < num_digits) { n /= to_unsigned(detail::pow10(to_unsigned(num_digits - remaining))); out = format_decimal(out, n, remaining).end; From e74bc9974674da9bc5863e894966eea0724d5066 Mon Sep 17 00:00:00 2001 From: Stepan Ponomarev Date: Wed, 26 Oct 2022 12:29:55 +0200 Subject: [PATCH 4/7] Add alias for typename Duration::rep --- include/fmt/chrono.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index cff225c4908e..840e11f1cd82 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1099,7 +1099,8 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision) { // pass the Rep value in the chrono_formatter. template void write_floating_seconds(memory_buffer& buf, Duration duration) { - FMT_ASSERT(std::is_floating_point::value, ""); + using Rep = typename Duration::rep; + FMT_ASSERT(std::is_floating_point::value, ""); auto num_fractional_digits = count_fractional_digits::value; @@ -1107,35 +1108,36 @@ void write_floating_seconds(memory_buffer& buf, Duration duration) { // precision. auto val = duration.count(); if (num_fractional_digits < 6 && - static_cast(std::round(val)) != val) + static_cast(std::round(val)) != val) num_fractional_digits = 6; format_to( std::back_inserter(buf), runtime("{:.{}f}"), std::fmod(val * - static_cast(Duration::period::num) / - static_cast(Duration::period::den), - static_cast(60)), + static_cast(Duration::period::num) / + static_cast(Duration::period::den), + static_cast(60)), num_fractional_digits); } template void write_floating_seconds(memory_buffer& buf, Duration duration, int precision) { + using Rep = typename Duration::rep; if (precision < 0) { write_floating_seconds(buf, duration); return; } - FMT_ASSERT(std::is_floating_point::value, ""); + FMT_ASSERT(std::is_floating_point::value, ""); auto val = duration.count(); format_to( std::back_inserter(buf), runtime("{:.{}f}"), std::fmod(val * - static_cast(Duration::period::num) / - static_cast(Duration::period::den), - static_cast(60)), + static_cast(Duration::period::num) / + static_cast(Duration::period::den), + static_cast(60)), precision); } From 54fa95f01354d79f72c1e8839da4ed454a4607df Mon Sep 17 00:00:00 2001 From: Stepan Ponomarev Date: Wed, 2 Nov 2022 13:01:02 +0100 Subject: [PATCH 5/7] Fixes --- include/fmt/chrono.h | 136 ++++++++++++++----------------------------- 1 file changed, 45 insertions(+), 91 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 840e11f1cd82..571081b2db9b 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1026,8 +1026,7 @@ struct count_fractional_digits { // Format subseconds which are given as an integer type with an appropriate // number of digits. template -void write_fractional_seconds(OutputIt& out, Duration d) { - FMT_ASSERT(!std::is_floating_point::value, ""); +void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) { constexpr auto num_fractional_digits = count_fractional_digits::value; @@ -1036,59 +1035,37 @@ void write_fractional_seconds(OutputIt& out, Duration d) { typename std::common_type::type, std::ratio<1, detail::pow10(num_fractional_digits)>>; - if (std::ratio_less::value) { - *out++ = '.'; - auto fractional = - detail::abs(d) - std::chrono::duration_cast(d); - auto subseconds = - std::chrono::treat_as_floating_point< - typename subsecond_precision::rep>::value - ? fractional.count() - : std::chrono::duration_cast(fractional) - .count(); - uint32_or_64_or_128_t n = - to_unsigned(to_nonnegative_int(subseconds, max_value())); - int num_digits = detail::count_digits(n); - if (num_fractional_digits > num_digits) - out = std::fill_n(out, num_fractional_digits - num_digits, '0'); - out = format_decimal(out, n, num_digits).end; - } -} -template -void write_fractional_seconds(OutputIt& out, Duration d, int precision) { - constexpr auto num_fractional_digits = - count_fractional_digits::value; + const auto fractional = + detail::abs(d) - std::chrono::duration_cast(d); + uint32_or_64_or_128_t subseconds = + std::chrono::treat_as_floating_point< + typename subsecond_precision::rep>::value + ? fractional.count() + : std::chrono::duration_cast(fractional).count(); + const int num_digits = detail::count_digits(subseconds); - using subsecond_precision = std::chrono::duration< - typename std::common_type::type, - std::ratio<1, detail::pow10(num_fractional_digits)>>; - if (precision > 0) { + int leading_zeroes = std::max(0, num_fractional_digits - num_digits); + if (precision < 0) { + FMT_ASSERT(!std::is_floating_point::value, ""); + if (std::ratio_less::value) { + *out++ = '.'; + out = std::fill_n(out, leading_zeroes, '0'); + out = format_decimal(out, subseconds, num_digits).end; + } + } else { *out++ = '.'; - auto fractional = - detail::abs(d) - std::chrono::duration_cast(d); - auto subseconds = - std::chrono::treat_as_floating_point< - typename subsecond_precision::rep>::value - ? fractional.count() - : std::chrono::duration_cast(fractional) - .count(); - uint32_or_64_or_128_t n = - to_unsigned(to_nonnegative_int(subseconds, max_value())); - int num_digits = detail::count_digits(n); - int zeroes = - std::min(std::max(0, num_fractional_digits - num_digits), precision); - if (num_fractional_digits > num_digits) out = std::fill_n(out, zeroes, '0'); - int remaining = precision - zeroes; + leading_zeroes = std::min(leading_zeroes, precision); + out = std::fill_n(out, leading_zeroes, '0'); + int remaining = precision - leading_zeroes; if (remaining < num_digits) { - n /= to_unsigned(detail::pow10(to_unsigned(num_digits - remaining))); - out = format_decimal(out, n, remaining).end; + subseconds /= + to_unsigned(detail::pow10(to_unsigned(num_digits - remaining))); + out = format_decimal(out, subseconds, remaining).end; return; } - out = format_decimal(out, n, num_digits).end; + out = format_decimal(out, subseconds, num_digits).end; remaining -= num_digits; out = std::fill_n(out, remaining, '0'); } @@ -1097,48 +1074,27 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision) { // Format subseconds which are given as a floating point type with an appropiate // number of digits. We cannot pass the Duration here, as we explicitly need to // pass the Rep value in the chrono_formatter. -template -void write_floating_seconds(memory_buffer& buf, Duration duration) { - using Rep = typename Duration::rep; - FMT_ASSERT(std::is_floating_point::value, ""); - auto num_fractional_digits = - count_fractional_digits::value; - // For non-integer values, we ensure at least 6 digits to get microsecond - // precision. - auto val = duration.count(); - if (num_fractional_digits < 6 && - static_cast(std::round(val)) != val) - num_fractional_digits = 6; - - format_to( - std::back_inserter(buf), runtime("{:.{}f}"), - std::fmod(val * - static_cast(Duration::period::num) / - static_cast(Duration::period::den), - static_cast(60)), - num_fractional_digits); -} - template void write_floating_seconds(memory_buffer& buf, Duration duration, - int precision) { - using Rep = typename Duration::rep; - if (precision < 0) { - write_floating_seconds(buf, duration); - return; - } + int num_fractional_digits = -1) { + using rep = typename Duration::rep; + FMT_ASSERT(std::is_floating_point::value, ""); - FMT_ASSERT(std::is_floating_point::value, ""); auto val = duration.count(); - format_to( - std::back_inserter(buf), runtime("{:.{}f}"), - std::fmod(val * - static_cast(Duration::period::num) / - static_cast(Duration::period::den), - static_cast(60)), - precision); + if (num_fractional_digits < 0) { + num_fractional_digits = + count_fractional_digits::value; + if (num_fractional_digits < 6 && static_cast(std::round(val)) != val) + num_fractional_digits = 6; + } + + format_to(std::back_inserter(buf), runtime("{:.{}f}"), + std::fmod(val * static_cast(Duration::period::num) / + static_cast(Duration::period::den), + static_cast(60)), + num_fractional_digits); } template { - bool is_floating_point = false; - bool has_precision = false; + bool has_precision_integral = false; FMT_NORETURN void unsupported() { FMT_THROW(format_error("no date")); } @@ -1594,7 +1549,7 @@ struct chrono_format_checker : null_chrono_spec_handler { FMT_CONSTEXPR void on_iso_time() {} FMT_CONSTEXPR void on_am_pm() {} FMT_CONSTEXPR void on_duration_value() const { - if (has_precision && !is_floating_point) { + if (has_precision_integral) { FMT_THROW(format_error("precision not allowed for this argument type")); } } @@ -2073,9 +2028,8 @@ struct formatter, Char> { begin = detail::parse_width(begin, end, handler); if (begin == end) return {begin, begin}; auto checker = detail::chrono_format_checker(); - checker.is_floating_point = std::is_floating_point::value; if (*begin == '.') { - checker.has_precision = true; + checker.has_precision_integral = !std::is_floating_point::value; begin = detail::parse_precision(begin, end, handler); } if (begin != end && *begin == 'L') { From e30efa75f810f2d8b530b4d6581540982774a756 Mon Sep 17 00:00:00 2001 From: Stepan Ponomarev Date: Wed, 2 Nov 2022 14:28:34 +0100 Subject: [PATCH 6/7] Fix build: make n unsigned properly --- include/fmt/chrono.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 571081b2db9b..51ef184f47e6 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1038,12 +1038,13 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) { const auto fractional = detail::abs(d) - std::chrono::duration_cast(d); - uint32_or_64_or_128_t subseconds = + const auto& subseconds = std::chrono::treat_as_floating_point< typename subsecond_precision::rep>::value ? fractional.count() : std::chrono::duration_cast(fractional).count(); - const int num_digits = detail::count_digits(subseconds); + auto n = static_cast>(subseconds); + const int num_digits = detail::count_digits(n); int leading_zeroes = std::max(0, num_fractional_digits - num_digits); if (precision < 0) { @@ -1052,7 +1053,7 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) { std::chrono::seconds::period>::value) { *out++ = '.'; out = std::fill_n(out, leading_zeroes, '0'); - out = format_decimal(out, subseconds, num_digits).end; + out = format_decimal(out, n, num_digits).end; } } else { *out++ = '.'; @@ -1060,12 +1061,11 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) { out = std::fill_n(out, leading_zeroes, '0'); int remaining = precision - leading_zeroes; if (remaining < num_digits) { - subseconds /= - to_unsigned(detail::pow10(to_unsigned(num_digits - remaining))); - out = format_decimal(out, subseconds, remaining).end; + n /= to_unsigned(detail::pow10(to_unsigned(num_digits - remaining))); + out = format_decimal(out, n, remaining).end; return; } - out = format_decimal(out, subseconds, num_digits).end; + out = format_decimal(out, n, num_digits).end; remaining -= num_digits; out = std::fill_n(out, remaining, '0'); } From 5408dd183c0073d09bcd2ac383a5d8033d14fb60 Mon Sep 17 00:00:00 2001 From: Stepan Ponomarev Date: Wed, 2 Nov 2022 21:42:24 +0300 Subject: [PATCH 7/7] Merge write_fractional_seconds call --- include/fmt/chrono.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 51ef184f47e6..397a2704e699 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1038,7 +1038,7 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) { const auto fractional = detail::abs(d) - std::chrono::duration_cast(d); - const auto& subseconds = + const auto subseconds = std::chrono::treat_as_floating_point< typename subsecond_precision::rep>::value ? fractional.count() @@ -1860,13 +1860,8 @@ struct chrono_formatter { out = std::copy(buf.begin(), buf.end(), out); } else { write(second(), 2); - if (precision >= 0) { - write_fractional_seconds( - out, std::chrono::duration(val), precision); - } else { - write_fractional_seconds( - out, std::chrono::duration(val)); - } + write_fractional_seconds( + out, std::chrono::duration(val), precision); } return; }