missing possibility to use alternative translated month names in to_char function

Started by Pavel Stehule12 days ago16 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

appliessuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253378
psql -h localhost -U postgres

Built from patchset v12 (message #12), August 23, 2026 at 05:45 AM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t253378_12 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t253378_12 && git checkout t253378_12

Patchset v12 (message #12) is on t253378_12

Jump to latest
#1Pavel Stehule
pavel.stehule@gmail.com

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?

Regards

Pavel

#2Pavel Stehule
pavel.stehule@gmail.com
In reply to: Pavel Stehule (#1)
Re: missing possibility to use alternative translated month names in to_char function

út 11. 8. 2026 v 17:06 odesílatel Pavel Stehule <pavel.stehule@gmail.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@nemesis:~/src/orafce$ date +'%B'
srpna
pavel@nemesis:~/src/orafce$ date +'%OB'
srpen
pavel@nemesis:~/src/orafce$ LANG=C date +'%OB'
August

Show quoted text

Regards

Pavel

#3Pavel Stehule
pavel.stehule@gmail.com
In reply to: Pavel Stehule (#2)
Re: missing possibility to use alternative translated month names in to_char function

Hi

út 11. 8. 2026 v 17:14 odesílatel Pavel Stehule <pavel.stehule@gmail.com>
napsal:

út 11. 8. 2026 v 17:06 odesílatel Pavel Stehule <pavel.stehule@gmail.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@nemesis:~/src/orafce$ date +'%B'
srpna
pavel@nemesis:~/src/orafce$ date +'%OB'
srpen
pavel@nemesis:~/src/orafce$ LANG=C date +'%OB'
August

attached patch that implements 'TAM' modifier for data/timestamp formatting

Regards

Pavel

Show quoted text

Regards

Pavel

Attachments:

t253378_3
0001-introduce-tam-modifier-for-date-timestamp-formatting.patchtext/x-patch; charset=UTF-8; name=0001-introduce-tam-modifier-for-date-timestamp-formatting.patchDownload+160-18
#4Bernd Reiß
bd_reiss@gmx.at
In reply to: Pavel Stehule (#3)
Re: missing possibility to use alternative translated month names in to_char function

Hi Pavel,

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

Threads I found touching TMMONTH + glibc:
/messages/by-id/CALSKcLS3Zi4o0Ak5pNOheqmAiKWcez++qwKvyPccvOz2v62QZQ@mail.gmail.com
(Russian)
/messages/by-id/14717914.JAiOoc7IO7@utklippan

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

Show quoted text

On 12/08/2026 09:13, Pavel Stehule wrote:

Hi

út 11. 8. 2026 v 17:14 odesílatel Pavel Stehule
<pavel.stehule@gmail.com> napsal:

út 11. 8. 2026 v 17:06 odesílatel Pavel Stehule
<pavel.stehule@gmail.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@nemesis:~/src/orafce$ date +'%B'
srpna
pavel@nemesis:~/src/orafce$ date +'%OB'
srpen
pavel@nemesis:~/src/orafce$ LANG=C date +'%OB'
August

attached patch that implements 'TAM' modifier for data/timestamp
formatting

Regards

Pavel

Regards

Pavel

#5Pavel Stehule
pavel.stehule@gmail.com
In reply to: Bernd Reiß (#4)
Re: missing possibility to use alternative translated month names in to_char function

Hi

st 12. 8. 2026 v 23:51 odesílatel Bernd Reiß <bd_reiss@gmx.at> napsal:

Hi Pavel,

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

Threads I found touching TMMONTH + glibc:

/messages/by-id/CALSKcLS3Zi4o0Ak5pNOheqmAiKWcez++qwKvyPccvOz2v62QZQ@mail.gmail.com
(Russian)
/messages/by-id/14717914.JAiOoc7IO7@utklippan

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.

TAMMON is not implemented, because glibc doesn't provide an alternative
form for abbreviated month names.
It is a question if it is better to raise an error, return a non
alternative name or just ignore this flag. I have not strong
opinion about this. Inside DCH_to_char the prefix TM is ignored when it is
not used. So I did the same.

But I can imagine using localized abbreviation. It is possible for the
Czech language - but I have not idea if it is true for other languages.

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.

Yes, I badly expected that prefixes could be mixed. I checked the code, and
this is not possible, so I removed this check

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.

I am afraid about this case too, and I expect maybe some fallback mode
there. But because
I have not a Window machine or some machine with older glibc I decided to
don't touch it
for this moment.

glibc older than 2.28 doesn't support %OB. On the second hand the result of
%B is probably
equal to expected result %B.

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.

please, if you can write this part of the doc. My English is not good
enough to write well about these linguistic details.
It is a problem primarily for slavic languages - like Czech or Russian -
but maybe it can be a wide problem.

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.

Thank you very much for this immediate review

Regards

Pavel

Show quoted text

Best
Bernd

On 12/08/2026 09:13, Pavel Stehule wrote:

Hi

út 11. 8. 2026 v 17:14 odesílatel Pavel Stehule
<pavel.stehule@gmail.com> napsal:

út 11. 8. 2026 v 17:06 odesílatel Pavel Stehule
<pavel.stehule@gmail.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@nemesis:~/src/orafce$ date +'%B'
srpna
pavel@nemesis:~/src/orafce$ date +'%OB'
srpen
pavel@nemesis:~/src/orafce$ LANG=C date +'%OB'
August

attached patch that implements 'TAM' modifier for data/timestamp
formatting

Regards

Pavel

Regards

Pavel

Attachments:

t253378_5
0001-introduce-tam-modifier-for-date-timestamp-formatting.patchtext/x-patch; charset=UTF-8; name=0001-introduce-tam-modifier-for-date-timestamp-formatting.patchDownload+142-18
#6Bernd Reiß
bd_reiss@gmx.at
In reply to: Pavel Stehule (#5)
Re: missing possibility to use alternative translated month names in to_char function

Hi again,

thanks for the updated patch.

TAMMON is not implemented, because glibc doesn't provide an
alternative form for abbreviated month names.
It is a question if it is better to raise an error, return a non
alternative name or just ignore this flag. I have not strong
opinion about this. Inside DCH_to_char the prefix TM is ignored when
it is not used. So I did the same.

The Locale standard actually mentions abbreviated alternative month
names as
"ab_alt_mon" (see [1]https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html). I tested this by setting your TAMMONTH strftime
call to '%Ob'.
If we set the locale to Russian and call the function for May this
actually returns
an abbreviated version of the month name:

Breakpoint 1, cache_locale_time () at pg_locale.c:772
772           if (strftime_l(bufptr, MAX_L10N_DATA, "%Ob", timeinfo,
locale) <= 0)
(gdb) n
774                     bufptr += MAX_L10N_DATA;
(gdb) print bufptr
$4 = 0x7ffde4554630 "май"

Compared to the TMMON form of May in Russian this actually makes a
difference:

postgres=# set lc_time='ru_RU.UTF8';
SET
postgres=# select to_char('2026-05-01'::date, 'TMMON');
 to_char
---------
 МАЯ
(1 row)

postgres=# select to_char('2026-05-01'::date, 'TAMMONTH');
 to_char
---------
 МАЙ
(1 row)

Again, TAMMONTH uses %Ob here. So I would argue for implementing the
abbreviated
forms too.

    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.

Yes, I badly expected that prefixes could be mixed. I checked the
code, and this is not possible, so I removed this check

I think you missed one occurrence in the current patch:

[bernd@paco patches]$ cat 
v2-0001-introduce-tam-modifier-for-date-timestamp-formatting.patch | 
grep -B4 together
+
+ if (IS_SUFFIX_TM(n->suffix) && IS_SUFFIX_TAM(n->suffix))
+         ereturn(escontext,,
+                         (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
+                          errmsg("TM and TAM prefixes cannot be used 
together")));

    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.

I am afraid about this case too, and I expect maybe some fallback mode
there. But because
I have not a Window machine or some machine with older glibc I decided
to don't touch it
for this moment.

glibc older than 2.28 doesn't support %OB. On the second hand the
result of %B is probably
equal to expected result %B.

Turns out I was wrong about this one. For one, although %OB is not
supported, Windows
actually does fall back to %B when used:

postgres=# set lc_time='cs-CZ.UTF8';
SET
postgres=# SELECT to_char('2026-08-01'::date, 'TMMONTH');
 to_char
---------
 SRPEN
(1 row)

postgres=# SELECT to_char('2026-08-01'::date, 'TAMMONTH');
 to_char
---------
 SRPEN
(1 row)

The documentation for wcsftime even mentions this behaviour (see [2]https://en.cppreference.com/cpp/chrono/c/wcsftime).

Furthermore, strftime_l only returns 0 when the result string does not
fit the buffer (or the result is in fact empty, see [3]https://man7.org/linux/man-pages/man3/strftime.3.html). The return
value of
a function call with unrecognized format is not defined. glibc seems to
default to returning the format string itself:

PS C:\Users\bernd> docker run --rm -it debian:8 bash -c 'LC_TIME=C date
"+%B"'
August
PS C:\Users\bernd> docker run --rm -it debian:8 bash -c 'LC_TIME=C date
"+%OB"'
%OB

In my opinion this function call is very unlikely to ever return 0
because %OB is not
defined. So I don't see an issue with that code segment after all, as
this patch does
not interfere with TM and the current documentation of this patch
mentions the
platform dependency of this feature. However, one could argue for
checking whether
%OB/%Ob is literally returned and manually falling back to %B/%b to
cover all bases
and make behaviour more consistent.

    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.

please, if you can write this part of the doc. My English is not good
enough to write well about these linguistic details.
It is a problem primarily for slavic languages - like Czech or Russian
- but maybe it can be a wide problem.

I attached a revised version of your patch to this message explaining the
difference from a linguistic standpoint. I also fixed the second
listitem not
mentioning the suppression of trailing white space by TAM.

As English is also not my first language, I would be very glad if any
native
speaker reading this could have a look over it. Any feedback is
appreciated!

Thank you very much for this immediate review

You are most welcome 🙂

Best
Bernd

[1]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html
[2]: https://en.cppreference.com/cpp/chrono/c/wcsftime
[3]: https://man7.org/linux/man-pages/man3/strftime.3.html

Attachments:

t253378_6
v3-0001-introduce-tam-modifier-for-date-timestamp-formatt.patchtext/x-patch; charset=UTF-8; name=v3-0001-introduce-tam-modifier-for-date-timestamp-formatt.patchDownload+165-20
#7Pavel Stehule
pavel.stehule@gmail.com
In reply to: Bernd Reiß (#6)
Re: missing possibility to use alternative translated month names in to_char function

Hi

so 15. 8. 2026 v 14:03 odesílatel Bernd Reiß <bd_reiss@gmx.at> napsal:

Hi again,

thanks for the updated patch.

TAMMON is not implemented, because glibc doesn't provide an
alternative form for abbreviated month names.
It is a question if it is better to raise an error, return a non
alternative name or just ignore this flag. I have not strong
opinion about this. Inside DCH_to_char the prefix TM is ignored when
it is not used. So I did the same.

The Locale standard actually mentions abbreviated alternative month
names as
"ab_alt_mon" (see [1]). I tested this by setting your TAMMONTH strftime
call to '%Ob'.
If we set the locale to Russian and call the function for May this
actually returns
an abbreviated version of the month name:

Breakpoint 1, cache_locale_time () at pg_locale.c:772
772 if (strftime_l(bufptr, MAX_L10N_DATA, "%Ob", timeinfo,
locale) <= 0)
(gdb) n
774 bufptr += MAX_L10N_DATA;
(gdb) print bufptr
$4 = 0x7ffde4554630 "май"

Compared to the TMMON form of May in Russian this actually makes a
difference:

postgres=# set lc_time='ru_RU.UTF8';
SET
postgres=# select to_char('2026-05-01'::date, 'TMMON');
to_char
---------
МАЯ
(1 row)

postgres=# select to_char('2026-05-01'::date, 'TAMMONTH');
to_char
---------
МАЙ
(1 row)

Again, TAMMONTH uses %Ob here. So I would argue for implementing the
abbreviated
forms too.

I implemented it - please check

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.

Yes, I badly expected that prefixes could be mixed. I checked the
code, and this is not possible, so I removed this check

I think you missed one occurrence in the current patch:

[bernd@paco patches]$ cat
v2-0001-introduce-tam-modifier-for-date-timestamp-formatting.patch |
grep -B4 together
+
+ if (IS_SUFFIX_TM(n->suffix) && IS_SUFFIX_TAM(n->suffix))
+         ereturn(escontext,,
+                         (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
+                          errmsg("TM and TAM prefixes cannot be used
together")));

removed

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.

I am afraid about this case too, and I expect maybe some fallback mode
there. But because
I have not a Window machine or some machine with older glibc I decided
to don't touch it
for this moment.

glibc older than 2.28 doesn't support %OB. On the second hand the
result of %B is probably
equal to expected result %B.

Turns out I was wrong about this one. For one, although %OB is not
supported, Windows
actually does fall back to %B when used:

postgres=# set lc_time='cs-CZ.UTF8';
SET
postgres=# SELECT to_char('2026-08-01'::date, 'TMMONTH');
to_char
---------
SRPEN
(1 row)

postgres=# SELECT to_char('2026-08-01'::date, 'TAMMONTH');
to_char
---------
SRPEN
(1 row)

The documentation for wcsftime even mentions this behaviour (see [2]).

Furthermore, strftime_l only returns 0 when the result string does not
fit the buffer (or the result is in fact empty, see [3]). The return
value of
a function call with unrecognized format is not defined. glibc seems to
default to returning the format string itself:

PS C:\Users\bernd> docker run --rm -it debian:8 bash -c 'LC_TIME=C date
"+%B"'
August
PS C:\Users\bernd> docker run --rm -it debian:8 bash -c 'LC_TIME=C date
"+%OB"'
%OB

In my opinion this function call is very unlikely to ever return 0
because %OB is not
defined. So I don't see an issue with that code segment after all, as
this patch does
not interfere with TM and the current documentation of this patch
mentions the
platform dependency of this feature. However, one could argue for
checking whether
%OB/%Ob is literally returned and manually falling back to %B/%b to
cover all bases
and make behaviour more consistent.

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.

please, if you can write this part of the doc. My English is not good
enough to write well about these linguistic details.
It is a problem primarily for slavic languages - like Czech or Russian
- but maybe it can be a wide problem.

I attached a revised version of your patch to this message explaining the
difference from a linguistic standpoint. I also fixed the second
listitem not
mentioning the suppression of trailing white space by TAM.

As English is also not my first language, I would be very glad if any
native
speaker reading this could have a look over it. Any feedback is
appreciated!

I merged your documentation patch, thank you

Thank you very much for this immediate review

You are most welcome 🙂

:-)

Please check updated patch

Nice evening

Pavel

Show quoted text

Best
Bernd

[1]
https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html
[2] https://en.cppreference.com/cpp/chrono/c/wcsftime
[3] https://man7.org/linux/man-pages/man3/strftime.3.html

Attachments:

t253378_7
v20260818-4-0001-introduce-tam-modifier-for-date-timestamp-formatting.patchtext/x-patch; charset=UTF-8; name=v20260818-4-0001-introduce-tam-modifier-for-date-timestamp-formatting.patchDownload+241-33
#8Bernd Reiß
bd_reiss@gmx.at
In reply to: Pavel Stehule (#7)
Re: missing possibility to use alternative translated month names in to_char function

Hi Pavel,

On 8/18/26 8:47 PM, Pavel Stehule wrote:

Hi

so 15. 8. 2026 v 14:03 odesílatel Bernd Reiß <bd_reiss@gmx.at <mailto:bd_reiss@gmx.at>> napsal:

Hi again,

thanks for the updated patch.

TAMMON is not implemented, because glibc doesn't provide an
alternative form for abbreviated month names.
It is a question if it is better to raise an error, return a non
alternative name or just ignore this flag. I have not strong
opinion about this. Inside DCH_to_char the prefix TM is ignored when
it is not used. So I did the same.

The Locale standard actually mentions abbreviated alternative month
names as
"ab_alt_mon" (see [1]). I tested this by setting your TAMMONTH strftime
call to '%Ob'.
If we set the locale to Russian and call the function for May this
actually returns
an abbreviated version of the month name:

Breakpoint 1, cache_locale_time () at pg_locale.c:772
772           if (strftime_l(bufptr, MAX_L10N_DATA, "%Ob", timeinfo,
locale) <= 0)
(gdb) n
774                     bufptr += MAX_L10N_DATA;
(gdb) print bufptr
$4 = 0x7ffde4554630 "май"

Compared to the TMMON form of May in Russian this actually makes a
difference:

postgres=# set lc_time='ru_RU.UTF8';
SET
postgres=# select to_char('2026-05-01'::date, 'TMMON');
  to_char
---------
  МАЯ
(1 row)

postgres=# select to_char('2026-05-01'::date, 'TAMMONTH');
  to_char
---------
  МАЙ
(1 row)

Again, TAMMONTH uses %Ob here. So I would argue for implementing the
abbreviated
forms too.

I implemented it - please check

LGTM. I compiled it and it works as expected. I also like the introduction of
the get_localized_*_months functions. However, this leads to suffix_len being
declared and set but never used in the DCH_MONTH, DCH_Month, and DCH_month
cases (as well as for the abbreviated equivalents) in DCH_from_char. Passing
NULL and guarding in the functions would be an option to avoid this. However,
I don't feel strongly about this.

In DCH_to_char I think you forgot to refactor this if statement for the
MON/Mon/mon cases?

if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
strcpy(s, str);

Please check updated patch

With the if statements cleaned up this is a +1 for Ready for Committer from me.

Best
Bernd

#9Tom Lane
tgl@sss.pgh.pa.us
In reply to: Bernd Reiß (#8)
Re: missing possibility to use alternative translated month names in to_char function

=?UTF-8?Q?Bernd_Rei=C3=9F?= <bd_reiss@gmx.at> writes:

With the if statements cleaned up this is a +1 for Ready for Committer from me.

I have no opinion about the merits of this patch, but I am
pretty sure it needs a rebase after 03d255463. (The cfbot
doesn't seem to have noticed that yet.)

regards, tom lane

#10Haibo Yan
tristan.yim@gmail.com
In reply to: Pavel Stehule (#5)
Re: missing possibility to use alternative translated month names in to_char function

On Wed, Aug 12, 2026 at 9:47 PM Pavel Stehule <pavel.stehule@gmail.com> wrote:

Hi

st 12. 8. 2026 v 23:51 odesílatel Bernd Reiß <bd_reiss@gmx.at> napsal:

Hi Pavel,

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

Threads I found touching TMMONTH + glibc:
/messages/by-id/CALSKcLS3Zi4o0Ak5pNOheqmAiKWcez++qwKvyPccvOz2v62QZQ@mail.gmail.com
(Russian)
/messages/by-id/14717914.JAiOoc7IO7@utklippan

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.

TAMMON is not implemented, because glibc doesn't provide an alternative form for abbreviated month names.
It is a question if it is better to raise an error, return a non alternative name or just ignore this flag. I have not strong
opinion about this. Inside DCH_to_char the prefix TM is ignored when it is not used. So I did the same.

But I can imagine using localized abbreviation. It is possible for the Czech language - but I have not idea if it is true for other languages.

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.

Yes, I badly expected that prefixes could be mixed. I checked the code, and this is not possible, so I removed this check

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.

I am afraid about this case too, and I expect maybe some fallback mode there. But because
I have not a Window machine or some machine with older glibc I decided to don't touch it
for this moment.

glibc older than 2.28 doesn't support %OB. On the second hand the result of %B is probably
equal to expected result %B.

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.

please, if you can write this part of the doc. My English is not good enough to write well about these linguistic details.
It is a problem primarily for slavic languages - like Czech or Russian - but maybe it can be a wide problem.

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.

Thank you very much for this immediate review

Regards

Pavel

Best
Bernd

On 12/08/2026 09:13, Pavel Stehule wrote:

Hi

út 11. 8. 2026 v 17:14 odesílatel Pavel Stehule
<pavel.stehule@gmail.com> napsal:

út 11. 8. 2026 v 17:06 odesílatel Pavel Stehule
<pavel.stehule@gmail.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@nemesis:~/src/orafce$ date +'%B'
srpna
pavel@nemesis:~/src/orafce$ date +'%OB'
srpen
pavel@nemesis:~/src/orafce$ LANG=C date +'%OB'
August

attached patch that implements 'TAM' modifier for data/timestamp
formatting

Regards

Pavel

Regards

Pavel

The use case makes sense to me, but I wonder a bit about the abstraction
boundary here.

TA exposes a fairly specific locale/grammatical distinction as part of the
to_char() format language. Is this something we want to make part of the
long-term SQL-facing API, rather than leaving context-sensitive localization
to the application/localization layer?

I’m not objecting to the patch, but if other locale-specific grammatical forms
come up later, would we expect to keep adding similar modifiers? Maybe this
particular distinction is common enough to justify it, but I think the i
intended boundary is worth considering.

I’m not a committer, so I may be missing some of the context here, and I’m
happy to defer to others who have more experience with this area.

Regards,
Haibo

#11Pavel Stehule
pavel.stehule@gmail.com
In reply to: Haibo Yan (#10)
Re: missing possibility to use alternative translated month names in to_char function

Hi

The use case makes sense to me, but I wonder a bit about the abstraction
boundary here.

TA exposes a fairly specific locale/grammatical distinction as part of the
to_char() format language. Is this something we want to make part of the
long-term SQL-facing API, rather than leaving context-sensitive
localization
to the application/localization layer?

I’m not objecting to the patch, but if other locale-specific grammatical
forms
come up later, would we expect to keep adding similar modifiers? Maybe this
particular distinction is common enough to justify it, but I think the i
intended boundary is worth considering.

The design is based on glibc locales - and they introduced just one
alternative form - no others.

I don't have a knowledge about other languages than Czech language, but
generally there are used only two forms for name of month

1. in combination with day - 2024-07-01 ... 1 července 2024 - this is
always combination day, month
2. Just the name of the month .. červenec - this form can be combined with
day, but can be used as an isolated name of month (in this case, only this
form).

Sometimes can be used third form (little bit obsolete) ... k 1 červenci
(this form is not supported by any library)

The form @2 was the historical default of all libraries that support
localized month names. glibc 2.28 z 2018 changed form to @1, and original
values were moved to alternative names.

libicu has a similar design (with different names) - it supports two forms
of month name - MMMM (month in year) and LLLL (stand-alone month in year).
No other form is supported.

https://unicode-org.github.io/icu/userguide/format_parse/datetime/#formatting-dates

Regards

Pavel

Show quoted text

I’m not a committer, so I may be missing some of the context here, and I’m
happy to defer to others who have more experience with this area.

Regards,
Haibo

#12Pavel Stehule
pavel.stehule@gmail.com
In reply to: Bernd Reiß (#8)
Re: missing possibility to use alternative translated month names in to_char function

Hi

pá 21. 8. 2026 v 18:56 odesílatel Bernd Reiß <bd_reiss@gmx.at> napsal:

Hi Pavel,

On 8/18/26 8:47 PM, Pavel Stehule wrote:

Hi

so 15. 8. 2026 v 14:03 odesílatel Bernd Reiß <bd_reiss@gmx.at <mailto:

bd_reiss@gmx.at>> napsal:

Hi again,

thanks for the updated patch.

TAMMON is not implemented, because glibc doesn't provide an
alternative form for abbreviated month names.
It is a question if it is better to raise an error, return a non
alternative name or just ignore this flag. I have not strong
opinion about this. Inside DCH_to_char the prefix TM is ignored

when

it is not used. So I did the same.

The Locale standard actually mentions abbreviated alternative month
names as
"ab_alt_mon" (see [1]). I tested this by setting your TAMMONTH

strftime

call to '%Ob'.
If we set the locale to Russian and call the function for May this
actually returns
an abbreviated version of the month name:

Breakpoint 1, cache_locale_time () at pg_locale.c:772
772 if (strftime_l(bufptr, MAX_L10N_DATA, "%Ob", timeinfo,
locale) <= 0)
(gdb) n
774 bufptr += MAX_L10N_DATA;
(gdb) print bufptr
$4 = 0x7ffde4554630 "май"

Compared to the TMMON form of May in Russian this actually makes a
difference:

postgres=# set lc_time='ru_RU.UTF8';
SET
postgres=# select to_char('2026-05-01'::date, 'TMMON');
to_char
---------
МАЯ
(1 row)

postgres=# select to_char('2026-05-01'::date, 'TAMMONTH');
to_char
---------
МАЙ
(1 row)

Again, TAMMONTH uses %Ob here. So I would argue for implementing the
abbreviated
forms too.

I implemented it - please check

LGTM. I compiled it and it works as expected. I also like the introduction
of
the get_localized_*_months functions. However, this leads to suffix_len
being
declared and set but never used in the DCH_MONTH, DCH_Month, and DCH_month
cases (as well as for the abbreviated equivalents) in DCH_from_char.
Passing
NULL and guarding in the functions would be an option to avoid this.
However,
I don't feel strongly about this.

In DCH_to_char I think you forgot to refactor this if statement for the
MON/Mon/mon cases?

if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) *
DCH_MAX_ITEM_SIZ)
strcpy(s, str);

this code is removed in new version

Please check updated patch

With the if statements cleaned up this is a +1 for Ready for Committer
from me.

Regards

Pavel

Show quoted text

Best
Bernd

Attachments:

t253378_12
0001-introduce-tam-modifier-for-date-timestamp-formatting.patchtext/x-patch; charset=UTF-8; name=0001-introduce-tam-modifier-for-date-timestamp-formatting.patchDownload+216-30
#13Bernd Reiß
bd_reiss@gmx.at
In reply to: Pavel Stehule (#12)
Re: missing possibility to use alternative translated month names in to_char function

Hi,

On 23/08/2026 07:30, Pavel Stehule wrote:

Hi

pá 21. 8. 2026 v 18:56 odesílatel Bernd Reiß <bd_reiss@gmx.at> napsal:

Hi Pavel,

On 8/18/26 8:47 PM, Pavel Stehule wrote:

Hi

so 15. 8. 2026 v 14:03 odesílatel Bernd Reiß <bd_reiss@gmx.at

<mailto:bd_reiss@gmx.at>> napsal:

     Hi again,

     thanks for the updated patch.
     > TAMMON is not implemented, because glibc doesn't provide an
     > alternative form for abbreviated month names.
     > It is a question if it is better to raise an error, return

a non

     > alternative name or just ignore this flag. I have not strong
     > opinion about this. Inside DCH_to_char the prefix TM is

ignored when

     > it is not used. So I did the same.
     The Locale standard actually mentions abbreviated

alternative month

     names as
     "ab_alt_mon" (see [1]). I tested this by setting your

TAMMONTH strftime

     call to '%Ob'.
     If we set the locale to Russian and call the function for

May this

     actually returns
     an abbreviated version of the month name:

     Breakpoint 1, cache_locale_time () at pg_locale.c:772
     772           if (strftime_l(bufptr, MAX_L10N_DATA, "%Ob",

timeinfo,

     locale) <= 0)
     (gdb) n
     774                     bufptr += MAX_L10N_DATA;
     (gdb) print bufptr
     $4 = 0x7ffde4554630 "май"

     Compared to the TMMON form of May in Russian this actually

makes a

     difference:

     postgres=# set lc_time='ru_RU.UTF8';
     SET
     postgres=# select to_char('2026-05-01'::date, 'TMMON');
       to_char
     ---------
       МАЯ
     (1 row)

     postgres=# select to_char('2026-05-01'::date, 'TAMMONTH');
       to_char
     ---------
       МАЙ
     (1 row)

     Again, TAMMONTH uses %Ob here. So I would argue for

implementing the

     abbreviated
     forms too.

I implemented it - please check

LGTM. I compiled it and it works as expected. I also like the
introduction of
the get_localized_*_months functions. However, this leads to
suffix_len being
declared and set but never used in the DCH_MONTH, DCH_Month, and
DCH_month
cases (as well as for the abbreviated equivalents) in
DCH_from_char. Passing
NULL and guarding in the functions would be an option to avoid
this. However,
I don't feel strongly about this.

In DCH_to_char I think you forgot to refactor this if statement
for the
MON/Mon/mon cases?

          if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) *
DCH_MAX_ITEM_SIZ)
            strcpy(s, str);

this code is removed in new version

Please check updated patch

With the if statements cleaned up this is a +1 for Ready for
Committer from me.

Regards

Pavel

Patch applies cleanly now on HEAD. New changes LGTM. Compiles without
problems and
regression tests are all green. I am moving this to Ready for Reviewer.

Best
Bernd

#14Pavel Stehule
pavel.stehule@gmail.com
In reply to: Bernd Reiß (#13)
Re: missing possibility to use alternative translated month names in to_char function

ne 23. 8. 2026 v 8:32 odesílatel Bernd Reiß <bd_reiss@gmx.at> napsal:

Hi,

On 23/08/2026 07:30, Pavel Stehule wrote:

Hi

pá 21. 8. 2026 v 18:56 odesílatel Bernd Reiß <bd_reiss@gmx.at> napsal:

Hi Pavel,

On 8/18/26 8:47 PM, Pavel Stehule wrote:

Hi

so 15. 8. 2026 v 14:03 odesílatel Bernd Reiß <bd_reiss@gmx.at

<mailto:bd_reiss@gmx.at>> napsal:

Hi again,

thanks for the updated patch.

TAMMON is not implemented, because glibc doesn't provide an
alternative form for abbreviated month names.
It is a question if it is better to raise an error, return

a non

alternative name or just ignore this flag. I have not strong
opinion about this. Inside DCH_to_char the prefix TM is

ignored when

it is not used. So I did the same.

The Locale standard actually mentions abbreviated

alternative month

names as
"ab_alt_mon" (see [1]). I tested this by setting your

TAMMONTH strftime

call to '%Ob'.
If we set the locale to Russian and call the function for

May this

actually returns
an abbreviated version of the month name:

Breakpoint 1, cache_locale_time () at pg_locale.c:772
772 if (strftime_l(bufptr, MAX_L10N_DATA, "%Ob",

timeinfo,

locale) <= 0)
(gdb) n
774 bufptr += MAX_L10N_DATA;
(gdb) print bufptr
$4 = 0x7ffde4554630 "май"

Compared to the TMMON form of May in Russian this actually

makes a

difference:

postgres=# set lc_time='ru_RU.UTF8';
SET
postgres=# select to_char('2026-05-01'::date, 'TMMON');
to_char
---------
МАЯ
(1 row)

postgres=# select to_char('2026-05-01'::date, 'TAMMONTH');
to_char
---------
МАЙ
(1 row)

Again, TAMMONTH uses %Ob here. So I would argue for

implementing the

abbreviated
forms too.

I implemented it - please check

LGTM. I compiled it and it works as expected. I also like the
introduction of
the get_localized_*_months functions. However, this leads to
suffix_len being
declared and set but never used in the DCH_MONTH, DCH_Month, and
DCH_month
cases (as well as for the abbreviated equivalents) in
DCH_from_char. Passing
NULL and guarding in the functions would be an option to avoid
this. However,
I don't feel strongly about this.

In DCH_to_char I think you forgot to refactor this if statement
for the
MON/Mon/mon cases?

if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) *
DCH_MAX_ITEM_SIZ)
strcpy(s, str);

this code is removed in new version

Please check updated patch

With the if statements cleaned up this is a +1 for Ready for
Committer from me.

Regards

Pavel

Patch applies cleanly now on HEAD. New changes LGTM. Compiles without
problems and
regression tests are all green. I am moving this to Ready for Reviewer.

you are a reviewer :-)

Pavel

Show quoted text

Best
Bernd

#15Bernd Reiß
bd_reiss@gmx.at
In reply to: Pavel Stehule (#14)
Re: missing possibility to use alternative translated month names in to_char function

Ah, my bad. Meant to say Committer, of course :)

Bernd

Sent with Spark

Show quoted text

On 23 Aug 2026 at 12:32 +0200, Pavel Stehule <pavel.stehule@gmail.com>, wrote:

ne 23. 8. 2026 v 8:32 odesílatel Bernd Reiß <bd_reiss@gmx.at> napsal:

Hi,

On 23/08/2026 07:30, Pavel Stehule wrote:

Hi

pá 21. 8. 2026 v 18:56 odesílatel Bernd Reiß <bd_reiss@gmx.at> napsal:

     Hi Pavel,

     On 8/18/26 8:47 PM, Pavel Stehule wrote:
     > Hi
     >
     > so 15. 8. 2026 v 14:03 odesílatel Bernd Reiß <bd_reiss@gmx.at
     <mailto:bd_reiss@gmx.at>> napsal:
     >
     >     Hi again,
     >
     >     thanks for the updated patch.
     >     > TAMMON is not implemented, because glibc doesn't provide an
     >     > alternative form for abbreviated month names.
     >     > It is a question if it is better to raise an error, return
     a non
     >     > alternative name or just ignore this flag. I have not strong
     >     > opinion about this. Inside DCH_to_char the prefix TM is
     ignored when
     >     > it is not used. So I did the same.
     >     The Locale standard actually mentions abbreviated
     alternative month
     >     names as
     >     "ab_alt_mon" (see [1]). I tested this by setting your
     TAMMONTH strftime
     >     call to '%Ob'.
     >     If we set the locale to Russian and call the function for
     May this
     >     actually returns
     >     an abbreviated version of the month name:
     >
     >     Breakpoint 1, cache_locale_time () at pg_locale.c:772
     >     772           if (strftime_l(bufptr, MAX_L10N_DATA, "%Ob",
     timeinfo,
     >     locale) <= 0)
     >     (gdb) n
     >     774                     bufptr += MAX_L10N_DATA;
     >     (gdb) print bufptr
     >     $4 = 0x7ffde4554630 "май"
     >
     >     Compared to the TMMON form of May in Russian this actually
     makes a
     >     difference:
     >
     >     postgres=# set lc_time='ru_RU.UTF8';
     >     SET
     >     postgres=# select to_char('2026-05-01'::date, 'TMMON');
     >       to_char
     >     ---------
     >       МАЯ
     >     (1 row)
     >
     >     postgres=# select to_char('2026-05-01'::date, 'TAMMONTH');
     >       to_char
     >     ---------
     >       МАЙ
     >     (1 row)
     >
     >     Again, TAMMONTH uses %Ob here. So I would argue for
     implementing the
     >     abbreviated
     >     forms too.
     >
     >
     > I implemented it - please check

     LGTM. I compiled it and it works as expected. I also like the
     introduction of
     the get_localized_*_months functions. However, this leads to
     suffix_len being
     declared and set but never used in the DCH_MONTH, DCH_Month, and
     DCH_month
     cases (as well as for the abbreviated equivalents) in
     DCH_from_char. Passing
     NULL and guarding in the functions would be an option to avoid
     this. However,
     I don't feel strongly about this.

     In DCH_to_char I think you forgot to refactor this if statement
     for the
     MON/Mon/mon cases?

               if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) *
     DCH_MAX_ITEM_SIZ)
                 strcpy(s, str);

this code is removed in new version

     >
     > Please check updated patch
     >

     With the if statements cleaned up this is a +1 for Ready for
     Committer from me.

Regards

Pavel

Patch applies cleanly now on HEAD. New changes LGTM. Compiles without
problems and
regression tests are all green. I am moving this to Ready for Reviewer.

you are a reviewer :-)

Pavel

Best
Bernd

#16Pavel Stehule
pavel.stehule@gmail.com
In reply to: Bernd Reiß (#15)
Re: missing possibility to use alternative translated month names in to_char function

ne 23. 8. 2026 v 12:37 odesílatel <bd_reiss@gmx.at> napsal:

Ah, my bad. Meant to say Committer, of course :)

Thank you :)

Pavel

Show quoted text

Bernd

Sent with Spark <https://sparkmailapp.com/source?from=signature&gt;
On 23 Aug 2026 at 12:32 +0200, Pavel Stehule <pavel.stehule@gmail.com>,
wrote:

ne 23. 8. 2026 v 8:32 odesílatel Bernd Reiß <bd_reiss@gmx.at> napsal:

Hi,

On 23/08/2026 07:30, Pavel Stehule wrote:

Hi

pá 21. 8. 2026 v 18:56 odesílatel Bernd Reiß <bd_reiss@gmx.at> napsal:

Hi Pavel,

On 8/18/26 8:47 PM, Pavel Stehule wrote:

Hi

so 15. 8. 2026 v 14:03 odesílatel Bernd Reiß <bd_reiss@gmx.at

<mailto:bd_reiss@gmx.at>> napsal:

Hi again,

thanks for the updated patch.

TAMMON is not implemented, because glibc doesn't provide an
alternative form for abbreviated month names.
It is a question if it is better to raise an error, return

a non

alternative name or just ignore this flag. I have not strong
opinion about this. Inside DCH_to_char the prefix TM is

ignored when

it is not used. So I did the same.

The Locale standard actually mentions abbreviated

alternative month

names as
"ab_alt_mon" (see [1]). I tested this by setting your

TAMMONTH strftime

call to '%Ob'.
If we set the locale to Russian and call the function for

May this

actually returns
an abbreviated version of the month name:

Breakpoint 1, cache_locale_time () at pg_locale.c:772
772 if (strftime_l(bufptr, MAX_L10N_DATA, "%Ob",

timeinfo,

locale) <= 0)
(gdb) n
774 bufptr += MAX_L10N_DATA;
(gdb) print bufptr
$4 = 0x7ffde4554630 "май"

Compared to the TMMON form of May in Russian this actually

makes a

difference:

postgres=# set lc_time='ru_RU.UTF8';
SET
postgres=# select to_char('2026-05-01'::date, 'TMMON');
to_char
---------
МАЯ
(1 row)

postgres=# select to_char('2026-05-01'::date, 'TAMMONTH');
to_char
---------
МАЙ
(1 row)

Again, TAMMONTH uses %Ob here. So I would argue for

implementing the

abbreviated
forms too.

I implemented it - please check

LGTM. I compiled it and it works as expected. I also like the
introduction of
the get_localized_*_months functions. However, this leads to
suffix_len being
declared and set but never used in the DCH_MONTH, DCH_Month, and
DCH_month
cases (as well as for the abbreviated equivalents) in
DCH_from_char. Passing
NULL and guarding in the functions would be an option to avoid
this. However,
I don't feel strongly about this.

In DCH_to_char I think you forgot to refactor this if statement
for the
MON/Mon/mon cases?

if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) *
DCH_MAX_ITEM_SIZ)
strcpy(s, str);

this code is removed in new version

Please check updated patch

With the if statements cleaned up this is a +1 for Ready for
Committer from me.

Regards

Pavel

Patch applies cleanly now on HEAD. New changes LGTM. Compiles without
problems and
regression tests are all green. I am moving this to Ready for Reviewer.

you are a reviewer :-)

Pavel

Best
Bernd