On 15/07/2025 11:45, Bruno Haible via Gnulib discussion list wrote:
This patch adds proper support for the non-Gregorian calendars in use in
   - Thailand,
   - Iran,
   - Ethiopia,
to the 'nstrftime' module and, with it (automatically) to the GNU coreutils
'date' program (for output).

Why is this needed? Because these countries don't use the Gregorian calendar
primarily.

   * Thailand:
     https://en.wikipedia.org/wiki/Thai_calendar says
     "In Thailand, two main calendar systems are used alongside each other:
      the Thai solar calendar, based on the Gregorian calendar and used for
      official and most day-to-day purposes, and ..."

   * Iran:
     https://en.wikipedia.org/wiki/Solar_Hijri_calendar says
     "The Solar Hijri calendar is the official calendar of Iran."
     https://en.wikipedia.org/wiki/Solar_Hijri_calendar#Iran says
     "The present Iranian calendar was legally adopted on 31 March 1925"
     
https://en.wikipedia.org/wiki/Iranian_calendars#Modern_calendar:_Solar_Hijri_(SH)
     says "The present Iranian calendar was legally adopted on 31 March 1925"

   * Ethiopia:
     https://en.wikipedia.org/wiki/Ethiopian_calendar says it
     "is the official state civil calendar of Ethiopia".

And because glibc does not support it well. The effects of the change in a
system with libc:

* Thailand locale:

$ LC_ALL=th_TH.UTF-8 date-9.7
จ. 14 ก.ค. 2568 19:35:16 CEST
$ LC_ALL=th_TH.UTF-8 src/date
จ. 14 ก.ค. 2568 19:34:44 CEST
$ LC_ALL=th_TH.UTF-8 date-9.7 +%Y
2025
$ LC_ALL=th_TH.UTF-8 src/date +%Y
2568

You can see that glibc's strftime() supports the Thai calendar for
_some_ format directives, but not for others. In particular, it
doesn't for '%Y'.

* Iran locale:

$ LC_ALL=fa_IR date-9.7
دوشنبه ۱۴ ژوئیه ۲۵، ساعت ۱۹:۳۷:۵۱ (CEST)‬
$ LC_ALL=fa_IR src/date
دوشنبه ۲۳ تیر ۲۵، ساعت ۱۹:۳۸:۱ (CEST)‬
$ LC_ALL=fa_IR date-9.7 +%Y-%m-%d
2025-07-14
$ LC_ALL=fa_IR src/date +%Y-%m-%d
1404-04-23

You can see that glibc's strftime() supports the Farsi digits but
not the Iranian calendar.

* Ethiopia locale:

$ LC_ALL=am_ET date-9.7
ሰኞ፣ ጁላይ 14 ቀን  7:40:21 ከሰዓት CEST 2025 ዓ/ም
$ LC_ALL=am_ET src/date
ሰኞ፣ ሐምሌ  7 ቀን  7:40:24 ከሰዓት CEST 2017 ዓ/ም
$ LC_ALL=am_ET date-9.7 +%Y-%m-%d
2025-07-14
$ LC_ALL=am_ET src/date +%Y-%m-%d
2017-11-07

You can see that glibc's strftime() prints wrong year, month, and day
values.

The ISO C 23 § 7.29.3.5 and POSIX
https://pubs.opengroup.org/onlinepubs/9799919799/functions/strftime.html
specifications specify an "alternative" choice feature. This code does
*NOT* make use of this "alternative" API.
It's better if the use of the specific calendar turns on the
particular years, months names and numbers, days etc. all at once.
Rationale:
   - Because the "alternatives" approach that makes it too easy to produce
     nonsensical output (as shown with %Y in the Thai locale, above).
   - Because there is no documentation anywhere what "alternative" actually
     means.
   - Because in ISO C and POSIX the month number is specified to be in the
     range 1..12, but some calendars (the Ethiopian calendar) have month
     numbers 1..13.
   - Because the month number to month name mapping may depend on the era
     in some calendars (the Thai calendar).

So, the code is careful not to mix Gregorian time elements (in 'struct tm')
with non-Gregorian time elements (in 'struct calendar_date').

Pádraig, you may add something like the following as a coreutils/NEWS entry:

   'date' now outputs dates in the country's native calendar for the Iranian
   locale (fa_IR) and for the Ethiopian locale (am_ET), and also does so more
   consistently for the Thailand locale (th_TH.UTF-8).

Sure I'll add that.

Off the top of your head might there be any platform general tests
that could be added to coreutils?

thanks,
Padraig

Reply via email to