libstdc++: Fix localized %c formatting for <chrono> [PR117085]

When formatting a time point with %c we call std::vformat_to using the
formatting locale's D_T_FMT string, but we weren't adding the L option
to the format string. This meant we always interpreted D_T_FMT in the C
locale, instead of using the formatting locale as obviously intended
when %c is used.

libstdc++-v3/ChangeLog:

	PR libstdc++/117085
	* include/bits/chrono_io.h (__formatter_chrono::_M_c): Add L
	option to format string.
	* testsuite/std/time/format.cc: Move to...
	* testsuite/std/time/format/format.cc: ...here.
	* testsuite/std/time/format_localized.cc: Move to...
	* testsuite/std/time/format/localized.cc: ...here.
	* testsuite/std/time/format/pr117085.cc: New test.
This commit is contained in:
Jonathan Wakely 2024-10-11 09:40:38 +01:00 committed by Jonathan Wakely
parent c10b442ee4
commit 4ad697bb7f
No known key found for this signature in database
4 changed files with 27 additions and 6 deletions

View File

@ -893,17 +893,19 @@ namespace __format
// %c Locale's date and time representation.
// %Ec Locale's alternate date and time representation.
basic_string<_CharT> __fmt;
auto __t = _S_floor_seconds(__tt);
locale __loc = _M_locale(__ctx);
const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
const _CharT* __formats[2];
__tp._M_date_time_formats(__formats);
const _CharT* __rep = __formats[__mod];
if (!*__rep) [[unlikely]]
__rep = _GLIBCXX_WIDEN("%a %b %e %T %Y");
basic_string<_CharT> __fmt(_S_empty_spec);
__fmt.insert(1u, 1u, _S_colon);
__fmt.insert(2u, __rep);
if (*__formats[__mod]) [[likely]]
{
__fmt = _GLIBCXX_WIDEN("{:L}");
__fmt.insert(3u, __formats[__mod]);
}
else
__fmt = _GLIBCXX_WIDEN("{:L%a %b %e %T %Y}");
return std::vformat_to(std::move(__out), __loc, __fmt,
std::make_format_args<_FormatContext>(__t));
}

View File

@ -0,0 +1,19 @@
// { dg-do run { target c++20 } }
// { dg-require-namedlocale "fr_FR.ISO8859-1" }
#include <chrono>
#include <locale>
#include <testsuite_hooks.h>
void
test_c()
{
std::locale::global(std::locale(ISO_8859(1,fr_FR)));
auto s = std::format("{:L%c}", std::chrono::sys_seconds());
VERIFY( ! s.starts_with("Thu") );
}
int main()
{
test_c();
}