mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-08 03:43:13 +00:00
Implemented fmt::day, fmt::month, fmt::year and related unit tests (#3906)
This commit is contained in:
parent
88620e53a4
commit
74a187288b
@ -2036,17 +2036,52 @@ struct chrono_formatter {
|
||||
|
||||
#if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907
|
||||
using weekday = std::chrono::weekday;
|
||||
using day = std::chrono::day;
|
||||
using month = std::chrono::month;
|
||||
using year = std::chrono::year;
|
||||
#else
|
||||
// A fallback version of weekday.
|
||||
class weekday {
|
||||
private:
|
||||
unsigned char value;
|
||||
unsigned char value_;
|
||||
|
||||
public:
|
||||
weekday() = default;
|
||||
explicit constexpr weekday(unsigned wd) noexcept
|
||||
: value(static_cast<unsigned char>(wd != 7 ? wd : 0)) {}
|
||||
constexpr auto c_encoding() const noexcept -> unsigned { return value; }
|
||||
constexpr explicit weekday(unsigned wd) noexcept
|
||||
: value_(static_cast<unsigned char>(wd != 7 ? wd : 0)) {}
|
||||
constexpr auto c_encoding() const noexcept -> unsigned { return value_; }
|
||||
};
|
||||
|
||||
class day {
|
||||
private:
|
||||
unsigned char value_;
|
||||
|
||||
public:
|
||||
day() = default;
|
||||
constexpr explicit day(unsigned d) noexcept
|
||||
: value_(static_cast<unsigned char>(d)) {}
|
||||
constexpr explicit operator unsigned() const noexcept { return value_; }
|
||||
};
|
||||
|
||||
class month {
|
||||
private:
|
||||
unsigned char value_;
|
||||
|
||||
public:
|
||||
month() = default;
|
||||
constexpr explicit month(unsigned m) noexcept
|
||||
: value_(static_cast<unsigned char>(m)) {}
|
||||
constexpr explicit operator unsigned() const noexcept { return value_; }
|
||||
};
|
||||
|
||||
class year {
|
||||
private:
|
||||
int value_;
|
||||
|
||||
public:
|
||||
year() = default;
|
||||
constexpr explicit year(int y) noexcept : value_(y) {}
|
||||
constexpr explicit operator int() const noexcept { return value_; }
|
||||
};
|
||||
|
||||
class year_month_day {};
|
||||
@ -2079,6 +2114,68 @@ template <typename Char> struct formatter<weekday, Char> {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char> struct formatter<day, Char> {
|
||||
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
||||
-> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(day d, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
auto time = std::tm();
|
||||
time.tm_mday = static_cast<int>(static_cast<unsigned>(d));
|
||||
detail::get_locale loc(false, ctx.locale());
|
||||
auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);
|
||||
w.on_day_of_month(detail::numeric_system::standard);
|
||||
return w.out();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char> struct formatter<month, Char> {
|
||||
private:
|
||||
bool localized = false;
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
||||
-> decltype(ctx.begin()) {
|
||||
auto begin = ctx.begin(), end = ctx.end();
|
||||
if (begin != end && *begin == 'L') {
|
||||
++begin;
|
||||
localized = true;
|
||||
}
|
||||
return begin;
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(month m, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
auto time = std::tm();
|
||||
// std::chrono::month has a range of 1-12, std::tm requires 0-11
|
||||
time.tm_mon = static_cast<int>(static_cast<unsigned>(m)) - 1;
|
||||
detail::get_locale loc(localized, ctx.locale());
|
||||
auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);
|
||||
w.on_abbr_month();
|
||||
return w.out();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char> struct formatter<year, Char> {
|
||||
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
||||
-> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(year y, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
auto time = std::tm();
|
||||
// std::tm::tm_year is years since 1900
|
||||
time.tm_year = static_cast<int>(y) - 1900;
|
||||
detail::get_locale loc(true, ctx.locale());
|
||||
auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);
|
||||
w.on_year(detail::numeric_system::standard);
|
||||
return w.out();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Rep, typename Period, typename Char>
|
||||
struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
private:
|
||||
|
@ -1011,4 +1011,16 @@ TEST(chrono_test, glibc_extensions) {
|
||||
TEST(chrono_test, out_of_range) {
|
||||
auto d = std::chrono::duration<unsigned long, std::giga>(538976288);
|
||||
EXPECT_THROW((void)fmt::format("{:%j}", d), fmt::format_error);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(chrono_test, year_month_day) {
|
||||
auto loc = get_locale("es_ES.UTF-8");
|
||||
std::locale::global(loc);
|
||||
auto year = fmt::year(2024);
|
||||
auto month = fmt::month(1);
|
||||
auto day = fmt::day(1);
|
||||
|
||||
EXPECT_EQ(fmt::format("{}", year), "2024");
|
||||
EXPECT_EQ(fmt::format("{}", month), "Jan");
|
||||
EXPECT_EQ(fmt::format("{}", day), "01");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user