diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 2b289a87..9de56df9 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -376,13 +376,24 @@ struct chrono_format_checker { FMT_NORETURN void on_tz_name() { report_no_date(); } }; -template inline int to_int(Int value) { +template inline int to_int(T value) { FMT_ASSERT(value >= (std::numeric_limits::min)() && value <= (std::numeric_limits::max)(), "invalid value"); return static_cast(value); } +template ::value, int>::type = 0> +inline T mod(T x, int y) { + return x % y; +} +template ::value, + int>::type = 0> +inline T mod(T x, int y) { + return std::fmod(x, y); +} + template OutputIt static format_chrono_duration_value(OutputIt out, Rep val, int precision) { @@ -410,8 +421,9 @@ struct chrono_formatter { OutputIt out; int precision; Rep val; + typedef std::chrono::duration seconds; + seconds s; typedef std::chrono::duration milliseconds; - std::chrono::seconds s; milliseconds ms; typedef typename FormatContext::char_type char_type; @@ -421,18 +433,18 @@ struct chrono_formatter { : context(ctx), out(o), val(d.count()), - s(std::chrono::duration_cast(d)), + s(std::chrono::duration_cast(d)), ms(std::chrono::duration_cast(d - s)) {} - int hour() const { return to_int((s.count() / 3600) % 24); } + int hour() const { return to_int(mod((s.count() / 3600), 24)); } int hour12() const { - auto hour = to_int((s.count() / 3600) % 12); + auto hour = to_int(mod((s.count() / 3600), 12)); return hour > 0 ? hour : 12; } - int minute() const { return to_int((s.count() / 60) % 60); } - int second() const { return to_int(s.count() % 60); } + int minute() const { return to_int(mod((s.count() / 60), 60)); } + int second() const { return to_int(mod(s.count(), 60)); } std::tm time() const { auto time = std::tm(); diff --git a/test/chrono-test.cc b/test/chrono-test.cc index a4f563cd..8965af92 100644 --- a/test/chrono-test.cc +++ b/test/chrono-test.cc @@ -306,4 +306,8 @@ TEST(ChronoTest, InvalidColons) { fmt::format_error); } +TEST(ChronoTest, LargeDuration) { + EXPECT_EQ("40", fmt::format("{:%S}", std::chrono::duration(1e20))); +} + #endif // FMT_STATIC_THOUSANDS_SEPARATOR