diff mbox series

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

Message ID 20241011145300.1322712-1-jwakely@redhat.com
State New
Headers show
Series [committed] libstdc++: Fix localized %c formatting for <chrono> [PR117085] | expand

Commit Message

Jonathan Wakely Oct. 11, 2024, 2:52 p.m. UTC
Tested x86_64-linux. Pushed to trunk.

-- >8 --

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.
---
 libstdc++-v3/include/bits/chrono_io.h         | 14 ++++++++------
 .../testsuite/std/time/{ => format}/format.cc |  0
 .../localized.cc}                             |  0
 .../testsuite/std/time/format/pr117085.cc     | 19 +++++++++++++++++++
 4 files changed, 27 insertions(+), 6 deletions(-)
 rename libstdc++-v3/testsuite/std/time/{ => format}/format.cc (100%)
 rename libstdc++-v3/testsuite/std/time/{format_localized.cc => format/localized.cc} (100%)
 create mode 100644 libstdc++-v3/testsuite/std/time/format/pr117085.cc
diff mbox series

Patch

diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index 652e88ffe3a..8c026586d4c 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -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));
 	}
diff --git a/libstdc++-v3/testsuite/std/time/format.cc b/libstdc++-v3/testsuite/std/time/format/format.cc
similarity index 100%
rename from libstdc++-v3/testsuite/std/time/format.cc
rename to libstdc++-v3/testsuite/std/time/format/format.cc
diff --git a/libstdc++-v3/testsuite/std/time/format_localized.cc b/libstdc++-v3/testsuite/std/time/format/localized.cc
similarity index 100%
rename from libstdc++-v3/testsuite/std/time/format_localized.cc
rename to libstdc++-v3/testsuite/std/time/format/localized.cc
diff --git a/libstdc++-v3/testsuite/std/time/format/pr117085.cc b/libstdc++-v3/testsuite/std/time/format/pr117085.cc
new file mode 100644
index 00000000000..99ef8389995
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/time/format/pr117085.cc
@@ -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();
+}