Skip to content

Commit

Permalink
Implement %j specifier for std::chrono::duration
Browse files Browse the repository at this point in the history
This adds support for `%j` presentation type for duration types:

> "If the type being formatted is a specialization of duration, the decimal
number of days without padding."

Fixes fmtlib#3643.
  • Loading branch information
intelfx committed Dec 1, 2023
1 parent 99b9fbf commit 2015800
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 1 deletion.
8 changes: 7 additions & 1 deletion include/fmt/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -1622,6 +1622,7 @@ struct chrono_format_checker : null_chrono_spec_handler<chrono_format_checker> {

template <typename Char>
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
FMT_CONSTEXPR void on_day_of_year() {}
FMT_CONSTEXPR void on_24_hour(numeric_system, pad_type) {}
FMT_CONSTEXPR void on_12_hour(numeric_system, pad_type) {}
FMT_CONSTEXPR void on_minute(numeric_system, pad_type) {}
Expand Down Expand Up @@ -1806,6 +1807,7 @@ struct chrono_formatter {
return true;
}

Rep days() const { return static_cast<Rep>(s.count() / 86400); }
Rep hour() const { return static_cast<Rep>(mod((s.count() / 3600), 24)); }

Rep hour12() const {
Expand Down Expand Up @@ -1884,10 +1886,14 @@ struct chrono_formatter {
void on_dec0_week_of_year(numeric_system) {}
void on_dec1_week_of_year(numeric_system) {}
void on_iso_week_of_year(numeric_system) {}
void on_day_of_year() {}
void on_day_of_month(numeric_system) {}
void on_day_of_month_space(numeric_system) {}

void on_day_of_year() {
if (handle_nan_inf()) return;
return write(days(), 0);
}

void on_24_hour(numeric_system ns, pad_type pad) {
if (handle_nan_inf()) return;

Expand Down
10 changes: 10 additions & 0 deletions test/chrono-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ using testing::Contains;
# define FMT_HAS_C99_STRFTIME 1
#endif

#if !(defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907L)
using days = std::chrono::duration<std::chrono::hours::rep, std::ratio<86400>>;
#endif

auto make_tm() -> std::tm {
auto time = std::tm();
time.tm_mday = 1;
Expand Down Expand Up @@ -533,6 +537,12 @@ TEST(chrono_test, format_specs) {
EXPECT_EQ("12", fmt::format("{:%I}", std::chrono::hours(24)));
EXPECT_EQ("04", fmt::format("{:%I}", std::chrono::hours(4)));
EXPECT_EQ("02", fmt::format("{:%I}", std::chrono::hours(14)));
# if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907L
EXPECT_EQ("12345", fmt::format("{:%j}", std::chrono::days(12345)));
# else
EXPECT_EQ("12345", fmt::format("{:%j}", days(12345)));
# endif
EXPECT_EQ("12345", fmt::format("{:%j}", std::chrono::hours(12345*24+12)));
EXPECT_EQ("03:25:45",
fmt::format("{:%H:%M:%S}", std::chrono::seconds(12345)));
EXPECT_EQ("03:25", fmt::format("{:%R}", std::chrono::seconds(12345)));
Expand Down

0 comments on commit 2015800

Please sign in to comment.