Fw: [PATCH 1/2] strftime.c(__strftime): add %i, %q, %v, tests; tweak %Z docs

Brian Inglis Brian.Inglis@SystematicSw.ab.ca
Thu Oct 20 22:07:09 GMT 2022


On 2022-10-18 08:03, Corinna Vinschen wrote:
> On Sep 19 11:51, C Howland wrote:
>> On Saturday, September 17, 2022 1:00 AM, Brian Inglis wrote:
>>> newlib/libc/time/strftime.c(__strftime):
>>> %i year in century [00..99] Synonym for "%y". Non-POSIX extension.
>>> [tm_year]
>>> %q GNU quarter of the year (from `<<1>>' to `<<4>>') [tm_mon]
>>> %v OSX/Ruby VMS/Oracle date "%d-%b-%Y". Non-POSIX extension. [tm_mday,
>>> tm_mon, tm_year]
>>> add %i %q %v tests
>>> %Z clarify current time zone *abbreviation* not "name" [tm_isdst]
>>> ---
>>>   newlib/libc/time/strftime.c | 67 +++++++++++++++++++++++++++++++++++--
>>>   1 file changed, 64 insertions(+), 3 deletions(-)

> - %i: Where is used and documented?  I don't see this in glibc, not even
>    in the latest from the glibc git repo.

Some portable language implementations for non-Unix platforms that I came across 
and documented but did not keep track of, and now can't find!

> - %q: Ditto. For a GNU extension, it's surprisingly absent from the
>    most recent glibc code, or do I miss something?

Looks like this may have been lost in the discussion:

https://inbox.sourceware.org/libc-alpha/2f5f737e-2e42-08c6-ae2b-33aab798a1d9@draigBrady.com/

but as he says, it was already in gnulib, and made it into date the same month:

https://git.savannah.gnu.org/cgit/coreutils.git/diff/?id=30012b290facf66551cdf395ace397903d00483d

also in Perl and ksh93 printf %(...)T.

> - %v: OSX/Ruby?  Isn't that already gone?  Also, it introduces another
>    ambiguous date format where %F or equivalent should be used instead.

All the BSDs, Darwin, Oracle, and Ruby support it: it is localized, but not 
ambiguous, as it's dd-Mon-yyyy.

> It's nice to add features, but it wouldn't hurt to have some
> clarification and justification if it's non-standard stuff.
> Availability in glibc or in the BSDs is typically justification enough,
> but I don't see this here.

See attached sh and log for doc and code searches.

-- 
Take care. Thanks, Brian Inglis			Calgary, Alberta, Canada

La perfection est atteinte			Perfection is achieved
non pas lorsqu'il n'y a plus rien à ajouter	not when there is no more to add
mais lorsqu'il n'y a plus rien à retirer	but when there is no more to cut
			-- Antoine de Saint-Exupéry
-------------- next part --------------
#!/bin/bash
# date-iqv.sh

echo "$ man date | grep \"'[iqv]'\|%[iqv]\""
man date | grep "'[iqv]'\|%[iqv]"

echo "$ perldoc Date::Format | grep \"'[iqv]'\|%[iqv]\""
perldoc Date::Format | grep "'[iqv]'\|%[iqv]"

echo "$ ri Date.strftime | grep \"'[iqv]'\|%[iqv]\""
ri Date.strftime | grep "'[iqv]'\|%[iqv]"

echo "$ grep -A8 \"'[iqv]'\|%[iqv]\" ../{BSD/*BSD,cygwin/coreutils/coreutils-9.0-?.x*/origsrc/coreutils-9.0/*,glibc/time,gnulib/lib,musl/time}/*{date,{str,wcs}[fp]time}*"
grep -A8 "'[iqv]'\|%[iqv]" ../{BSD/*BSD,cygwin/coreutils/coreutils-9.0-?.x*/origsrc/coreutils-9.0/*,glibc/time,gnulib/lib,musl/time}/*{date,{str,wcs}[fp]time}*

-------------- next part --------------
$ man date | grep "'[iqv]'\|%[iqv]"
       %q     quarter of year (1..4)
$ perldoc Date::Format | grep "'[iqv]'\|%[iqv]"
            %q      Quarter number, starting with 1
    %d, %e, %H, %I, %j, %k, %l, %m, %M, %q, %y and %Y can be output in Roman
$ ri Date.strftime | grep "'[iqv]'\|%[iqv]"
    %v - VMS date (%e-%b-%Y)
$ grep -A8 "'[iqv]'\|%[iqv]" ../{BSD/*BSD,cygwin/coreutils/coreutils-9.0-?.x*/origsrc/coreutils-9.0/*,glibc/time,gnulib/lib,musl/time}/*{date,{str,wcs}[fp]time}*
../BSD/FreeBSD/strftime.c:			case 'v':
../BSD/FreeBSD/strftime.c-				/*
../BSD/FreeBSD/strftime.c-				 * From Arnold Robbins' strftime version 3.0:
../BSD/FreeBSD/strftime.c-				 * "date as dd-bbb-YYYY"
../BSD/FreeBSD/strftime.c-				 * (ado, 1993-05-24)
../BSD/FreeBSD/strftime.c-				 */
../BSD/FreeBSD/strftime.c-				pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, loc);
../BSD/FreeBSD/strftime.c-				continue;
../BSD/FreeBSD/strftime.c-			case 'W':
--
../BSD/NetBSD/strftime.c:			case 'v':
../BSD/NetBSD/strftime.c-				/*
../BSD/NetBSD/strftime.c-				** From Arnold Robbins' strftime version 3.0:
../BSD/NetBSD/strftime.c-				** "date as dd-bbb-YYYY"
../BSD/NetBSD/strftime.c-				** (ado, 1993-05-24)
../BSD/NetBSD/strftime.c-				*/
../BSD/NetBSD/strftime.c-				pt = _fmt(sp, "%e-%b-%Y", t, pt, ptlim, warnp,
../BSD/NetBSD/strftime.c-				    loc);
../BSD/NetBSD/strftime.c-				continue;
--
../BSD/OpenBSD/strftime.c:			case 'v':
../BSD/OpenBSD/strftime.c-				/*
../BSD/OpenBSD/strftime.c-				** From Arnold Robbins' strftime version 3.0:
../BSD/OpenBSD/strftime.c-				** "date as dd-bbb-YYYY"
../BSD/OpenBSD/strftime.c-				** (ado, 1993-05-24)
../BSD/OpenBSD/strftime.c-				*/
../BSD/OpenBSD/strftime.c-				pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
../BSD/OpenBSD/strftime.c-				continue;
../BSD/OpenBSD/strftime.c-			case 'W':
--
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/man/date.1:%q
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/man/date.1-quarter of year (1..4)
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/man/date.1-.TP
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/man/date.1-%r
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/man/date.1-locale's 12\-hour clock time (e.g., 11:11:04 PM)
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/man/date.1-.TP
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/man/date.1-%R
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/man/date.1-24\-hour hour and minute; same as %H:%M
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/man/date.1-.TP
--
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/src/date.c:  %q   quarter of year (1..4)\n\
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/src/date.c-  %r   locale's 12-hour clock time (e.g., 11:11:04 PM)\n\
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/src/date.c-  %R   24-hour hour and minute; same as %H:%M\n\
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/src/date.c-  %s   seconds since the Epoch (1970-01-01 00:00 UTC)\n\
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/src/date.c-"), stdout);
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/src/date.c-      fputs (_("\
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/src/date.c-  %S   second (00..60)\n\
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/src/date.c-  %t   a tab\n\
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/src/date.c-  %T   time; same as %H:%M:%S\n\
--
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c:  /* Check %q.  */
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-  for (mon = 1; mon <= 12; mon++)
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-    {
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-      char out[2];
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-      char exp[2] = {0,};
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-      struct tm qtm = { .tm_mon = mon - 1 };
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c:      char fmt[3] = {'%','q','\0'};
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-      size_t r = nstrftime (out, sizeof (out), fmt, &qtm, 0, 0);
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-      if (r == 0)
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-        {
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c:          puts ("nstrftime(\"%q\") failed");
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-          result = 1;
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-          break;
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-        }
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-      exp[0] = mon < 4 ? '1' : mon < 7 ? '2' : mon < 10 ? '3' : '4';
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-      if (strcmp (out, exp) != 0)
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-        {
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c:          printf ("nstrftime %%q: expected \"%s\", got \"%s\"\n", exp, out);
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-          result = 1;
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-          break;
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-        }
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-    }
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-  return result;
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-}
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/gnulib-tests/test-nstrftime.c-
--
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c:        case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-        case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c:        case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c:        case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-        case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-        case L_('~'):
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-          /* The C Standard requires these 98 characters (plus '%') to
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-             be in the basic execution character set.  None of these
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-             characters can start a multibyte sequence, so they need
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-             not be analyzed further.  */
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-          add1 (*f);
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-          continue;
--
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c:        case L_('q'):           /* GNU extension.  */
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-          DO_SIGNED_NUMBER (1, false, ((tp->tm_mon * 11) >> 5) + 1);
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-          break;
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-        case L_('R'):
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-          subfmt = L_("%H:%M");
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-          goto subformat;
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-
../cygwin/coreutils/coreutils-9.0-1.x86_64/origsrc/coreutils-9.0/lib/nstrftime.c-        case L_('r'):
--
../glibc/time/strftime_l.c:	case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
../glibc/time/strftime_l.c-	case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
../glibc/time/strftime_l.c:	case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
../glibc/time/strftime_l.c:	case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
../glibc/time/strftime_l.c-	case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
../glibc/time/strftime_l.c-	case L_('~'):
../glibc/time/strftime_l.c-	  /* The C Standard requires these 98 characters (plus '%') to
../glibc/time/strftime_l.c-	     be in the basic execution character set.  None of these
../glibc/time/strftime_l.c-	     characters can start a multibyte sequence, so they need
../glibc/time/strftime_l.c-	     not be analyzed further.  */
../glibc/time/strftime_l.c-	  add (1, *p = *f);
../glibc/time/strftime_l.c-	  continue;
--
../gnulib/lib/nstrftime.c:        case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'):
../gnulib/lib/nstrftime.c-        case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'):
../gnulib/lib/nstrftime.c:        case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'):
../gnulib/lib/nstrftime.c:        case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'):
../gnulib/lib/nstrftime.c-        case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'):
../gnulib/lib/nstrftime.c-        case L_('~'):
../gnulib/lib/nstrftime.c-          /* The C Standard requires these 98 characters (plus '%') to
../gnulib/lib/nstrftime.c-             be in the basic execution character set.  None of these
../gnulib/lib/nstrftime.c-             characters can start a multibyte sequence, so they need
../gnulib/lib/nstrftime.c-             not be analyzed further.  */
../gnulib/lib/nstrftime.c-          add1 (*f);
../gnulib/lib/nstrftime.c-          continue;
--
../gnulib/lib/nstrftime.c:        case L_('q'):           /* GNU extension.  */
../gnulib/lib/nstrftime.c-          DO_SIGNED_NUMBER (1, false, ((tp->tm_mon * 11) >> 5) + 1);
../gnulib/lib/nstrftime.c-
../gnulib/lib/nstrftime.c-        case L_('R'):
../gnulib/lib/nstrftime.c-          subfmt = L_("%H:%M");
../gnulib/lib/nstrftime.c-          goto subformat;
../gnulib/lib/nstrftime.c-
../gnulib/lib/nstrftime.c-        case L_('r'):
../gnulib/lib/nstrftime.c-#ifdef _NL_CURRENT
--
../gnulib/lib/strptime.c:        case 'q':
../gnulib/lib/strptime.c-          /* Match quarter of year.  GNU extension.  */
../gnulib/lib/strptime.c-          get_number (1, 4, 1);
../gnulib/lib/strptime.c-          tm->tm_mon = (val - 1) * 3;
../gnulib/lib/strptime.c-          tm->tm_mday = 1;
../gnulib/lib/strptime.c-          have_mon = 1;
../gnulib/lib/strptime.c-          have_mday = 1;
../gnulib/lib/strptime.c-          want_xday = 1;
../gnulib/lib/strptime.c-          break;
--
../gnulib/lib/strptime.c:            case 'q':
../gnulib/lib/strptime.c-              /* Match quarter using alternate numeric symbols.  */
../gnulib/lib/strptime.c-              get_alt_number (1, 4, 1);
../gnulib/lib/strptime.c-              tm->tm_mon = (val - 1) * 3;
../gnulib/lib/strptime.c-              tm->tm_mday = 1;
../gnulib/lib/strptime.c-              have_mon = 1;
../gnulib/lib/strptime.c-              have_mday = 1;
../gnulib/lib/strptime.c-              want_xday = 1;
../gnulib/lib/strptime.c-              break;


More information about the Newlib mailing list