mirror of
https://github.com/fmtlib/fmt.git
synced 2024-09-19 20:39:59 +00:00
Fix negative subsec for time_point (#3261)
This commit is contained in:
parent
2c80cedc39
commit
676c2a107e
@ -1046,26 +1046,6 @@ inline Int to_nonnegative_int(T value, Int upper) {
|
|||||||
return static_cast<Int>(value);
|
return static_cast<Int>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Rep, typename Period,
|
|
||||||
FMT_ENABLE_IF(std::numeric_limits<Rep>::is_signed)>
|
|
||||||
constexpr std::chrono::duration<Rep, Period> abs(
|
|
||||||
std::chrono::duration<Rep, Period> 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 <typename Rep, typename Period,
|
|
||||||
FMT_ENABLE_IF(!std::numeric_limits<Rep>::is_signed)>
|
|
||||||
constexpr std::chrono::duration<Rep, Period> abs(
|
|
||||||
std::chrono::duration<Rep, Period> d) {
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr long long pow10(std::uint32_t n) {
|
constexpr long long pow10(std::uint32_t n) {
|
||||||
return n == 0 ? 1 : 10 * pow10(n - 1);
|
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)>>;
|
std::ratio<1, detail::pow10(num_fractional_digits)>>;
|
||||||
|
|
||||||
const auto fractional =
|
const auto fractional =
|
||||||
detail::abs(d) - std::chrono::duration_cast<std::chrono::seconds>(d);
|
d - std::chrono::duration_cast<std::chrono::seconds>(d);
|
||||||
const auto subseconds =
|
const auto subseconds =
|
||||||
std::chrono::treat_as_floating_point<
|
std::chrono::treat_as_floating_point<
|
||||||
typename subsecond_precision::rep>::value
|
typename subsecond_precision::rep>::value
|
||||||
@ -2125,9 +2105,14 @@ struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
|
|||||||
if (period::num != 1 || period::den != 1 ||
|
if (period::num != 1 || period::den != 1 ||
|
||||||
std::is_floating_point<typename Duration::rep>::value) {
|
std::is_floating_point<typename Duration::rep>::value) {
|
||||||
const auto epoch = val.time_since_epoch();
|
const auto epoch = val.time_since_epoch();
|
||||||
const auto subsecs = std::chrono::duration_cast<Duration>(
|
auto subsecs = std::chrono::duration_cast<Duration>(
|
||||||
epoch - std::chrono::duration_cast<std::chrono::seconds>(epoch));
|
epoch - std::chrono::duration_cast<std::chrono::seconds>(epoch));
|
||||||
|
|
||||||
|
if (subsecs.count() < 0) {
|
||||||
|
subsecs += std::chrono::seconds(1);
|
||||||
|
val -= std::chrono::seconds(1);
|
||||||
|
}
|
||||||
|
|
||||||
return formatter<std::tm, Char>::do_format(
|
return formatter<std::tm, Char>::do_format(
|
||||||
gmtime(std::chrono::time_point_cast<std::chrono::seconds>(val)), ctx,
|
gmtime(std::chrono::time_point_cast<std::chrono::seconds>(val)), ctx,
|
||||||
&subsecs);
|
&subsecs);
|
||||||
|
@ -908,4 +908,14 @@ TEST(chrono_test, timestamps_sub_seconds) {
|
|||||||
t10(std::chrono::milliseconds(2000));
|
t10(std::chrono::milliseconds(2000));
|
||||||
|
|
||||||
EXPECT_EQ(fmt::format("{:%S}", t10), "02.000");
|
EXPECT_EQ(fmt::format("{:%S}", t10), "02.000");
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto epoch = std::chrono::time_point<std::chrono::system_clock,
|
||||||
|
std::chrono::milliseconds>();
|
||||||
|
const auto d = std::chrono::milliseconds(250);
|
||||||
|
|
||||||
|
EXPECT_EQ("59.750", fmt::format("{:%S}", epoch - d));
|
||||||
|
EXPECT_EQ("00.000", fmt::format("{:%S}", epoch));
|
||||||
|
EXPECT_EQ("00.250", fmt::format("{:%S}", epoch + d));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user