Here are two proposed patches, regarding non-Gregorian calendars in 'date'
(cf. <https://lists.gnu.org/archive/html/bug-gnulib/2025-07/msg00091.html>).

>From 3a7298ccd4c8676f30522745c3cd36d8b1d938cf Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Thu, 17 Jul 2025 16:29:05 +0200
Subject: [PATCH 1/2] date: Force a Gregorian calendar for options --iso-8601
 and --rfc-3339

* src/date.c (show_date_helper): Add a use_c_locale parameter.
(batch_convert): Add a format_in_c_locale parameter.
(main): Set format_in_c_locale to true if any of the options --rfc-3339,
--iso-8601, -R is seen.
---
 src/date.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/src/date.c b/src/date.c
index b55aba757..953962820 100644
--- a/src/date.c
+++ b/src/date.c
@@ -37,7 +37,7 @@
 
 #define AUTHORS proper_name ("David MacKenzie")
 
-static bool show_date_helper (char const *, struct timespec, timezone_t);
+static bool show_date_helper (char const *, bool, struct timespec, timezone_t);
 
 enum Time_spec
 {
@@ -336,7 +336,8 @@ adjust_resolution (char const *format)
    Return true if successful.  */
 
 static bool
-batch_convert (char const *input_filename, char const *format,
+batch_convert (char const *input_filename,
+               char const *format, bool format_in_c_locale,
                timezone_t tz, char const *tzstring)
 {
   bool ok;
@@ -381,7 +382,7 @@ batch_convert (char const *input_filename, char const *format,
         }
       else
         {
-          ok &= show_date_helper (format, when, tz);
+          ok &= show_date_helper (format, format_in_c_locale, when, tz);
         }
     }
 
@@ -402,6 +403,7 @@ main (int argc, char **argv)
   struct timespec when;
   bool set_date = false;
   char const *format = nullptr;
+  bool format_in_c_locale = false;
   bool get_resolution = false;
   char *batch_file = nullptr;
   char *reference = nullptr;
@@ -451,6 +453,7 @@ main (int argc, char **argv)
               XARGMATCH ("--rfc-3339", optarg,
                          time_spec_string + 2, time_spec + 2);
             new_format = rfc_3339_format[i];
+            format_in_c_locale = true;
             break;
           }
         case 'I':
@@ -468,6 +471,7 @@ main (int argc, char **argv)
                ? XARGMATCH ("--iso-8601", optarg, time_spec_string, time_spec)
                : TIME_SPEC_DATE);
             new_format = iso_8601_format[i];
+            format_in_c_locale = true;
             break;
           }
         case 'r':
@@ -475,6 +479,7 @@ main (int argc, char **argv)
           break;
         case 'R':
           new_format = rfc_email_format;
+          format_in_c_locale = true;
           break;
         case 's':
           if (set_datestr)
@@ -578,7 +583,8 @@ main (int argc, char **argv)
   timezone_t tz = tzalloc (tzstring);
 
   if (batch_file != nullptr)
-    ok = batch_convert (batch_file, format_res, tz, tzstring);
+    ok = batch_convert (batch_file, format_res, format_in_c_locale,
+                        tz, tzstring);
   else
     {
       bool valid_date = true;
@@ -643,24 +649,25 @@ main (int argc, char **argv)
             }
         }
 
-      ok &= show_date_helper (format_res, when, tz);
+      ok &= show_date_helper (format_res, format_in_c_locale, when, tz);
     }
 
   main_exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
 }
 
 static bool
-show_date_helper (char const *format, struct timespec when, timezone_t tz)
+show_date_helper (char const *format, bool use_c_locale,
+                  struct timespec when, timezone_t tz)
 {
   if (parse_datetime_flags & PARSE_DATETIME_DEBUG)
     error (0, 0, _("output format: %s"), quote (format));
 
-  if (format == rfc_email_format)
+  if (use_c_locale)
     setlocale (LC_TIME, "C");
 
   bool ok = show_date (format, when, tz);
 
-  if (format == rfc_email_format)
+  if (use_c_locale)
     setlocale (LC_TIME, "");
 
   putchar ('\n');
-- 
2.43.0

>From c9220920335a45c6fdbd9bf0ff2469ddfeb68b96 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Thu, 17 Jul 2025 16:30:57 +0200
Subject: [PATCH 2/2] date: Update documentation regarding non-Gregorian
 calendars

* doc/coreutils.texi (Calendars): New section.
---
 doc/coreutils.texi | 86 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 7fc2db571..0aad90f22 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -16517,6 +16517,7 @@ is not set.  @xref{TZ Variable,, Specifying the Time Zone with
 
 @menu
 * Date format specifiers::         Used in @samp{date '+...'}
+* Calendars::                      Different concepts of year and month.
 * Setting the time::               Changing the system clock.
 * Options for date::               Instead of the current time.
 @detailmenu
@@ -16839,6 +16840,91 @@ width is also present.  Other combinations of flags, field widths and
 modifiers are GNU extensions.
 
 
+@node Calendars
+@subsection Calendars
+
+@cindex calendar
+A calendar is a system that groups some sequences of days into ``months'',
+and some sequences of months into ``years''.
+In most countries, the calendar in use is the Gregorian calendar,
+with months ranging from January (the first month) to December (the 12th month).
+
+@cindex calendars, non-Gregorian
+In some specific countries, other calendars are in effect, and
+GNU @command{date} supports them in its output.
+The calendar depends on the @code{LC_TIME} category of the current locale:
+@itemize
+@item
+In the locale of Thailand (@code{th_TH.UTF-8}),
+the Thai solar calendar is used.
+@item
+In the locale of Iran (@code{fa_IR}),
+the Persian solar Hijri calendar is used.
+@item
+In the locale of Ethiopia (@code{am_ET}),
+the Ethiopian / Ge'ez calendar is used.
+@end itemize
+
+The dates in these calendars look different.
+For example, the day the GNU project was announced:
+@example
+$ LC_ALL=en_US.UTF-8 date +%Y-%m-%d -d 1983-09-27
+1983-09-27
+$ LC_ALL=th_TH.UTF-8 date +%Y-%m-%d -d 1983-09-27
+2526-09-27
+$ LC_ALL=fa_IR date +%Y-%m-%d -d 1983-09-27
+1362-07-05
+$ LC_ALL=am_ET date +%Y-%m-%d -d 1983-09-27
+1976-01-16
+@end example
+
+In these locales, when a non-Gregorian calendar is in use,
+a few date conversion specifiers should not be used,
+because they don't apply in the expected way:
+@itemize
+@item
+@samp{%C} for the century,
+@item
+@samp{%y} for a two-digit year,
+@item
+@samp{%G} and @samp{%g} for a week-based year,
+@item
+@samp{%U}, @samp{%W}, and @samp{%V} for the week in the year,
+@item
+@samp{%j} for the day in the year,
+@item
+and @samp{%D} for the date in U.S.@: formatting convention.
+@end itemize
+
+If you are using one of these locales
+and want to see Gregorian dates nevertheless,
+you can achieve that by
+@enumerate
+@item
+making sure that you use the @code{LANG} environment variable,
+not the @code{LC_ALL} environment variable,
+for specifiying your general locale, and
+@item
+setting the @code{LC_TIME} environment variable to a locale
+that uses the Gregorian calendar.
+@end enumerate
+@noindent
+For example:
+@example
+$ unset LC_ALL
+$ LANG=fa_IR LC_TIME=en_US.UTF-8 date +%Y-%m-%d -d 1983-09-27
+1983-09-27
+@end example
+
+For more information on how to set your locale, see the GNU gettext manual at
+@ifinfo
+@ref{Users,,The User's View,gettext}.
+@end ifinfo
+@ifnotinfo
+@url{https://www.gnu.org/software/gettext/manual/html_node/Users.html}.
+@end ifnotinfo
+
+
 @node Setting the time
 @subsection Setting the time
 
-- 
2.43.0

Reply via email to