From 5fe5b000f6d33c463707f219c1e5c69d76126c43 Mon Sep 17 00:00:00 2001 From: Shawn Zhong Date: Tue, 3 Jan 2023 21:56:49 -0600 Subject: [PATCH] Fix negative subsec for tp --- include/fmt/chrono.h | 30 ++++++++---------------------- test/chrono-test.cc | 8 ++++++++ 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 64ebdabe..86defb3c 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1046,26 +1046,6 @@ inline Int to_nonnegative_int(T value, Int upper) { return static_cast(value); } -template ::is_signed)> -constexpr std::chrono::duration abs( - std::chrono::duration d) { - // We need to compare the duration using the count() method directly - // due to a compiler bug in clang-11 regarding the spaceship operator, - // when -Wzero-as-null-pointer-constant is enabled. - // In clang-12 the bug has been fixed. See - // https://bugs.llvm.org/show_bug.cgi?id=46235 and the reproducible example: - // https://www.godbolt.org/z/Knbb5joYx. - return d.count() >= d.zero().count() ? d : -d; -} - -template ::is_signed)> -constexpr std::chrono::duration abs( - std::chrono::duration d) { - return d; -} - constexpr long long pow10(std::uint32_t n) { return n == 0 ? 1 : 10 * pow10(n - 1); } @@ -1101,7 +1081,7 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) { std::ratio<1, detail::pow10(num_fractional_digits)>>; const auto fractional = - detail::abs(d) - std::chrono::duration_cast(d); + d - std::chrono::duration_cast(d); const auto subseconds = std::chrono::treat_as_floating_point< typename subsecond_precision::rep>::value @@ -2127,9 +2107,15 @@ struct formatter, if (period::num != 1 || period::den != 1 || std::is_floating_point::value) { const auto epoch = val.time_since_epoch(); - const auto subsecs = std::chrono::duration_cast( + auto subsecs = std::chrono::duration_cast( epoch - std::chrono::duration_cast(epoch)); + if (subsecs.count() < 0) { + subsecs += std::chrono::seconds(1); + val -= std::chrono::seconds(1); + } + + return formatter::do_format( gmtime(std::chrono::time_point_cast(val)), ctx, &subsecs); diff --git a/test/chrono-test.cc b/test/chrono-test.cc index 9ac9142c..c694e82f 100644 --- a/test/chrono-test.cc +++ b/test/chrono-test.cc @@ -879,4 +879,12 @@ TEST(chrono_test, timestamps_sub_seconds) { t10(std::chrono::milliseconds(2000)); EXPECT_EQ(fmt::format("{:%S}", t10), "02.000"); + + const auto tp11 = std::chrono::system_clock::from_time_t(0) + + std::chrono::milliseconds(250); + EXPECT_EQ(fmt::format("{:%S}", tp11), "00.250000"); + + const auto tp12 = std::chrono::system_clock::from_time_t(0) - + std::chrono::milliseconds(250); + EXPECT_EQ(fmt::format("{:%S}", tp12), "59.750000"); }