blob: 7fde97f9ae1554a0eeb4eb1af185431e59bcd17f [file] [log] [blame]
// { 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();
}