Review fixes 2
This commit is contained in:
parent
e4f5e770d1
commit
d7f2a700d9
@ -1023,9 +1023,10 @@ struct count_fractional_digits<Num, Den, N, false> {
|
|||||||
static constexpr int value = (Num % Den == 0) ? N : 6;
|
static constexpr int value = (Num % Den == 0) ? N : 6;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Format non-fractional subseconds with an appriate number of digits.
|
// Format subseconds which are given as an integer type with an appropriate
|
||||||
template <typename OutputIt, typename Duration, typename char_type>
|
// number of digits.
|
||||||
void write_sub_sec(OutputIt& out, Duration d) {
|
template <typename char_type, typename OutputIt, typename Duration>
|
||||||
|
void write_fractional_seconds(OutputIt& out, Duration d) {
|
||||||
FMT_ASSERT(!std::is_floating_point<typename Duration::rep>::value, "");
|
FMT_ASSERT(!std::is_floating_point<typename Duration::rep>::value, "");
|
||||||
constexpr auto num_fractional_digits =
|
constexpr auto num_fractional_digits =
|
||||||
count_fractional_digits<Duration::period::num,
|
count_fractional_digits<Duration::period::num,
|
||||||
@ -1055,24 +1056,26 @@ void write_sub_sec(OutputIt& out, Duration d) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format fractional seconds with an appropiate number of digits.
|
// Format subseconds which are given as a floating point type with an appropiate
|
||||||
|
// number of digits. We cannot pass the Duration here, as we explicitly need to
|
||||||
|
// pass the Rep value in the chrono_formatter.
|
||||||
template <typename Rep, long long Num, long long Den>
|
template <typename Rep, long long Num, long long Den>
|
||||||
void format_sec_fractional(basic_memory_buffer<char>& buf, Rep val) {
|
void format_floating_seconds(memory_buffer& buf, Rep val) {
|
||||||
FMT_ASSERT(std::is_floating_point<Rep>::value, "");
|
FMT_ASSERT(std::is_floating_point<Rep>::value, "");
|
||||||
auto num_fractional_digits = count_fractional_digits<Num, Den>::value;
|
auto num_fractional_digits = count_fractional_digits<Num, Den>::value;
|
||||||
// For non-integer values, we ensure at least 6 digits to get microsecond
|
// For non-integer values, we ensure at least 6 digits to get microsecond
|
||||||
// precision.
|
// precision.
|
||||||
if (num_fractional_digits < 6 && static_cast<Rep>(std::round(val)) != val) {
|
if (num_fractional_digits < 6 && static_cast<Rep>(std::round(val)) != val)
|
||||||
num_fractional_digits = 6;
|
num_fractional_digits = 6;
|
||||||
}
|
|
||||||
format_to(std::back_inserter(buf), runtime("{:.{}f}"),
|
format_to(std::back_inserter(buf), runtime("{:.{}f}"),
|
||||||
std::fmod(val * static_cast<Rep>(Num) / static_cast<Rep>(Den),
|
std::fmod(val * static_cast<Rep>(Num) / static_cast<Rep>(Den),
|
||||||
static_cast<Rep>(60)),
|
static_cast<Rep>(60)),
|
||||||
num_fractional_digits);
|
num_fractional_digits);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename Char, typename Rep = int,
|
template <typename OutputIt, typename Char,
|
||||||
typename Period = std::ratio<1, 1>>
|
typename Duration = std::chrono::seconds>
|
||||||
class tm_writer {
|
class tm_writer {
|
||||||
private:
|
private:
|
||||||
static constexpr int days_per_week = 7;
|
static constexpr int days_per_week = 7;
|
||||||
@ -1080,8 +1083,7 @@ class tm_writer {
|
|||||||
const std::locale& loc_;
|
const std::locale& loc_;
|
||||||
const bool is_classic_;
|
const bool is_classic_;
|
||||||
OutputIt out_;
|
OutputIt out_;
|
||||||
std::chrono::duration<Rep, Period> subsecs_;
|
const Duration* subsecs_;
|
||||||
bool has_subsecs_;
|
|
||||||
const std::tm& tm_;
|
const std::tm& tm_;
|
||||||
|
|
||||||
auto tm_sec() const noexcept -> int {
|
auto tm_sec() const noexcept -> int {
|
||||||
@ -1245,19 +1247,11 @@ class tm_writer {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
tm_writer(const std::locale& loc, OutputIt out, const std::tm& tm,
|
tm_writer(const std::locale& loc, OutputIt out, const std::tm& tm,
|
||||||
std::chrono::duration<Rep, Period> subsecs)
|
const Duration* subsecs = nullptr)
|
||||||
: loc_(loc),
|
: loc_(loc),
|
||||||
is_classic_(loc_ == get_classic_locale()),
|
is_classic_(loc_ == get_classic_locale()),
|
||||||
out_(out),
|
out_(out),
|
||||||
subsecs_(subsecs),
|
subsecs_(subsecs),
|
||||||
has_subsecs_(true),
|
|
||||||
tm_(tm) {}
|
|
||||||
|
|
||||||
tm_writer(const std::locale& loc, OutputIt out, const std::tm& tm)
|
|
||||||
: loc_(loc),
|
|
||||||
is_classic_(loc_ == get_classic_locale()),
|
|
||||||
out_(out),
|
|
||||||
has_subsecs_(false),
|
|
||||||
tm_(tm) {}
|
tm_(tm) {}
|
||||||
|
|
||||||
OutputIt out() const { return out_; }
|
OutputIt out() const { return out_; }
|
||||||
@ -1460,18 +1454,18 @@ class tm_writer {
|
|||||||
void on_second(numeric_system ns) {
|
void on_second(numeric_system ns) {
|
||||||
if (is_classic_ || ns == numeric_system::standard) {
|
if (is_classic_ || ns == numeric_system::standard) {
|
||||||
write2(tm_sec());
|
write2(tm_sec());
|
||||||
if (has_subsecs_) {
|
if (subsecs_) {
|
||||||
if (std::is_floating_point<Rep>::value) {
|
if (std::is_floating_point<typename Duration::rep>::value) {
|
||||||
auto buf = memory_buffer();
|
auto buf = memory_buffer();
|
||||||
format_sec_fractional<Rep, Period::num, Period::den>(
|
format_floating_seconds<typename Duration::rep, Duration::period::num,
|
||||||
buf, subsecs_.count());
|
Duration::period::den>(buf,
|
||||||
|
subsecs_->count());
|
||||||
if (buf.size() > 1) {
|
if (buf.size() > 1) {
|
||||||
// Remove the leading "0", write something like ".123".
|
// Remove the leading "0", write something like ".123".
|
||||||
out_ = std::copy(buf.begin() + 1, buf.end(), out_);
|
out_ = std::copy(buf.begin() + 1, buf.end(), out_);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
write_sub_sec<OutputIt, std::chrono::duration<Rep, Period>, Char>(
|
write_fractional_seconds<Char>(out_, *subsecs_);
|
||||||
out_, subsecs_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1832,13 +1826,13 @@ struct chrono_formatter {
|
|||||||
if (ns == numeric_system::standard) {
|
if (ns == numeric_system::standard) {
|
||||||
if (std::is_floating_point<rep>::value) {
|
if (std::is_floating_point<rep>::value) {
|
||||||
auto buf = memory_buffer();
|
auto buf = memory_buffer();
|
||||||
format_sec_fractional<rep, Period::num, Period::den>(buf, val);
|
format_floating_seconds<rep, Period::num, Period::den>(buf, val);
|
||||||
if (negative) *out++ = '-';
|
if (negative) *out++ = '-';
|
||||||
if (buf.size() < 2 || buf[1] == '.') *out++ = '0';
|
if (buf.size() < 2 || buf[1] == '.') *out++ = '0';
|
||||||
out = std::copy(buf.begin(), buf.end(), out);
|
out = std::copy(buf.begin(), buf.end(), out);
|
||||||
} else {
|
} else {
|
||||||
write(second(), 2);
|
write(second(), 2);
|
||||||
write_sub_sec<OutputIt, std::chrono::duration<Rep, Period>, char_type>(
|
write_fractional_seconds<char_type>(
|
||||||
out, std::chrono::duration<Rep, Period>(val));
|
out, std::chrono::duration<Rep, Period>(val));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -2077,12 +2071,11 @@ struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
|
|||||||
return formatter<std::tm, Char>::format(
|
return formatter<std::tm, Char>::format(
|
||||||
localtime(std::chrono::time_point_cast<std::chrono::seconds>(val)),
|
localtime(std::chrono::time_point_cast<std::chrono::seconds>(val)),
|
||||||
ctx, subsecs);
|
ctx, subsecs);
|
||||||
|
|
||||||
} else {
|
|
||||||
return formatter<std::tm, Char>::format(
|
|
||||||
localtime(std::chrono::time_point_cast<std::chrono::seconds>(val)),
|
|
||||||
ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return formatter<std::tm, Char>::format(
|
||||||
|
localtime(std::chrono::time_point_cast<std::chrono::seconds>(val)),
|
||||||
|
ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2150,14 +2143,13 @@ template <typename Char> struct formatter<std::tm, Char> {
|
|||||||
return w.out();
|
return w.out();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FormatContext, typename Rep, typename Period>
|
template <typename FormatContext, typename Duration>
|
||||||
auto format(const std::tm& tm, FormatContext& ctx,
|
auto format(const std::tm& tm, FormatContext& ctx,
|
||||||
const std::chrono::duration<Rep, Period>& subsecs) const
|
const Duration& subsecs) const -> decltype(ctx.out()) {
|
||||||
-> decltype(ctx.out()) {
|
|
||||||
const auto loc_ref = ctx.locale();
|
const auto loc_ref = ctx.locale();
|
||||||
detail::get_locale loc(static_cast<bool>(loc_ref), loc_ref);
|
detail::get_locale loc(static_cast<bool>(loc_ref), loc_ref);
|
||||||
auto w = detail::tm_writer<decltype(ctx.out()), Char, Rep, Period>(
|
auto w = detail::tm_writer<decltype(ctx.out()), Char, Duration>(
|
||||||
loc, ctx.out(), tm, subsecs);
|
loc, ctx.out(), tm, &subsecs);
|
||||||
if (spec_ == spec::year_month_day)
|
if (spec_ == spec::year_month_day)
|
||||||
w.on_iso_date();
|
w.on_iso_date();
|
||||||
else if (spec_ == spec::hh_mm_ss)
|
else if (spec_ == spec::hh_mm_ss)
|
||||||
|
|||||||
@ -645,6 +645,8 @@ TEST(chrono_test, cpp20_duration_subsecond_support) {
|
|||||||
// Check that floating point seconds with ratio<1,1> are printed.
|
// Check that floating point seconds with ratio<1,1> are printed.
|
||||||
EXPECT_EQ(fmt::format("{:%S}", std::chrono::duration<double>{1.5}),
|
EXPECT_EQ(fmt::format("{:%S}", std::chrono::duration<double>{1.5}),
|
||||||
"01.500000");
|
"01.500000");
|
||||||
|
EXPECT_EQ(fmt::format("{:%M:%S}", std::chrono::duration<double>{-61.25}),
|
||||||
|
"-01:01.250000");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
|
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user