From dd122ba55ce24071818fdef98583b87bdce29a4a Mon Sep 17 00:00:00 2001 From: js324 Date: Wed, 7 Feb 2024 12:47:32 -0500 Subject: [PATCH] Fix %S formatting for chrono durations with leading zeroes (#3814) --- include/fmt/chrono.h | 19 ++++++++++++------- test/chrono-test.cc | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index f6e5e7556398..71606a4ef5c3 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1151,18 +1151,23 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) { out = std::fill_n(out, leading_zeroes, '0'); out = format_decimal(out, n, num_digits).end; } - } else { + } else if (precision > 0) { *out++ = '.'; leading_zeroes = (std::min)(leading_zeroes, precision); - out = std::fill_n(out, leading_zeroes, '0'); int remaining = precision - leading_zeroes; - if (remaining != 0 && remaining < num_digits) { - n /= to_unsigned(detail::pow10(to_unsigned(num_digits - remaining))); - out = format_decimal(out, n, remaining).end; + out = std::fill_n(out, leading_zeroes, '0'); + if (remaining < num_digits) { + int num_truncated_digits = num_digits - remaining; + n /= to_unsigned(detail::pow10(to_unsigned(num_truncated_digits))); + if (n) { + out = format_decimal(out, n, remaining).end; + } return; } - out = format_decimal(out, n, num_digits).end; - remaining -= num_digits; + if (n) { + out = format_decimal(out, n, num_digits).end; + remaining -= num_digits; + } out = std::fill_n(out, remaining, '0'); } } diff --git a/test/chrono-test.cc b/test/chrono-test.cc index 827fa102b1f6..fa237f22a586 100644 --- a/test/chrono-test.cc +++ b/test/chrono-test.cc @@ -791,6 +791,20 @@ TEST(chrono_test, cpp20_duration_subsecond_support) { "01.234000"); EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{-1234}), "-01.234000"); + EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{12345}), + "12.34"); + EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{12375}), + "12.37"); + EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{-12375}), + "-12.37"); + EXPECT_EQ(fmt::format("{:.0%S}", std::chrono::milliseconds{12054}), + "12"); + EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{99999}), + "39.99"); + EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{1000}), + "01.00"); + EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::milliseconds{1}), + "00.001"); 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");