inconsistent handling of flags with nstrftime formats

Pádraig Brady <[email protected]>
Newsgroups gmane.comp.lib.gnulib.bugs
Message-ID <[email protected]>
The following are understandable/consistent:

   # Y (unlike glibc) defaults to 04Y
   $ date -d '1-2-3' +[%Y]
   [0001]

   # A flag can override that
   $ date -d '1-2-3' +[%_Y]
   [   1]

   # The compound %D is %m/%d/%y
   $ date -d '1-2-3' +[%D]
   [02/03/01]

   $ The compound %F is %+4Y-%m-%d
   $ date -d '1-2-3' +[%F]
   [0001-02-03]

So far so good.
But what about flags on compound specifiers?
I would expect them to propagate to the sub formats.
But they don't on glibc, and are essentially ignored.
That's a bit surprising, but consistent.
E.g. glibc strftime() produces:

   %D    [02/03/01]
   %_D   [02/03/01]
   %-D   [02/03/01]
   %10D  [  02/03/01]
   %_10D [  02/03/01]
   %010D [0003/03/01]
   %-10D [  02/03/01]
   %F    [1-02-03]
   %_F   [1-02-03]
   %-F   [1-02-03]

Still consistent so far.
But with gnulib since commit 188d87b051 introducing support
for the POSIX¹ '+' flag, all flags are now propagated to
just the year component:

   $ date -d '1-2-3' +[%_D]
   [02/03/ 1]

   $ date -d "1-2-3" "+[%-D]"
   [02/03/1]

That seems confusing and inconsistent to me
(for the first 9 years of each century at least).
I.e. these flags propagate to the %y sub specifier, but not the %m or %d.
Note all these specifiers support these flags in isolation:

   $ date -d "1-2-3" "+%-y/%-m/%-d"
   1/2/3

To make this consistent we could either:
   1. Propagate flags to all sub specifiers
   2. Ignore these glibc [_-] flags in all sub specifiers

1. would be more consistent with the '+' flag,
and in my reading, the POSIX intent of propagating compound flags to sub specifiers

2. would be more consistent with glibc's strftime() output.
Note glibc strftime() still doesn't support the POSIX '+' flag.

Attached is a quick patch for discussion to effect option 2.

cheers,
Padraig

¹ https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/strftime.html
gnulib-strftime-compound-year-flag.diff (text/x-patch, 2 KB)
diff --git a/lib/strftime.c b/lib/strftime.c
index 5a3544674e..f92fff90f5 100644
--- a/lib/strftime.c
+++ b/lib/strftime.c
@@ -1641,11 +1641,14 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
           subwidth = -1;
         subformat_width:
           {
+            enum pad_style subpad =
+              (format_char == L_('F') || format_char == L_('Y')
+               ? pad : yr_spec);
             retval_t len =
               __strftime_internal (NULL, STRFTIME_ARG ((size_t) -1)
                                    subfmt, tp,
                                    CAL_ARGS (cal, caldate)
-                                   to_uppcase, pad, subwidth,
+                                   to_uppcase, subpad, subwidth,
                                    tzset_called
                                    extra_args LOCALE_ARG);
             if (FAILURE < 0 && len < 0)
@@ -1654,7 +1657,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
                                            STRFTIME_ARG (maxsize - i)
                                            subfmt, tp,
                                            CAL_ARGS (cal, caldate)
-                                           to_uppcase, pad, subwidth,
+                                           to_uppcase, subpad, subwidth,
                                            tzset_called
                                            extra_args LOCALE_ARG));
           }
diff --git a/tests/test-nstrftime.h b/tests/test-nstrftime.h
index 7ab38b40c5..64a007b521 100644
--- a/tests/test-nstrftime.h
+++ b/tests/test-nstrftime.h
@@ -50,6 +50,8 @@ struct posixtm_test
 static struct posixtm_test const T[] =
   {
     { 1300000000, 0,            "%F", "2011-03-13" },
+    { 1086393600, 0,            "%_D", "06/05/04" },
+    { 1086393600, 0,            "%-D", "06/05/04" },
     { 0,          10,           "%T.%N", "00:00:00.000000010" },
     { 56,         123456789,    "%T.%12N", "00:00:56.123456789000" },
     { 0,          123000000,    "%T.%_6N", "00:00:00.123   " },
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.