Skip to content

Commit

Permalink
fix chrono duration rounding with leading zeroes
Browse files Browse the repository at this point in the history
  • Loading branch information
js324 committed Jan 16, 2024
1 parent 13ec66b commit 8227a2f
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 7 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ set_verbose(FMT_INC_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE STRING
"Installation directory for include files, a relative path that "
"will be joined with ${CMAKE_INSTALL_PREFIX} or an absolute path.")

option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF)
option(FMT_PEDANTIC "Enable extra warnings and expensive tests." ON)
option(FMT_WERROR "Halt the compilation with an error on compiler warnings."
OFF)

Expand Down
35 changes: 29 additions & 6 deletions include/fmt/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -1154,15 +1154,38 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) {
} else {
*out++ = '.';
leading_zeroes = (std::min)(leading_zeroes, precision);
out = std::fill_n(out, leading_zeroes, '0');
int remaining = precision - leading_zeroes;
if (remaining != 0 && remaining < num_digits) {
n /= to_unsigned(detail::pow10(to_unsigned(num_digits - remaining)));
out = format_decimal<Char>(out, n, remaining).end;
if (remaining < num_digits) {
int num_truncated_digits = num_digits - remaining;
n /= to_unsigned(detail::pow10(to_unsigned(num_truncated_digits)-1)); //002999
const int old_num_digits = detail::count_digits(n);
int roundingDigit = n % 10;
n /= 10;
if (roundingDigit > 5 || (roundingDigit == 5 && n % 10 % 2 != 0)) {
n += 1;
}
if (old_num_digits == detail::count_digits(n)) {
if (leading_zeroes) {
out = std::fill_n(out, leading_zeroes-1, '0');
*out++ = '1';
out = std::fill_n(out, remaining, '0');
}
else {
n -= 1;
out = format_decimal<Char>(out, n, remaining).end;
}
}
else {
out = std::fill_n(out, leading_zeroes, '0');
out = format_decimal<Char>(out, n, remaining).end;
}
return;
}
out = format_decimal<Char>(out, n, num_digits).end;
remaining -= num_digits;
out = std::fill_n(out, leading_zeroes, '0');
if (n) {
out = format_decimal<Char>(out, n, num_digits).end;
remaining -= num_digits;
}
out = std::fill_n(out, remaining, '0');
}
}
Expand Down
12 changes: 12 additions & 0 deletions test/chrono-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,18 @@ TEST(chrono_test, cpp20_duration_subsecond_support) {
"01.234000");
EXPECT_EQ(fmt::format("{:.6%S}", std::chrono::milliseconds{-1234}),
"-01.234000");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{12345}),
"12.34");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{12375}),
"12.38");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{-12375}),
"-12.38");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{12054}),
"12.05");
EXPECT_EQ(fmt::format("{:.1%S}", std::chrono::milliseconds{12054}),
"12.1");
EXPECT_EQ(fmt::format("{:.2%S}", std::chrono::milliseconds{99999}),
"39.99");
EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::seconds{1234}), "34.000");
EXPECT_EQ(fmt::format("{:.3%S}", std::chrono::hours{1234}), "00.000");
EXPECT_EQ(fmt::format("{:.5%S}", dms(1.234)), "00.00123");
Expand Down

0 comments on commit 8227a2f

Please sign in to comment.