time: in strptime(), make %z accept [+-]HH:MM tz [BZ #17887]

In ISO 8601, +03:30 is a valid time zone. Currently, strptime() only
parses it as a 2-digit time zone an believes this is +03:00. This change
makes it accept a single colon.
This commit is contained in:
Vincent Bernat 2015-09-17 09:56:13 +02:00 committed by Mike Frysinger
parent 900f33e23e
commit e952e1dfeb
4 changed files with 38 additions and 13 deletions

View File

@ -1,3 +1,9 @@
2015-09-18 Vincent Bernat <vincent@bernat.im>
[BZ #17887]
* time/strptime_l.c (__strptime_internal): Make %z accept
[+-]HH:MM time zones.
2015-09-18 Vincent Bernat <vincent@bernat.im> 2015-09-18 Vincent Bernat <vincent@bernat.im>
[BZ #17886] [BZ #17886]

10
NEWS
View File

@ -11,11 +11,11 @@ Version 2.23
2542, 2543, 2558, 2898, 4404, 6803, 14341, 14912, 15384, 15786, 15918, 2542, 2543, 2558, 2898, 4404, 6803, 14341, 14912, 15384, 15786, 15918,
16141, 16296, 16415, 16517, 16519, 16520, 16521, 16734, 16973, 16985, 16141, 16296, 16415, 16517, 16519, 16520, 16521, 16734, 16973, 16985,
17118, 17243, 17244, 17787, 17886, 17905, 18084, 18086, 18240, 18265, 17118, 17243, 17244, 17787, 17886, 17887, 17905, 18084, 18086, 18240,
18370, 18421, 18480, 18525, 18595, 18610, 18618, 18647, 18661, 18674, 18265, 18370, 18421, 18480, 18525, 18595, 18610, 18618, 18647, 18661,
18675, 18681, 18757, 18778, 18781, 18787, 18789, 18790, 18795, 18796, 18674, 18675, 18681, 18757, 18778, 18781, 18787, 18789, 18790, 18795,
18820, 18823, 18824, 18857, 18863, 18870, 18872, 18873, 18875, 18887, 18796, 18820, 18823, 18824, 18857, 18863, 18870, 18872, 18873, 18875,
18921, 18951, 18952, 18961, 18966, 18967, 18970, 18977. 18887, 18921, 18951, 18952, 18961, 18966, 18967, 18970, 18977.
* The obsolete header <regexp.h> has been removed. Programs that require * The obsolete header <regexp.h> has been removed. Programs that require
this header must be updated to use <regex.h> instead. this header must be updated to use <regex.h> instead.

View File

@ -749,9 +749,11 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM)
rp++; rp++;
break; break;
case 'z': case 'z':
/* We recognize three formats: if two digits are given, these /* We recognize four formats:
specify hours. If fours digits are used, minutes are 1. Two digits specify hours.
also specified. 'Z' is equivalent to +0000. */ 2. Four digits specify hours and minutes.
3. Two digits, ':', and two digits specify hours and minutes.
4. 'Z' is equivalent to +0000. */
{ {
val = 0; val = 0;
while (ISSPACE (*rp)) while (ISSPACE (*rp))
@ -770,6 +772,8 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM)
{ {
val = val * 10 + *rp++ - '0'; val = val * 10 + *rp++ - '0';
++n; ++n;
if (*rp == ':' && n == 2 && isdigit (*(rp + 1)))
++rp;
} }
if (n == 2) if (n == 2)
val *= 100; val *= 100;

View File

@ -35,7 +35,8 @@ static bool verbose;
following fields: following fields:
Sign field consisting of a '+' or '-' sign, Sign field consisting of a '+' or '-' sign,
Hours field in two decimal digits, and Hours field in two decimal digits, and
optional Minutes field in two decimal digits. optional Minutes field in two decimal digits. Optionally,
a ':' is used to seperate hours and minutes.
This function may write test strings with minutes values outside This function may write test strings with minutes values outside
the valid range 00-59. These are invalid strings and useful for the valid range 00-59. These are invalid strings and useful for
@ -56,7 +57,7 @@ static bool verbose;
range of 00 to 59. */ range of 00 to 59. */
static long int static long int
mkbuf (char *buf, bool neg, unsigned int hhmm, size_t ndigits) mkbuf (char *buf, bool neg, bool colon, unsigned int hhmm, size_t ndigits)
{ {
const int mm_max = 59; const int mm_max = 59;
char sign = neg ? '-' : '+'; char sign = neg ? '-' : '+';
@ -66,7 +67,10 @@ mkbuf (char *buf, bool neg, unsigned int hhmm, size_t ndigits)
long int expect = LONG_MAX; long int expect = LONG_MAX;
i = sprintf (buf, "%s %c", dummy_string, sign); i = sprintf (buf, "%s %c", dummy_string, sign);
snprintf (buf + i, ndigits + 1, "%04u", hhmm); if (colon)
snprintf (buf + i, ndigits + 2, "%02u:%02u", hh, mm);
else
snprintf (buf + i, ndigits + 1, "%04u", hhmm);
if (mm <= mm_max && (ndigits == 2 || ndigits == 4)) if (mm <= mm_max && (ndigits == 2 || ndigits == 4))
{ {
@ -177,11 +181,22 @@ do_test (void)
{ {
/* Test both positive and negative signs. */ /* Test both positive and negative signs. */
expect = mkbuf (buf, false, hhmm, ndigits); expect = mkbuf (buf, false, false, hhmm, ndigits);
result |= compare (buf, expect, nresult); result |= compare (buf, expect, nresult);
expect = mkbuf (buf, true, hhmm, ndigits); expect = mkbuf (buf, true, false, hhmm, ndigits);
result |= compare (buf, expect, nresult); result |= compare (buf, expect, nresult);
/* Test with colon as well. */
if (ndigits >= 3)
{
expect = mkbuf (buf, false, true, hhmm, ndigits);
result |= compare (buf, expect, nresult);
expect = mkbuf (buf, true, true, hhmm, ndigits);
result |= compare (buf, expect, nresult);
}
} }
if (result > 0 || verbose) if (result > 0 || verbose)