Fix a few chrono formatting corner cases (#1178)
This commit is contained in:
parent
e5512c5d57
commit
30bce6c14c
@ -419,13 +419,10 @@ inline std::chrono::duration<Rep, std::milli> get_milliseconds(
|
||||
}
|
||||
|
||||
template <typename Rep, typename OutputIt>
|
||||
OutputIt static format_chrono_duration_value(OutputIt out, Rep val,
|
||||
int precision) {
|
||||
if (precision < 0) {
|
||||
return format_to(out, std::is_floating_point<Rep>::value ? "{:g}" : "{}",
|
||||
val);
|
||||
}
|
||||
return format_to(out, "{:.{}f}", val, precision);
|
||||
OutputIt format_chrono_duration_value(OutputIt out, Rep val, int precision) {
|
||||
if (precision >= 0) return format_to(out, "{:.{}f}", val, precision);
|
||||
return format_to(out, std::is_floating_point<Rep>::value ? "{:g}" : "{}",
|
||||
val);
|
||||
}
|
||||
|
||||
template <typename Period, typename OutputIt>
|
||||
@ -441,20 +438,20 @@ struct chrono_formatter {
|
||||
FormatContext& context;
|
||||
OutputIt out;
|
||||
int precision;
|
||||
Rep val;
|
||||
typedef std::chrono::duration<Rep> seconds;
|
||||
typedef typename std::conditional<std::is_integral<Rep>::value &&
|
||||
sizeof(Rep) < sizeof(int),
|
||||
int, Rep>::type rep;
|
||||
rep val;
|
||||
typedef std::chrono::duration<rep> seconds;
|
||||
seconds s;
|
||||
typedef std::chrono::duration<Rep, std::milli> milliseconds;
|
||||
typedef std::chrono::duration<rep, std::milli> milliseconds;
|
||||
|
||||
typedef typename FormatContext::char_type char_type;
|
||||
|
||||
explicit chrono_formatter(FormatContext& ctx, OutputIt o,
|
||||
std::chrono::duration<Rep, Period> d)
|
||||
: context(ctx), out(o), val(d.count()) {
|
||||
if (d.count() < 0) {
|
||||
d = -d;
|
||||
*out++ = '-';
|
||||
}
|
||||
if (d.count() < 0) d = -d;
|
||||
s = std::chrono::duration_cast<seconds>(d);
|
||||
}
|
||||
|
||||
@ -476,7 +473,15 @@ struct chrono_formatter {
|
||||
return time;
|
||||
}
|
||||
|
||||
void write_sign() {
|
||||
if (val < 0) {
|
||||
*out++ = '-';
|
||||
val = -val;
|
||||
}
|
||||
}
|
||||
|
||||
void write(Rep value, int width) {
|
||||
write_sign();
|
||||
if (isnan(value)) return write_nan();
|
||||
typedef typename int_traits<int>::main_type main_type;
|
||||
main_type n = to_unsigned(to_int(value));
|
||||
@ -570,6 +575,7 @@ struct chrono_formatter {
|
||||
void on_am_pm() { format_localized(time(), "%p"); }
|
||||
|
||||
void on_duration_value() {
|
||||
write_sign();
|
||||
out = format_chrono_duration_value(out, val, precision);
|
||||
}
|
||||
|
||||
|
@ -306,12 +306,22 @@ TEST(ChronoTest, InvalidColons) {
|
||||
fmt::format_error);
|
||||
}
|
||||
|
||||
TEST(ChronoTest, NegativeDuration) {
|
||||
EXPECT_EQ("-12345", fmt::format("{:%Q}", std::chrono::seconds(-12345)));
|
||||
EXPECT_EQ("-03:25:45",
|
||||
fmt::format("{:%H:%M:%S}", std::chrono::seconds(-12345)));
|
||||
EXPECT_EQ("-00:01",
|
||||
fmt::format("{:%M:%S}", std::chrono::duration<double>(-1)));
|
||||
EXPECT_EQ("s", fmt::format("{:%q}", std::chrono::seconds(-12345)));
|
||||
EXPECT_EQ("-00.127",
|
||||
fmt::format("{:%S}",
|
||||
std::chrono::duration<signed char, std::milli>{-127}));
|
||||
}
|
||||
|
||||
TEST(ChronoTest, SpecialDurations) {
|
||||
EXPECT_EQ(
|
||||
"40.",
|
||||
fmt::format("{:%S}", std::chrono::duration<double>(1e20)).substr(0, 3));
|
||||
EXPECT_EQ("-00:01",
|
||||
fmt::format("{:%M:%S}", std::chrono::duration<double>(-1)));
|
||||
auto nan = std::numeric_limits<double>::quiet_NaN();
|
||||
EXPECT_EQ(
|
||||
"nan nan nan nan.nan nan:nan nan",
|
||||
@ -322,6 +332,10 @@ TEST(ChronoTest, SpecialDurations) {
|
||||
"1Es");
|
||||
EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::atto>(1)),
|
||||
"1as");
|
||||
EXPECT_EQ(fmt::format("{:%R}", std::chrono::duration<char, std::mega>{2}),
|
||||
"03:33");
|
||||
EXPECT_EQ(fmt::format("{:%T}", std::chrono::duration<char, std::mega>{2}),
|
||||
"03:33:20");
|
||||
}
|
||||
|
||||
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
|
Loading…
Reference in New Issue
Block a user