forked from fmtlib/fmt
Use the same rep type for seconds to prevent overflow
This commit is contained in:
@@ -376,13 +376,24 @@ struct chrono_format_checker {
|
|||||||
FMT_NORETURN void on_tz_name() { report_no_date(); }
|
FMT_NORETURN void on_tz_name() { report_no_date(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Int> inline int to_int(Int value) {
|
template <typename T> inline int to_int(T value) {
|
||||||
FMT_ASSERT(value >= (std::numeric_limits<int>::min)() &&
|
FMT_ASSERT(value >= (std::numeric_limits<int>::min)() &&
|
||||||
value <= (std::numeric_limits<int>::max)(),
|
value <= (std::numeric_limits<int>::max)(),
|
||||||
"invalid value");
|
"invalid value");
|
||||||
return static_cast<int>(value);
|
return static_cast<int>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
|
||||||
|
inline T mod(T x, int y) {
|
||||||
|
return x % y;
|
||||||
|
}
|
||||||
|
template <typename T, typename std::enable_if<std::is_floating_point<T>::value,
|
||||||
|
int>::type = 0>
|
||||||
|
inline T mod(T x, int y) {
|
||||||
|
return std::fmod(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Rep, typename OutputIt>
|
template <typename Rep, typename OutputIt>
|
||||||
OutputIt static format_chrono_duration_value(OutputIt out, Rep val,
|
OutputIt static format_chrono_duration_value(OutputIt out, Rep val,
|
||||||
int precision) {
|
int precision) {
|
||||||
@@ -410,8 +421,9 @@ struct chrono_formatter {
|
|||||||
OutputIt out;
|
OutputIt out;
|
||||||
int precision;
|
int precision;
|
||||||
Rep val;
|
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;
|
||||||
std::chrono::seconds s;
|
|
||||||
milliseconds ms;
|
milliseconds ms;
|
||||||
|
|
||||||
typedef typename FormatContext::char_type char_type;
|
typedef typename FormatContext::char_type char_type;
|
||||||
@@ -421,18 +433,18 @@ struct chrono_formatter {
|
|||||||
: context(ctx),
|
: context(ctx),
|
||||||
out(o),
|
out(o),
|
||||||
val(d.count()),
|
val(d.count()),
|
||||||
s(std::chrono::duration_cast<std::chrono::seconds>(d)),
|
s(std::chrono::duration_cast<seconds>(d)),
|
||||||
ms(std::chrono::duration_cast<milliseconds>(d - s)) {}
|
ms(std::chrono::duration_cast<milliseconds>(d - s)) {}
|
||||||
|
|
||||||
int hour() const { return to_int((s.count() / 3600) % 24); }
|
int hour() const { return to_int(mod((s.count() / 3600), 24)); }
|
||||||
|
|
||||||
int hour12() const {
|
int hour12() const {
|
||||||
auto hour = to_int((s.count() / 3600) % 12);
|
auto hour = to_int(mod((s.count() / 3600), 12));
|
||||||
return hour > 0 ? hour : 12;
|
return hour > 0 ? hour : 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
int minute() const { return to_int((s.count() / 60) % 60); }
|
int minute() const { return to_int(mod((s.count() / 60), 60)); }
|
||||||
int second() const { return to_int(s.count() % 60); }
|
int second() const { return to_int(mod(s.count(), 60)); }
|
||||||
|
|
||||||
std::tm time() const {
|
std::tm time() const {
|
||||||
auto time = std::tm();
|
auto time = std::tm();
|
||||||
|
@@ -306,4 +306,8 @@ TEST(ChronoTest, InvalidColons) {
|
|||||||
fmt::format_error);
|
fmt::format_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ChronoTest, LargeDuration) {
|
||||||
|
EXPECT_EQ("40", fmt::format("{:%S}", std::chrono::duration<double>(1e20)));
|
||||||
|
}
|
||||||
|
|
||||||
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
|
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
|
||||||
|
Reference in New Issue
Block a user