Re: missing possibility to use alternative translated month names in to_char function

From: Bernd Reiß <bd_reiss(at)gmx(dot)at>
To: Pavel Stehule <pavel(dot)stehule(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: missing possibility to use alternative translated month names in to_char function
Date: 2026-08-12 21:51:36
Message-ID: 78010782-fe08-402c-83e9-5239f6d322a3@gmx.at
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi Pavel,

I've looked into your patch and provide the review below.

Threads I found touching TMMONTH + glibc:
https://www.postgresql.org/message-id/CALSKcLS3Zi4o0Ak5pNOheqmAiKWcez%2B%2BqwKvyPccvOz2v62QZQ%40mail.gmail.com
(Russian)
https://www.postgresql.org/message-id/14717914.JAiOoc7IO7%40utklippan

I did not come across a prior thread proposing an implementation of what
this patch does. Worth noting that in the utklippan thread above, Tom Lane
suggested that a new format code or modifier would be the palatable way to
address a similar problem.

Contents & Purpose
==================
This patch gives users control over the case (genitive vs. nominative)
to use when pulling localized month names from  glibc via the function
to_char(). The author proposes to add a TAMMONTH option for formatting
dates.

Intended behaviour: TMMONTH uses the genitive form (if applicable to the
language; equivalent to %B) while TAMMONTH uses the nominative
(equivalent to %OB).

The patch contains regression test cases. It also adds a corresponding
entry in the documentation.

Initial Run
===========
The patch applies cleanly to HEAD. The regression tests all pass
successfully against the new patch, but fail against pre-patched HEAD,
so the test cases are sane and do cover the new behavior.

Manual Testing
==============
The provided examples all work fine. However, I realized that the
shortened form TAMMON falls back to English instead of honouring
lc_time:

postgres=# set lc_time to 'de_DE.UTF-8';
SET
postgres=# SELECT to_char(date '2026-03-01'::date, 'DD TMMON');
SELECT to_char(date '2026-03-01'::date, 'DD TAMMON');
 to_char
---------
 01 MÄR
(1 row)

 to_char
---------
 01 MAR
(1 row)

It looks like only the full-month cases (DCH_MONTH/Month/month) were
wired up for
TAM; the abbreviated cases (DCH_MON/Mon/mon) still test IS_SUFFIX_TM
only, so TAM
silently drops to the default English abbreviation. I'd expect TAMMON to
stay
localized.

Code Review
===========
I am not sure if this condition can be ever true:

+ if (IS_SUFFIX_TM(n->suffix) && IS_SUFFIX_TAM(n->suffix))

In case this is not possible the subsequent error message will never be
thrown and the whole block is dead code.

However, if there is a reason for this check, it would be nice to
have a comment mention it.

One thing I am not entirely sure about is this line:

+ if (strftime_l(bufptr, MAX_L10N_DATA, "%OB", timeinfo, locale) <= 0)
+     strftimefail = true;

As far as I checked %OB is not supported on Windows:

https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strftime-wcsftime-strftime-l-wcsftime-l?view=msvc-170

I was, however, not able to confirm this on a Windows machine right now.
I might be able to do so on the weekend.

However, the same problem exists with older glibc versions not supporting
%OB. As far as I understand strftime_l this will lead to it returning 0 and
therefore setting strftimefail to true always. Since this if statement
is evaluated
unconditionally I expect this to also influence the behaviour of TM.

Nitpicking & Conclusion
=======================
I feel like the documentation could explicitly mention the difference
between TMMONTH and TAMMONTH (i.e., mentioning genitive and nominative
like the Locale docs you mentioned do). I also think it would be
beneficial to
mention that this linguistic detail is specific to certain languages.

Furthermore, in general I feel like the code could have more comments.
The single comment /* TAM suffix - localized alternative month name */
I would rather put outside the if-else block and set TAM directly in
relation
to TM there.

All in all, this topic seems to have been a pain point for many people
as the discussion threads mentioned in the beginning attest. The patch
offers a solution to make glibc behaviour more predictable for users.
I see a very real use case here.

Best
Bernd

On 12/08/2026 09:13, Pavel Stehule wrote:
> Hi
>
> út 11. 8. 2026 v 17:14 odesílatel Pavel Stehule
> <pavel(dot)stehule(at)gmail(dot)com> napsal:
>
>
>
> út 11. 8. 2026 v 17:06 odesílatel Pavel Stehule
> <pavel(dot)stehule(at)gmail(dot)com> napsal:
>
> Hi
>
> My customer reported an interesting issue. He needs translated
> month name, and then he use
> to_char(current_date, 'tmmonth');
>
> Unfortunately, glibc returns nouns in the genitive case
> instead of the nominative case.
>
> This is a glibc feature from the 2.28 release. Genitive case
> makes sense, when the result holds a day, but without it, it
> is messy.
>
> glibc has alternative month names, that can be taken by usage
> placeholder '%OB'  of function strftime.
> https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html
> - see alt_mon.
>
> Can we enhance prefixes (maybe tmo) to be possible to use
> alternative names?
>
>
> example:
>
> pavel(at)nemesis:~/src/orafce$ date +'%B'
> srpna
> pavel(at)nemesis:~/src/orafce$ date +'%OB'
> srpen
> pavel(at)nemesis:~/src/orafce$ LANG=C date +'%OB'
> August
>
>
> attached patch that implements 'TAM' modifier for data/timestamp
> formatting
>
> Regards
>
> Pavel
>
>
> Regards
>
> Pavel
>
>
>
>
>

In response to

Browse pgsql-hackers by date

  From Date Subject
Previous Message Sami Imseih 2026-08-12 21:45:27 Re: Report index currently being vacuumed in pg_stat_progress_vacuum