diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 46590074..cc04243b 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1908,11 +1908,8 @@ struct formatter : private formatter { public: FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + this->set_format(detail::string_literal()); auto it = ctx.begin(), end = ctx.end(); - if (it != end && *it == 'L') { - ++it; - this->set_localized(); - } use_tm_formatter_ = it != end && *it != '}'; return use_tm_formatter_ ? formatter::parse(ctx) : it; } @@ -1922,7 +1919,7 @@ struct formatter : private formatter { auto time = std::tm(); time.tm_wday = static_cast(wd.c_encoding()); if (use_tm_formatter_) return formatter::format(time, ctx); - detail::get_locale loc(this->localized(), ctx.locale()); + detail::get_locale loc(false, ctx.locale()); auto w = detail::tm_writer(loc, ctx.out(), time); w.on_abbr_weekday(); return w.out(); @@ -1936,6 +1933,7 @@ struct formatter : private formatter { public: FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + this->set_format(detail::string_literal()); auto it = ctx.begin(), end = ctx.end(); use_tm_formatter_ = it != end && *it != '}'; return use_tm_formatter_ ? formatter::parse(ctx) : it; @@ -1960,11 +1958,8 @@ struct formatter : private formatter { public: FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + this->set_format(detail::string_literal()); auto it = ctx.begin(), end = ctx.end(); - if (it != end && *it == 'L') { - ++it; - this->set_localized(); - } use_tm_formatter_ = it != end && *it != '}'; return use_tm_formatter_ ? formatter::parse(ctx) : it; } @@ -1974,7 +1969,7 @@ struct formatter : private formatter { auto time = std::tm(); time.tm_mon = static_cast(static_cast(m)) - 1; if (use_tm_formatter_) return formatter::format(time, ctx); - detail::get_locale loc(this->localized(), ctx.locale()); + detail::get_locale loc(false, ctx.locale()); auto w = detail::tm_writer(loc, ctx.out(), time); w.on_abbr_month(); return w.out(); @@ -1988,6 +1983,7 @@ struct formatter : private formatter { public: FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + this->set_format(detail::string_literal()); auto it = ctx.begin(), end = ctx.end(); use_tm_formatter_ = it != end && *it != '}'; return use_tm_formatter_ ? formatter::parse(ctx) : it; @@ -2012,6 +2008,7 @@ struct formatter : private formatter { public: FMT_CONSTEXPR auto parse(parse_context& ctx) -> const Char* { + this->set_format(detail::string_literal()); auto it = ctx.begin(), end = ctx.end(); use_tm_formatter_ = it != end && *it != '}'; return use_tm_formatter_ ? formatter::parse(ctx) : it; @@ -2106,8 +2103,7 @@ template struct formatter { detail::string_literal(); protected: - auto localized() const -> bool { return specs_.localized(); } - FMT_CONSTEXPR void set_localized() { specs_.set_localized(); } + FMT_CONSTEXPR void set_format(basic_string_view fmt) { fmt_ = fmt; } FMT_CONSTEXPR auto do_parse(parse_context& ctx, bool has_timezone) -> const Char* { diff --git a/test/chrono-test.cc b/test/chrono-test.cc index b7a4e59a..f2875f0a 100644 --- a/test/chrono-test.cc +++ b/test/chrono-test.cc @@ -994,6 +994,57 @@ TEST(chrono_test, out_of_range) { EXPECT_THROW((void)fmt::format("{:%j}", fd), fmt::format_error); } +template +void check_calendar_padding(T value, const char* expected, + const char* chrono_format) { + EXPECT_EQ(expected, fmt::format("{}", value)); + EXPECT_EQ(expected, fmt::format("{:}", value)); + EXPECT_EQ(fmt::format("{:15}", expected), fmt::format("{:15}", value)); + EXPECT_EQ(fmt::format("{:<15}", expected), fmt::format("{:<15}", value)); + EXPECT_EQ(fmt::format("{:>15}", expected), fmt::format("{:>15}", value)); + EXPECT_EQ(fmt::format("{:*^15}", expected), fmt::format("{:*^15}", value)); + EXPECT_EQ(fmt::format("{:%>15}", expected), fmt::format("{:%>15}", value)); + EXPECT_EQ(fmt::format("{:L>15}", expected), fmt::format("{:L>15}", value)); + EXPECT_EQ(fmt::format("{:>15}", expected), fmt::format("{:>{}}", value, 15)); + EXPECT_EQ(expected, fmt::format("{:1}", value)); + auto explicit_format = fmt::format("{{:*^15{}}}", chrono_format); + auto unpadded_format = fmt::format("{{:{}}}", chrono_format); + EXPECT_EQ(fmt::format("{:*^15}", + fmt::format(runtime(unpadded_format), value)), + fmt::format(runtime(explicit_format), value)); + EXPECT_THROW((void)fmt::format(runtime("{:>{}}"), value, -1), + fmt::format_error); +} + +TEST(chrono_test, calendar_padding) { + check_calendar_padding(fmt::day(5), "05", "%d"); + check_calendar_padding(fmt::month(1), "Jan", "%B"); + check_calendar_padding(fmt::year(2024), "2024", "%y"); + check_calendar_padding(fmt::weekday(6), "Sat", "%A"); + check_calendar_padding( + fmt::year_month_day(fmt::year(2024), fmt::month(1), fmt::day(5)), + "2024-01-05", "%Y/%m/%d"); +} + +template void check_localized_calendar_padding(T value) { + auto loc = get_locale("es_ES.UTF-8"); + auto expected = fmt::format(loc, "{:L}", value); + EXPECT_EQ(fmt::format("{:*>15}", expected), + fmt::format(loc, "{:*>15L}", value)); + EXPECT_EQ(fmt::format("{:>15}", expected), + fmt::format(loc, "{:>{}L}", value, 15)); +} + +TEST(chrono_test, localized_calendar_padding) { + check_localized_calendar_padding(fmt::month(1)); + check_localized_calendar_padding(fmt::weekday(6)); + auto loc = get_locale("es_ES.UTF-8"); + EXPECT_EQ(fmt::format("{:>15}", fmt::format(loc, "{:L%B}", fmt::month(1))), + fmt::format(loc, "{:>15L%B}", fmt::month(1))); + EXPECT_EQ(fmt::format("{:>15}", fmt::format(loc, "{:L%A}", fmt::weekday(6))), + fmt::format(loc, "{:>15L%A}", fmt::weekday(6))); +} + TEST(chrono_test, year_month_day) { auto loc = get_locale("es_ES.UTF-8"); std::locale::global(loc);