]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Use formatting locale for std::time_put formats
authorJonathan Wakely <jwakely@redhat.com>
Wed, 19 Mar 2025 19:38:15 +0000 (19:38 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 21 Mar 2025 10:28:11 +0000 (10:28 +0000)
When using std::time_put to format a chrono value, we should imbue the
formatting locale into the stream. This ensures that when
std::time_put::do_put uses a ctype or __timepunct facet from the locale,
it gets the correct facets.

libstdc++-v3/ChangeLog:

* include/bits/chrono_io.h (__formatter_chrono::_M_locale_fmt):
Imbue locale into ostringstream.
* testsuite/std/time/format/localized.cc: Check that correct
locale is used for call to time_put::put.

Reviewed-by: Tomasz KamiƄski <tkaminsk@redhat.com>
libstdc++-v3/include/bits/chrono_io.h
libstdc++-v3/testsuite/std/time/format/localized.cc

index c16b555df2909da1e8649a655638a1e28abf0a59..55ebd4ee06108de1da72447d567ad39f1b64f193 100644 (file)
@@ -1697,6 +1697,7 @@ namespace __format
                      char __fmt, char __mod) const
        {
          basic_ostringstream<_CharT> __os;
+         __os.imbue(__loc);
          const auto& __tp = use_facet<time_put<_CharT>>(__loc);
          __tp.put(__os, __os, _S_space, &__tm, __fmt, __mod);
          if (__os)
index 393d0d200e459baf3f55a2ad70267d3a45aa7ded..7fde97f9ae1554a0eeb4eb1af185431e59bcd17f 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <chrono>
 #include <format>
+#include <locale>
 #include <stdio.h>
 #include <testsuite_hooks.h>
 
@@ -81,10 +82,42 @@ test_en()
     }
 }
 
+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();
 }