From 18440ef81b20aa79926c4f634ddad78269096220 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Thu, 28 Oct 2021 21:11:27 +0500 Subject: [PATCH] Use predefined names and formats for C-locale --- include/fmt/chrono.h | 116 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 106 insertions(+), 10 deletions(-) diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 0c38e02e..0ac173ff 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -1393,11 +1393,38 @@ struct tm_format_checker : null_chrono_spec_handler { FMT_CONSTEXPR void on_tz_name() {} }; +inline const char* tm_wday_full_name(int wday) { + static constexpr const char* full_name_list[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday"}; + return wday >= 0 && wday <= 6 ? full_name_list[wday] : "?"; +} +inline const char* tm_wday_short_name(int wday) { + static constexpr const char* short_name_list[] = {"Sun", "Mon", "Tue", "Wed", + "Thu", "Fri", "Sat"}; + return wday >= 0 && wday <= 6 ? short_name_list[wday] : "???"; +} + +inline const char* tm_mon_full_name(int mon) { + static constexpr const char* full_name_list[] = { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}; + return mon >= 0 && mon <= 11 ? full_name_list[mon] : "?"; +} +inline const char* tm_mon_short_name(int mon) { + static constexpr const char* short_name_list[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + }; + return mon >= 0 && mon <= 11 ? short_name_list[mon] : "???"; +} + template class tm_writer { private: static constexpr int days_per_week = 7; const std::locale& loc_; + const bool is_classic_; OutputIt out_; const std::tm& tm_; @@ -1514,7 +1541,10 @@ template class tm_writer { public: explicit tm_writer(const std::locale& loc, OutputIt out, const std::tm& tm) - : loc_(loc), out_(out), tm_(tm) {} + : loc_(loc), + is_classic_(loc_ == std::locale::classic()), + out_(out), + tm_(tm) {} OutputIt out() const { return out_; } @@ -1522,8 +1552,18 @@ template class tm_writer { out_ = copy_str(begin, end, out_); } - void on_abbr_weekday() { format_localized('a'); } - void on_full_weekday() { format_localized('A'); } + void on_abbr_weekday() { + if (is_classic_) + out_ = write(out_, tm_wday_short_name(tm_wday())); + else + format_localized('a'); + } + void on_full_weekday() { + if (is_classic_) + out_ = write(out_, tm_wday_full_name(tm_wday())); + else + format_localized('A'); + } void on_dec0_weekday(numeric_system ns) { if (ns != numeric_system::standard) return format_localized('w', 'O'); write1(tm_wday()); @@ -1534,17 +1574,51 @@ template class tm_writer { write1(wday == 0 ? days_per_week : wday); } - void on_abbr_month() { format_localized('b'); } - void on_full_month() { format_localized('B'); } + void on_abbr_month() { + if (is_classic_) + out_ = write(out_, tm_mon_short_name(tm_mon())); + else + format_localized('b'); + } + void on_full_month() { + if (is_classic_) + out_ = write(out_, tm_mon_full_name(tm_mon())); + else + format_localized('B'); + } void on_datetime(numeric_system ns) { - format_localized('c', ns == numeric_system::standard ? '\0' : 'E'); + if (is_classic_) { +#ifdef _WIN32 + on_us_date(); + *out_++ = ' '; + on_iso_time(); +#else + on_abbr_weekday(); + *out_++ = ' '; + on_abbr_month(); + *out_++ = ' '; + on_day_of_month_space(numeric_system::standard); + *out_++ = ' '; + on_iso_time(); + *out_++ = ' '; + on_year(numeric_system::standard); +#endif + } else { + format_localized('c', ns == numeric_system::standard ? '\0' : 'E'); + } } void on_loc_date(numeric_system ns) { - format_localized('x', ns == numeric_system::standard ? '\0' : 'E'); + if (is_classic_) + on_us_date(); + else + format_localized('x', ns == numeric_system::standard ? '\0' : 'E'); } void on_loc_time(numeric_system ns) { - format_localized('X', ns == numeric_system::standard ? '\0' : 'E'); + if (is_classic_) + on_iso_time(); + else + format_localized('X', ns == numeric_system::standard ? '\0' : 'E'); } void on_us_date() { char buf[8]; @@ -1658,7 +1732,22 @@ template class tm_writer { write2(tm_sec()); } - void on_12_hour_time() { format_localized('r'); } + void on_12_hour_time() { + if (is_classic_) { +#ifdef _WIN32 + on_iso_time(); +#else + char buf[8]; + write_digit2_separated(buf, to_unsigned(tm_hour12()), + to_unsigned(tm_min()), to_unsigned(tm_sec()), ':'); + out_ = copy_str(std::begin(buf), std::end(buf), out_); + *out_++ = ' '; + on_am_pm(); +#endif + } else { + format_localized('r'); + } + } void on_24_hour_time() { write2(tm_hour()); *out_++ = ':'; @@ -1671,7 +1760,14 @@ template class tm_writer { out_ = copy_str(std::begin(buf), std::end(buf), out_); } - void on_am_pm() { format_localized('p'); } + void on_am_pm() { + if (is_classic_) { + *out_++ = tm_hour() < 12 ? 'A' : 'P'; + *out_++ = 'M'; + } else { + format_localized('p'); + } + } // These apply to chrono durations but not tm. void on_duration_value() {}