From 10342301593b8288471faaaf79018519fd9eb90c Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 8 Feb 2024 12:48:14 +0100 Subject: [PATCH] nstrtime, c-nstrftime: Fix %c directive's result on NetBSD, Solaris. * lib/strftime.c (__strftime_internal): On NetBSD and Solaris, remove the last word of the %c directive's result if it looks like a time zone. --- ChangeLog | 6 ++++++ lib/strftime.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 53f6cb1765..d0891f1e66 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-02-08 Bruno Haible + + nstrtime, c-nstrftime: Fix %c directive's result on NetBSD, Solaris. + * lib/strftime.c (__strftime_internal): On NetBSD and Solaris, remove + the last word of the %c directive's result if it looks like a time zone. + 2024-02-07 Bruno Haible c-nstrftime: Add tests. diff --git a/lib/strftime.c b/lib/strftime.c index f6714524bd..b70494cf78 100644 --- a/lib/strftime.c +++ b/lib/strftime.c @@ -967,7 +967,48 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) len = strftime (ubuf, sizeof ubuf, ufmt, tp); # endif if (len != 0) - cpy (len - 1, ubuf + 1); + { +# if defined __NetBSD__ || defined __sun /* NetBSD, Solaris */ + if (format_char == L_('c')) + { + /* The output of the strftime %c directive consists of the + date, the time, and the time zone. But the time zone is + wrong, since neither TZ nor ZONE was passed as argument. + Therefore, remove the the last space-delimited word. + In order not to accidentally remove a date or a year + (that contains no letter) or an AM/PM indicator (that has + length 2), remove that last word only if it contains a + letter and has length >= 3. */ + char *space; + for (space = ubuf + len - 1; *space != ' '; space--) + ; + if (space > ubuf) + { + /* Found a space. */ + if (strlen (space + 1) >= 3) + { + /* The last word has length >= 3. */ + bool found_letter = false; + const char *p; + for (p = space + 1; *p != '\0'; p++) + if ((*p >= 'A' && *p <= 'Z') + || (*p >= 'a' && *p <= 'z')) + { + found_letter = true; + break; + } + if (found_letter) + { + /* The last word contains a letter. */ + *space = '\0'; + len = space - ubuf; + } + } + } + } +# endif + cpy (len - 1, ubuf + 1); + } } break; #endif -- 2.39.5