From 47fcd357ab6a9583f2307d1f78fdd674060efe61 Mon Sep 17 00:00:00 2001 From: khan Date: Fri, 6 Nov 2026 18:44:43 -0500 Subject: [PATCH] Avoid narrowing duration day counts to the original representation (#5003) * Avoid narrowing duration day counts to the original representation * Keep duration field values in the promoted representation --------- Co-authored-by: Aikhan Jumashukurov <117706338+aikhanj@users.noreply.github.com> --- include/fmt/chrono.h | 18 +++++++----------- test/chrono-test.cc | 10 ++++++++++ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index d4b44eb3..62d7a7c6 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1703,20 +1703,16 @@ struct duration_formatter { return true; } - auto days() const -> Rep { return static_cast(s.count() / 86400); } - auto hour() const -> Rep { - return static_cast(mod((s.count() / 3600), 24)); - } + auto days() const -> rep { return s.count() / 86400; } + auto hour() const -> rep { return mod((s.count() / 3600), 24); } - auto hour12() const -> Rep { - Rep hour = static_cast(mod((s.count() / 3600), 12)); + auto hour12() const -> rep { + auto hour = mod((s.count() / 3600), 12); return hour < 1 ? 12 : hour; } - auto minute() const -> Rep { - return static_cast(mod((s.count() / 60), 60)); - } - auto second() const -> Rep { return static_cast(mod(s.count(), 60)); } + auto minute() const -> rep { return mod((s.count() / 60), 60); } + auto second() const -> rep { return mod(s.count(), 60); } auto time() const -> std::tm { auto time = std::tm(); @@ -1732,7 +1728,7 @@ struct duration_formatter { negative = false; } - void write(Rep value, int width, pad_type pad = pad_type::zero) { + void write(rep value, int width, pad_type pad = pad_type::zero) { write_sign(); if (isnan(value)) return write_nan(); uint32_or_64_or_128_t n = diff --git a/test/chrono-test.cc b/test/chrono-test.cc index eac86bec..2b04a3a3 100644 --- a/test/chrono-test.cc +++ b/test/chrono-test.cc @@ -546,6 +546,16 @@ TEST(chrono_test, format_specs) { EXPECT_EQ(fmt::format("{:%q}", std::chrono::seconds(12345)), "s"); } +TEST(chrono_test, format_days_with_signed_char_rep) { + using signed_days = std::chrono::duration>; + EXPECT_EQ(fmt::format("{:%j}", signed_days(-128)), "-128"); +} + +TEST(chrono_test, format_days_with_unsigned_char_rep) { + using two_days = std::chrono::duration>; + EXPECT_EQ(fmt::format("{:%j}", two_days(200)), "400"); +} + TEST(chrono_test, invalid_specs) { auto sec = std::chrono::seconds(0); EXPECT_THROW_MSG((void)fmt::format(runtime("{:%a}"), sec), fmt::format_error,