Cygwin: strptime: fix am/pm handling
The %p format specifier is handled immediately. It requires
that tm_hour is already set. This falls flat in case the am/pm
marker preceeds the time specification. Locales with am/pm
marker preceeding time spec by default exist (e. g. ko_KR).
Also, the code expects that tm_hour might be set to an invalid
value because the %p specifier is used in conjunction with %H.
But this usage is invalid in itself and now catched as error
condition after commit 343a2a5581
("Cygwin: strptime: make
sure to fail on invalid input digits").
Change the %H/%I/%p handling according to GLibC, i. e.
- fix tm_hour for pm only if the time value has been specified
as 12 hour time %I, and
- perform the fixup only after the entire input has been scanned.
This decouples the fixup from the %p position relativ to %I.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
f0ab27c095
commit
4fe5b1d77b
|
@ -335,6 +335,8 @@ __strptime(const char *buf, const char *fmt, struct tm *tm,
|
||||||
const char *new_fmt;
|
const char *new_fmt;
|
||||||
uint ulim;
|
uint ulim;
|
||||||
int ymd = 0;
|
int ymd = 0;
|
||||||
|
bool got_I = false;
|
||||||
|
bool got_pm = false;
|
||||||
|
|
||||||
bp = (const unsigned char *)buf;
|
bp = (const unsigned char *)buf;
|
||||||
const struct lc_time_T *_CurrentTimeLocale = __get_time_locale (locale);
|
const struct lc_time_T *_CurrentTimeLocale = __get_time_locale (locale);
|
||||||
|
@ -537,6 +539,7 @@ literal:
|
||||||
case 'H':
|
case 'H':
|
||||||
LEGAL_ALT(ALT_O);
|
LEGAL_ALT(ALT_O);
|
||||||
bp = conv_num(bp, &tm->tm_hour, 0, 23, ALT_DIGITS);
|
bp = conv_num(bp, &tm->tm_hour, 0, 23, ALT_DIGITS);
|
||||||
|
got_I = false;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 'l': /* The hour (12-hour clock representation). */
|
case 'l': /* The hour (12-hour clock representation). */
|
||||||
|
@ -547,6 +550,7 @@ literal:
|
||||||
bp = conv_num(bp, &tm->tm_hour, 1, 12, ALT_DIGITS);
|
bp = conv_num(bp, &tm->tm_hour, 1, 12, ALT_DIGITS);
|
||||||
if (tm->tm_hour == 12)
|
if (tm->tm_hour == 12)
|
||||||
tm->tm_hour = 0;
|
tm->tm_hour = 0;
|
||||||
|
got_I = true;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 'j': /* The day of year. */
|
case 'j': /* The day of year. */
|
||||||
|
@ -573,9 +577,7 @@ literal:
|
||||||
case 'p': /* The locale's equivalent of AM/PM. */
|
case 'p': /* The locale's equivalent of AM/PM. */
|
||||||
bp = find_string(bp, &i, _ctloc(am_pm), NULL, 2,
|
bp = find_string(bp, &i, _ctloc(am_pm), NULL, 2,
|
||||||
locale);
|
locale);
|
||||||
if (tm->tm_hour > 11)
|
got_pm = (i == 1);
|
||||||
return NULL;
|
|
||||||
tm->tm_hour += i * 12;
|
|
||||||
LEGAL_ALT(0);
|
LEGAL_ALT(0);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -751,8 +753,12 @@ literal:
|
||||||
default: /* Unknown/unsupported conversion. */
|
default: /* Unknown/unsupported conversion. */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (got_I && got_pm)
|
||||||
|
tm->tm_hour += 12;
|
||||||
|
|
||||||
if (bp && (era || got_eoff))
|
if (bp && (era || got_eoff))
|
||||||
{
|
{
|
||||||
/* Default to current era. */
|
/* Default to current era. */
|
||||||
|
|
Loading…
Reference in New Issue