mirror of
https://github.com/fmtlib/fmt.git
synced 2024-12-26 00:21:13 +00:00
Fix handling of chrono durations with minimal signed rep
This commit is contained in:
parent
87e4ea2906
commit
78daa50ffc
@ -401,6 +401,17 @@ inline T mod(T x, int y) {
|
|||||||
return std::fmod(x, y);
|
return std::fmod(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If T is an integral type, maps T to its unsigned counterpart, otherwise
|
||||||
|
// leaves it unchanged (unlike std::make_unsigned).
|
||||||
|
template <typename T, bool INTEGRAL = std::is_integral<T>::value>
|
||||||
|
struct make_unsigned_or_unchanged {
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> struct make_unsigned_or_unchanged<T, true> {
|
||||||
|
using type = typename std::make_unsigned<T>::type;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Rep, typename Period,
|
template <typename Rep, typename Period,
|
||||||
typename std::enable_if<std::is_integral<Rep>::value, int>::type = 0>
|
typename std::enable_if<std::is_integral<Rep>::value, int>::type = 0>
|
||||||
inline std::chrono::duration<Rep, std::milli> get_milliseconds(
|
inline std::chrono::duration<Rep, std::milli> get_milliseconds(
|
||||||
@ -438,21 +449,27 @@ struct chrono_formatter {
|
|||||||
FormatContext& context;
|
FormatContext& context;
|
||||||
OutputIt out;
|
OutputIt out;
|
||||||
int precision;
|
int precision;
|
||||||
typedef typename std::conditional<std::is_integral<Rep>::value &&
|
// rep is unsigned to avoid overflow.
|
||||||
sizeof(Rep) < sizeof(int),
|
using rep = typename std::conditional<
|
||||||
int, Rep>::type rep;
|
std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int), unsigned,
|
||||||
|
typename make_unsigned_or_unchanged<Rep>::type>::type;
|
||||||
rep val;
|
rep val;
|
||||||
typedef std::chrono::duration<rep> seconds;
|
typedef std::chrono::duration<rep> seconds;
|
||||||
seconds s;
|
seconds s;
|
||||||
typedef std::chrono::duration<rep, std::milli> milliseconds;
|
typedef std::chrono::duration<rep, std::milli> milliseconds;
|
||||||
|
bool negative;
|
||||||
|
|
||||||
typedef typename FormatContext::char_type char_type;
|
typedef typename FormatContext::char_type char_type;
|
||||||
|
|
||||||
explicit chrono_formatter(FormatContext& ctx, OutputIt o,
|
explicit chrono_formatter(FormatContext& ctx, OutputIt o,
|
||||||
std::chrono::duration<Rep, Period> d)
|
std::chrono::duration<Rep, Period> d)
|
||||||
: context(ctx), out(o), val(d.count()) {
|
: context(ctx), out(o), val(d.count()), negative(false) {
|
||||||
if (d.count() < 0) d = -d;
|
if (d.count() < 0) {
|
||||||
s = std::chrono::duration_cast<seconds>(d);
|
val = -val;
|
||||||
|
negative = true;
|
||||||
|
}
|
||||||
|
s = std::chrono::duration_cast<seconds>(
|
||||||
|
std::chrono::duration<rep, Period>(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
Rep hour() const { return mod((s.count() / 3600), 24); }
|
Rep hour() const { return mod((s.count() / 3600), 24); }
|
||||||
@ -474,9 +491,9 @@ struct chrono_formatter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void write_sign() {
|
void write_sign() {
|
||||||
if (val < 0) {
|
if (negative) {
|
||||||
*out++ = '-';
|
*out++ = '-';
|
||||||
val = -val;
|
negative = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ TEST(ChronoTest, InvalidColons) {
|
|||||||
fmt::format_error);
|
fmt::format_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ChronoTest, NegativeDuration) {
|
TEST(ChronoTest, NegativeDurations) {
|
||||||
EXPECT_EQ("-12345", fmt::format("{:%Q}", std::chrono::seconds(-12345)));
|
EXPECT_EQ("-12345", fmt::format("{:%Q}", std::chrono::seconds(-12345)));
|
||||||
EXPECT_EQ("-03:25:45",
|
EXPECT_EQ("-03:25:45",
|
||||||
fmt::format("{:%H:%M:%S}", std::chrono::seconds(-12345)));
|
fmt::format("{:%H:%M:%S}", std::chrono::seconds(-12345)));
|
||||||
@ -316,6 +316,9 @@ TEST(ChronoTest, NegativeDuration) {
|
|||||||
EXPECT_EQ("-00.127",
|
EXPECT_EQ("-00.127",
|
||||||
fmt::format("{:%S}",
|
fmt::format("{:%S}",
|
||||||
std::chrono::duration<signed char, std::milli>{-127}));
|
std::chrono::duration<signed char, std::milli>{-127}));
|
||||||
|
auto min = std::numeric_limits<int>::min();
|
||||||
|
EXPECT_EQ(fmt::format("{}", min),
|
||||||
|
fmt::format("{:%Q}", std::chrono::duration<int>(min)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ChronoTest, SpecialDurations) {
|
TEST(ChronoTest, SpecialDurations) {
|
||||||
|
Loading…
Reference in New Issue
Block a user