]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
date: fix calendar-related test failures on macOS and OpenBSD
authorBruno Haible <bruno@clisp.org>
Thu, 31 Jul 2025 16:42:02 +0000 (18:42 +0200)
committerCollin Funk <collin.funk1@gmail.com>
Fri, 1 Aug 2025 04:54:49 +0000 (21:54 -0700)
* bootstrap.conf (gnulib_modules): Add xsetenv.
* src/date.c: Include xsetenv.h.
(set_LC_TIME): New function.
(show_date_helper): Call set_LC_TIME instead of setlocale.
* po/POTFILES.in: Add lib/xsetenv.c.
Fixes https://bugs.gnu.org/79118

bootstrap.conf
po/POTFILES.in
src/date.c

index 8488038a7cc0026865d7c1f9cbc3971d4069b690..99d4df90bfdb9085133f44aa3d5cd0b7330d4750 100644 (file)
@@ -309,6 +309,7 @@ gnulib_modules="
   xprintf
   xprintf-posix
   xreadlink
+  xsetenv
   xstrtod
   xstrtoimax
   xstrtol
index 95e3253368bfabaf5aa73c9497b3c782c6378eba..8e8fb056c76ca7c5e81f6606d28f4b6c57e8d6ac 100644 (file)
@@ -29,6 +29,7 @@ lib/xalloc-die.c
 lib/xbinary-io.c
 lib/xmemcoll.c
 lib/xprintf.c
+lib/xsetenv.c
 lib/xstrtol-error.c
 
 # Package source files
index 6979399c3c21856c5c8432cd10423682429921d3..4a8dabc2e1326f2d7356d71ae21e7b1484a22760 100644 (file)
@@ -31,6 +31,7 @@
 #include "quote.h"
 #include "show-date.h"
 #include "stat-time.h"
+#include "xsetenv.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
 #define PROGRAM_NAME "date"
@@ -330,6 +331,48 @@ adjust_resolution (char const *format)
   return copy;
 }
 
+/* Set the LC_TIME category of the current locale.
+   Return the previous value of the LC_TIME category, as a freshly allocated
+   string or null.  */
+
+static char *
+set_LC_TIME (char const *locale)
+{
+  /* It is not sufficient to do
+       setlocale (LC_TIME, locale);
+     because show_date relies on fprintftime, that uses the Gnulib module
+     'localename-unsafe', that looks at the values of the environment variables
+     (in order to distinguish the default locale from the C locale on platforms
+     like macOS).  */
+  char const *all = getenv ("LC_ALL");
+  if (all != nullptr && *all != '\0')
+    {
+      /* Setting LC_TIME when LC_ALL is set would have no effect.  Therefore we
+         have to unset LC_ALL and sets its value to all locale categories that
+         are relevant for this program.  */
+      xsetenv ("LC_CTYPE", all, 1);          /* definitely needed */
+      xsetenv ("LC_TIME", all, 1);           /* definitely needed */
+      xsetenv ("LC_MESSAGES", all, 1);       /* definitely needed */
+      xsetenv ("LC_NUMERIC", all, 1);        /* possibly needed */
+      /* xsetenv ("LC_COLLATE", all, 1); */  /* not needed */
+      /* xsetenv ("LC_MONETARY", all, 1); */ /* not needed */
+      unsetenv ("LC_ALL");
+    }
+
+  /* Set LC_TIME as an environment variable.  */
+  char const *value = getenv ("LC_TIME");
+  char *ret = (value == nullptr || *value == '\0' ? nullptr : xstrdup (value));
+  if (locale != nullptr)
+    xsetenv ("LC_TIME", locale, 1);
+  else
+    unsetenv ("LC_TIME");
+
+  /* Update the current locale accordingly.  */
+  setlocale (LC_TIME, "");
+
+  return ret;
+}
+
 /* Parse each line in INPUT_FILENAME as with --date and display each
    resulting time and date.  If the file cannot be opened, tell why
    then exit.  Issue a diagnostic for any lines that cannot be parsed.
@@ -662,13 +705,17 @@ show_date_helper (char const *format, bool use_c_locale,
   if (parse_datetime_flags & PARSE_DATETIME_DEBUG)
     error (0, 0, _("output format: %s"), quote (format));
 
+  bool ok;
   if (use_c_locale)
-    setlocale (LC_TIME, "C");
-
-  bool ok = show_date (format, when, tz);
-
-  if (use_c_locale)
-    setlocale (LC_TIME, "");
+    {
+      char *old_locale_category = set_LC_TIME ("C");
+      ok = show_date (format, when, tz);
+      char *new_locale_category = set_LC_TIME (old_locale_category);
+      free (new_locale_category);
+      free (old_locale_category);
+    }
+  else
+    ok = show_date (format, when, tz);
 
   putchar ('\n');
   return ok;