Commit de5da509 authored by Victor Zverovich's avatar Victor Zverovich

Fix formatting of extreme durations (#1154)

parent ea2976e6
...@@ -414,9 +414,8 @@ template < ...@@ -414,9 +414,8 @@ template <
typename std::enable_if<std::is_floating_point<Rep>::value, int>::type = 0> typename std::enable_if<std::is_floating_point<Rep>::value, int>::type = 0>
inline std::chrono::duration<Rep, std::milli> get_milliseconds( inline std::chrono::duration<Rep, std::milli> get_milliseconds(
std::chrono::duration<Rep, Period> d) { std::chrono::duration<Rep, Period> d) {
auto ms = return std::chrono::duration<Rep, std::milli>(
std::chrono::duration_cast<std::chrono::duration<Rep, std::milli>>(d); mod(d.count() * Period::num / Period::den * 1000, 1000));
return std::chrono::duration<Rep, std::milli>(mod(ms.count(), 1000));
} }
template <typename Rep, typename OutputIt> template <typename Rep, typename OutputIt>
...@@ -431,12 +430,9 @@ OutputIt static format_chrono_duration_value(OutputIt out, Rep val, ...@@ -431,12 +430,9 @@ OutputIt static format_chrono_duration_value(OutputIt out, Rep val,
template <typename Period, typename OutputIt> template <typename Period, typename OutputIt>
static OutputIt format_chrono_duration_unit(OutputIt out) { static OutputIt format_chrono_duration_unit(OutputIt out) {
if (const char* unit = get_units<Period>()) if (const char* unit = get_units<Period>()) return format_to(out, "{}", unit);
return format_to(out, "{}", unit); if (Period::den == 1) return format_to(out, "[{}]s", Period::num);
else if (Period::den == 1) return format_to(out, "[{}/{}]s", Period::num, Period::den);
return format_to(out, "[{}]s", Period::num);
else
return format_to(out, "[{}/{}]s", Period::num, Period::den);
} }
template <typename FormatContext, typename OutputIt, typename Rep, template <typename FormatContext, typename OutputIt, typename Rep,
...@@ -449,7 +445,6 @@ struct chrono_formatter { ...@@ -449,7 +445,6 @@ struct chrono_formatter {
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;
milliseconds ms;
typedef typename FormatContext::char_type char_type; typedef typename FormatContext::char_type char_type;
...@@ -461,7 +456,6 @@ struct chrono_formatter { ...@@ -461,7 +456,6 @@ struct chrono_formatter {
*out++ = '-'; *out++ = '-';
} }
s = std::chrono::duration_cast<seconds>(d); s = std::chrono::duration_cast<seconds>(d);
ms = get_milliseconds(d);
} }
Rep hour() const { return mod((s.count() / 3600), 24); } Rep hour() const { return mod((s.count() / 3600), 24); }
...@@ -547,6 +541,7 @@ struct chrono_formatter { ...@@ -547,6 +541,7 @@ struct chrono_formatter {
void on_second(numeric_system ns) { void on_second(numeric_system ns) {
if (ns == numeric_system::standard) { if (ns == numeric_system::standard) {
write(second(), 2); write(second(), 2);
auto ms = get_milliseconds(std::chrono::duration<Rep, Period>(val));
if (ms != std::chrono::milliseconds(0)) { if (ms != std::chrono::milliseconds(0)) {
*out++ = '.'; *out++ = '.';
write(ms.count(), 3); write(ms.count(), 3);
......
...@@ -251,7 +251,7 @@ namespace uintptr { ...@@ -251,7 +251,7 @@ namespace uintptr {
struct uintptr_t { struct uintptr_t {
unsigned char value[sizeof(void*)]; unsigned char value[sizeof(void*)];
}; };
} } // namespace uintptr
using uintptr::uintptr_t; using uintptr::uintptr_t;
typedef std::numeric_limits<uintptr_t> numutil; typedef std::numeric_limits<uintptr_t> numutil;
...@@ -1113,10 +1113,7 @@ FMT_CONSTEXPR unsigned basic_parse_context<Char, ErrorHandler>::next_arg_id() { ...@@ -1113,10 +1113,7 @@ FMT_CONSTEXPR unsigned basic_parse_context<Char, ErrorHandler>::next_arg_id() {
namespace internal { namespace internal {
namespace grisu_options { namespace grisu_options {
enum { enum { fixed = 1, grisu3 = 2 };
fixed = 1,
grisu3 = 2
};
} }
// Formats value using the Grisu algorithm: // Formats value using the Grisu algorithm:
...@@ -1190,8 +1187,7 @@ It grisu_prettify(const char* digits, int size, int exp, It it, ...@@ -1190,8 +1187,7 @@ It grisu_prettify(const char* digits, int size, int exp, It it,
if (!params.trailing_zeros) { if (!params.trailing_zeros) {
// Remove trailing zeros. // Remove trailing zeros.
while (size > full_exp && digits[size - 1] == '0') --size; while (size > full_exp && digits[size - 1] == '0') --size;
if (size != full_exp) if (size != full_exp) *it++ = static_cast<Char>('.');
*it++ = static_cast<Char>('.');
return copy_str<Char>(digits + full_exp, digits + size, it); return copy_str<Char>(digits + full_exp, digits + size, it);
} }
*it++ = static_cast<Char>('.'); *it++ = static_cast<Char>('.');
...@@ -2877,7 +2873,7 @@ void basic_writer<Range>::write_double(T value, const format_specs& spec) { ...@@ -2877,7 +2873,7 @@ void basic_writer<Range>::write_double(T value, const format_specs& spec) {
(spec.type != 'a' && spec.type != 'A' && spec.type != 'e' && (spec.type != 'a' && spec.type != 'A' && spec.type != 'e' &&
spec.type != 'E') && spec.type != 'E') &&
internal::grisu_format(static_cast<double>(value), buffer, internal::grisu_format(static_cast<double>(value), buffer,
precision, options, exp); precision, options, exp);
if (!use_grisu) internal::sprintf_format(value, buffer, spec); if (!use_grisu) internal::sprintf_format(value, buffer, spec);
if (handler.as_percentage) { if (handler.as_percentage) {
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
#include "chrono.h" #include "chrono.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma message("fmt/time.h is deprecated, use fmt/chrono.h instead") # pragma message("fmt/time.h is deprecated, use fmt/chrono.h instead")
#else #else
#warning fmt/time.h is deprecated, use fmt/chrono.h instead # warning fmt/time.h is deprecated, use fmt/chrono.h instead
#endif #endif
#endif // FMT_TIME_H_ #endif // FMT_TIME_H_
...@@ -318,6 +318,10 @@ TEST(ChronoTest, SpecialDurations) { ...@@ -318,6 +318,10 @@ TEST(ChronoTest, SpecialDurations) {
fmt::format("{:%I %H %M %S %R %r}", std::chrono::duration<double>(nan))); fmt::format("{:%I %H %M %S %R %r}", std::chrono::duration<double>(nan)));
fmt::format("{:%S}", fmt::format("{:%S}",
std::chrono::duration<float, std::atto>(1.79400457e+31f)); std::chrono::duration<float, std::atto>(1.79400457e+31f));
EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::exa>(1)),
"1Es");
EXPECT_EQ(fmt::format("{}", std::chrono::duration<float, std::atto>(1)),
"1as");
} }
#endif // FMT_STATIC_THOUSANDS_SEPARATOR #endif // FMT_STATIC_THOUSANDS_SEPARATOR
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment