On 04/11/16 11:33, Rafal Luzynski wrote:
> Hi,
>
> Shouldn't strptime() family also support the same?
I was debating that, but you're right,
strptime() should support that for consistency.
Updated patch is attached, which also adjusts
to Paul Eggert's optimization.
thanks,
Pádraig
From ad0ed0247612bf7d85afe1af0c8a61e804db274c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com>
Date: Thu, 3 Nov 2016 19:36:59 +0000
Subject: [PATCH] strftime,strptime: have %q represent the quarter of year
This is already supported by gnulib, and for example
simplifies quarter determination at the shell, which
currently needs to use "$(( ($(date +%-m)-1)/3+1 ))".
* manual/time.texi: Document %q for str[fp]time.
* time/strftime_l.c: Implement %q.
* time/strptime_l.c: Likewise.
* time/tst-strftime.c: Add a test case.
* time/tst-strptime3.c: Likewise.
* NEWS: Mention the new feature.
---
NEWS | 3 +++
manual/time.texi | 12 ++++++++++++
time/strftime_l.c | 7 +++++++
time/strptime_l.c | 18 ++++++++++++++++++
time/tst-strftime.c | 25 +++++++++++++++++++++++++
time/tst-strptime3.c | 20 ++++++++++++++++++++
6 files changed, 85 insertions(+)
@@ -119,6 +119,9 @@ Version 2.25
variable for a particular architecture in the GCC source file
'gcc/config.gcc'.
+* strftime and strptime now support the %q directive to represent
+ the quarter of the year, with January starting the first quarter.
+
Security related changes:
On ARM EABI (32-bit), generating a backtrace for execution contexts which
@@ -1510,6 +1510,12 @@ most locales @samp{AM}/@samp{PM} format is not supported, in such cases
This format is a GNU extension.
+@item %q
+Quarter of the year (@samp{1}@dots{}@samp{4}),
+with January starting the first quarter.
+
+This format is a GNU extension.
+
@item %r
The complete calendar time using the AM/PM format of the current locale.
@@ -1926,6 +1932,12 @@ all and therefore the conversion fails.
@code{%P} is a GNU extension following a GNU extension to @code{strftime}.
+@item %q
+Quarter of the year (@samp{1}@dots{}@samp{4}),
+with January starting the first quarter.
+
+This format is a GNU extension.
+
@item %r
The complete time using the AM/PM format of the current locale.
@@ -1085,6 +1085,13 @@ __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format,
goto underlying_strftime;
#endif
+ case L_('q'): /* Quarter of year. GNU extension. */
+ if (modifier == L_('E'))
+ goto bad_format;
+
+ DO_NUMBER (1, ((tp->tm_mon * 11) >> 5) + 1);
+ break;
+
case L_('R'):
subfmt = L_("%H:%M");
goto subformat;
@@ -593,6 +593,15 @@ __strptime_internal (const char *rp, const char *fmt, struct tm *tmp,
else
s.is_pm = 0;
break;
+ case 'q':
+ /* Match quarter of year. GNU extension. */
+ get_number (1, 4, 1);
+ tm->tm_mon = (val - 1) * 3;
+ tm->tm_mday = 1;
+ s.have_mon = 1;
+ s.have_mday = 1;
+ s.want_xday = 1;
+ break;
case 'r':
#ifdef _NL_CURRENT
if (s.decided != raw)
@@ -1050,6 +1059,15 @@ __strptime_internal (const char *rp, const char *fmt, struct tm *tmp,
get_alt_number (0, 59, 2);
tm->tm_min = val;
break;
+ case 'q':
+ /* Match quarter using alternate numeric symbols. */
+ get_alt_number (1, 4, 1);
+ tm->tm_mon = (val - 1) * 3;
+ tm->tm_mday = 1;
+ s.have_mon = 1;
+ s.have_mday = 1;
+ s.want_xday = 1;
+ break;
case 'S':
/* Match seconds using alternate numeric symbols. */
get_alt_number (0, 61, 2);
@@ -154,6 +154,31 @@ do_test (void)
}
}
+ /* Check %q. */
+ for (size_t mon = 1; mon <= 12; mon++)
+ {
+ char out[2];
+ char exp[2] = {0,};
+ struct tm qtm = { .tm_mon = mon - 1 };
+ char fmt[3] = {'%','q','\0'};
+
+ size_t r = strftime (out, sizeof (out), fmt, &qtm);
+ if (r == 0)
+ {
+ puts ("strftime(\"%q\") failed");
+ result = 1;
+ break;
+ }
+
+ exp[0] = mon < 4 ? '1' : mon < 7 ? '2' : mon < 10 ? '3' : '4';
+ if (strcmp (out, exp) != 0)
+ {
+ printf ("strftime %%q: expected \"%s\", got \"%s\"\n", exp, out);
+ result = 1;
+ break;
+ }
+ }
+
return result + do_bz18985 ();
}
@@ -48,6 +48,26 @@ do_test (void)
result = 1;
}
+ memset (&tm, 0xaa, sizeof (tm));
+ for (size_t q = 1; q <= 4; q++)
+ {
+ char in[2] = {0,};
+ in[0] = q + '0';
+ int exp_mon = q == 1 ? 0 : q == 2 ? 3 : q == 3 ? 6 : 9;
+ char fmt[3] = {'%','q','\0'};
+
+ if (strptime (in, fmt, &tm) == NULL)
+ {
+ puts ("strptime failed");
+ result = 1;
+ }
+ if (tm.tm_mon != exp_mon || tm.tm_mday != 1)
+ {
+ puts ("unexpected tm content");
+ result = 1;
+ }
+ }
+
return result;
}
--
2.5.5