| // { dg-do run { target c++20 } } | |
| // { dg-require-namedlocale "es_ES.ISO8859-1" } | |
| // { dg-require-namedlocale "fr_FR.ISO8859-1" } | |
| // { dg-require-namedlocale "en_US.ISO8859-1" } | |
| // { dg-require-namedlocale "en_US.ISO8859-15" } | |
| // { dg-require-namedlocale "en_US.UTF-8" } | |
| // P2419R2 | |
| // Clarify handling of encodings in localized formatting of chrono types | |
| // Localized date-time strings such as "février" should be converted to UTF-8 | |
| // if the locale uses a different encoding. | |
| #include <chrono> | |
| #include <format> | |
| #include <locale> | |
| #include <stdio.h> | |
| #include <testsuite_hooks.h> | |
| void | |
| test_ru() | |
| { | |
| bool ok = false; | |
| #if __cpp_exceptions | |
| std::locale loc; | |
| try | |
| { | |
| loc = std::locale("ru_UA.KOI8-U"); | |
| ok = true; | |
| } | |
| catch (const std::runtime_error&) | |
| { | |
| try | |
| { | |
| loc = std::locale("ru_RU.KOI8-R"); | |
| ok = true; | |
| } | |
| catch (const std::runtime_error&) | |
| { | |
| } | |
| } | |
| #endif | |
| if (ok) | |
| { | |
| auto s = std::format(loc, "День недели: {:L}", std::chrono::Monday); | |
| VERIFY( s == "День недели: Пн" || s == "День недели: пн" ); | |
| } | |
| else | |
| puts("NOTE: test_ru(): skipped unsupported locales"); | |
| } | |
| void | |
| test_es() | |
| { | |
| std::locale loc(ISO_8859(1,es_ES)); | |
| auto s = std::format(loc, "Día de la semana: {:L%A %a}", | |
| std::chrono::Wednesday); | |
| if (s.back() == '.') // FreeBSD has this in the %a string | |
| s.pop_back(); | |
| VERIFY( s == "Día de la semana: miércoles mié" ); | |
| } | |
| void | |
| test_fr() | |
| { | |
| std::locale loc(ISO_8859(1,fr_FR)); | |
| auto s = std::format(loc, "Six mois après {0:L%b}, c'est {1:L%B}.", | |
| std::chrono::February, std::chrono::August); | |
| VERIFY( s == "Six mois après févr., c'est août." ); | |
| } | |
| void | |
| test_en() | |
| { | |
| using namespace std::chrono; | |
| for (auto l : {ISO_8859(1,en_US), ISO_8859(15,en_US), "en_US.UTF-8", "C"}) | |
| { | |
| std::locale loc(l); | |
| auto s = std::format(loc, "{:L%b %B %a %A}", sys_days(2024y/July/30)); | |
| VERIFY( s == "Jul July Tue Tuesday" ); | |
| } | |
| } | |
| void | |
| test_locale_imbued() | |
| { | |
| // Custom time_put facet which returns %b string for %Om. | |
| // The %b string will come from io.getloc() which should be | |
| // the formatting locale using by std::format. | |
| struct TimePut : std::time_put<char> | |
| { | |
| iter_type | |
| do_put(iter_type out, std::ios_base& io, char_type fill, const tm* t, | |
| char format, char modifier) const override | |
| { | |
| if (format == 'm' && modifier == 'O') | |
| format = 'b'; | |
| return std::time_put<char>::do_put(out, io, fill, t, format, 0); | |
| } | |
| }; | |
| auto m = std::chrono::March; | |
| std::locale fr(ISO_8859(1,fr_FR)); | |
| std::locale fr2(fr, new TimePut); | |
| auto s1 = std::format(fr2, "{:L%Om}", m); // should be %b in fr_FR locale | |
| VERIFY( s1 == std::format(fr, "{:L}", m) ); | |
| std::locale es(ISO_8859(1,es_ES)); | |
| std::locale es2(es, new TimePut); | |
| auto s2 = std::format(es2, "{:L%Om}", m); // should be %b in es_ES locale | |
| VERIFY( s2 == std::format(es, "{:L}", m) ); | |
| } | |
| int main() | |
| { | |
| test_ru(); | |
| test_es(); | |
| test_fr(); | |
| test_en(); | |
| test_locale_imbued(); | |
| } |