mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-24 03:00:16 +00:00
Fix handling of nan durations
This commit is contained in:
parent
c1d430e61a
commit
ca978b3d21
@ -376,9 +376,20 @@ struct chrono_format_checker {
|
||||
FMT_NORETURN void on_tz_name() { report_no_date(); }
|
||||
};
|
||||
|
||||
template <typename T,
|
||||
typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
|
||||
inline bool isnan(T) {
|
||||
return false;
|
||||
}
|
||||
template <typename T, typename std::enable_if<std::is_floating_point<T>::value,
|
||||
int>::type = 0>
|
||||
inline bool isnan(T value) {
|
||||
return std::isnan(value);
|
||||
}
|
||||
|
||||
template <typename T> inline int to_int(T value) {
|
||||
FMT_ASSERT(value >= (std::numeric_limits<int>::min)() &&
|
||||
value <= (std::numeric_limits<int>::max)(),
|
||||
FMT_ASSERT(isnan(value) || (value >= (std::numeric_limits<int>::min)() &&
|
||||
value <= (std::numeric_limits<int>::max)()),
|
||||
"invalid value");
|
||||
return static_cast<int>(value);
|
||||
}
|
||||
@ -439,33 +450,37 @@ struct chrono_formatter {
|
||||
ms = std::chrono::duration_cast<milliseconds>(d - s);
|
||||
}
|
||||
|
||||
int hour() const { return to_int(mod((s.count() / 3600), 24)); }
|
||||
Rep hour() const { return mod((s.count() / 3600), 24); }
|
||||
|
||||
int hour12() const {
|
||||
auto hour = to_int(mod((s.count() / 3600), 12));
|
||||
return hour > 0 ? hour : 12;
|
||||
Rep hour12() const {
|
||||
Rep hour = mod((s.count() / 3600), 12);
|
||||
return hour <= 0 ? 12 : hour;
|
||||
}
|
||||
|
||||
int minute() const { return to_int(mod((s.count() / 60), 60)); }
|
||||
int second() const { return to_int(mod(s.count(), 60)); }
|
||||
Rep minute() const { return mod((s.count() / 60), 60); }
|
||||
Rep second() const { return mod(s.count(), 60); }
|
||||
|
||||
std::tm time() const {
|
||||
auto time = std::tm();
|
||||
time.tm_hour = hour();
|
||||
time.tm_min = minute();
|
||||
time.tm_sec = second();
|
||||
time.tm_hour = to_int(hour());
|
||||
time.tm_min = to_int(minute());
|
||||
time.tm_sec = to_int(second());
|
||||
return time;
|
||||
}
|
||||
|
||||
void write(int value, int width) {
|
||||
void write(Rep value, int width) {
|
||||
if (isnan(value)) return write_nan();
|
||||
typedef typename int_traits<int>::main_type main_type;
|
||||
main_type n = to_unsigned(value);
|
||||
main_type n = to_unsigned(to_int(value));
|
||||
int num_digits = internal::count_digits(n);
|
||||
if (width > num_digits) out = std::fill_n(out, width - num_digits, '0');
|
||||
out = format_decimal<char_type>(out, n, num_digits);
|
||||
}
|
||||
|
||||
void write_nan() { std::copy_n("nan", 3, out); }
|
||||
|
||||
void format_localized(const tm& time, const char* format) {
|
||||
if (isnan(val)) return write_nan();
|
||||
auto locale = context.locale().template get<std::locale>();
|
||||
auto& facet = std::use_facet<std::time_put<char_type>>(locale);
|
||||
std::basic_ostringstream<char_type> os;
|
||||
@ -497,14 +512,14 @@ struct chrono_formatter {
|
||||
void on_24_hour(numeric_system ns) {
|
||||
if (ns == numeric_system::standard) return write(hour(), 2);
|
||||
auto time = tm();
|
||||
time.tm_hour = hour();
|
||||
time.tm_hour = to_int(hour());
|
||||
format_localized(time, "%OH");
|
||||
}
|
||||
|
||||
void on_12_hour(numeric_system ns) {
|
||||
if (ns == numeric_system::standard) return write(hour12(), 2);
|
||||
auto time = tm();
|
||||
time.tm_hour = hour();
|
||||
time.tm_hour = hour12();
|
||||
format_localized(time, "%OI");
|
||||
}
|
||||
|
||||
@ -520,7 +535,7 @@ struct chrono_formatter {
|
||||
write(second(), 2);
|
||||
if (ms != std::chrono::milliseconds(0)) {
|
||||
*out++ = '.';
|
||||
write(to_int(ms.count()), 3);
|
||||
write(ms.count(), 3);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -306,12 +306,14 @@ TEST(ChronoTest, InvalidColons) {
|
||||
fmt::format_error);
|
||||
}
|
||||
|
||||
TEST(ChronoTest, LargeDuration) {
|
||||
TEST(ChronoTest, SpecialDurations) {
|
||||
EXPECT_EQ("40", fmt::format("{:%S}", std::chrono::duration<double>(1e20)));
|
||||
}
|
||||
|
||||
TEST(ChronoTest, NegativeDuration) {
|
||||
EXPECT_EQ("-00:01", fmt::format("{:%M:%S}", std::chrono::duration<double>(-1)));
|
||||
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",
|
||||
fmt::format("{:%I %H %M %S %R %r}", std::chrono::duration<double>(nan)));
|
||||
}
|
||||
|
||||
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
|
Loading…
Reference in New Issue
Block a user