* libc/time/strptime.c (strptime): Fill in tm_yday when all of tm_year,
tm_mon and tm_mday are updated. Fill in tm_mon, tm_mday and tm_wday when both of tm_year and tm_yday are updated.
This commit is contained in:
parent
7bb76e751b
commit
4d1bf2fbb8
|
@ -1,3 +1,9 @@
|
|||
2011-05-12 Peter Rosin <peda@lysator.liu.se>
|
||||
|
||||
* libc/time/strptime.c (strptime): Fill in tm_yday when all of tm_year,
|
||||
tm_mon and tm_mday are updated. Fill in tm_mon, tm_mday and tm_wday
|
||||
when both of tm_year and tm_yday are updated.
|
||||
|
||||
2011-05-12 Peter Rosin <peda@lysator.liu.se>
|
||||
|
||||
* libc/time/strptime.c (first_day): Actually return the wday
|
||||
|
|
|
@ -40,6 +40,16 @@
|
|||
|
||||
#define _ctloc(x) (_CurrentTimeLocale->x)
|
||||
|
||||
static _CONST int _DAYS_BEFORE_MONTH[12] =
|
||||
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
|
||||
|
||||
#define SET_MDAY 1
|
||||
#define SET_MON 2
|
||||
#define SET_YEAR 4
|
||||
#define SET_WDAY 8
|
||||
#define SET_YDAY 16
|
||||
#define SET_YMD (SET_YEAR | SET_MON | SET_MDAY)
|
||||
|
||||
/*
|
||||
* tm_year is relative this year
|
||||
*/
|
||||
|
@ -147,6 +157,7 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
struct tm *timeptr)
|
||||
{
|
||||
char c;
|
||||
int ymd = 0;
|
||||
|
||||
struct lc_time_T *_CurrentTimeLocale = __get_current_time_locale ();
|
||||
for (; (c = *format) != '\0'; ++format) {
|
||||
|
@ -166,18 +177,21 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
if (ret < 0)
|
||||
return NULL;
|
||||
timeptr->tm_wday = ret;
|
||||
ymd |= SET_WDAY;
|
||||
break;
|
||||
case 'a' :
|
||||
ret = match_string (&buf, _ctloc (wday));
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
timeptr->tm_wday = ret;
|
||||
ymd |= SET_WDAY;
|
||||
break;
|
||||
case 'B' :
|
||||
ret = match_string (&buf, _ctloc (month));
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
timeptr->tm_mon = ret;
|
||||
ymd |= SET_MON;
|
||||
break;
|
||||
case 'b' :
|
||||
case 'h' :
|
||||
|
@ -185,6 +199,7 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
if (ret < 0)
|
||||
return NULL;
|
||||
timeptr->tm_mon = ret;
|
||||
ymd |= SET_MON;
|
||||
break;
|
||||
case 'C' :
|
||||
ret = strtol (buf, &s, 10);
|
||||
|
@ -192,18 +207,21 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
return NULL;
|
||||
timeptr->tm_year = (ret * 100) - tm_year_base;
|
||||
buf = s;
|
||||
ymd |= SET_YEAR;
|
||||
break;
|
||||
case 'c' : /* %a %b %e %H:%M:%S %Y */
|
||||
s = strptime (buf, _ctloc (c_fmt), timeptr);
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
buf = s;
|
||||
ymd |= SET_WDAY | SET_YMD;
|
||||
break;
|
||||
case 'D' : /* %m/%d/%y */
|
||||
s = strptime (buf, "%m/%d/%y", timeptr);
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
buf = s;
|
||||
ymd |= SET_YMD;
|
||||
break;
|
||||
case 'd' :
|
||||
case 'e' :
|
||||
|
@ -212,6 +230,7 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
return NULL;
|
||||
timeptr->tm_mday = ret;
|
||||
buf = s;
|
||||
ymd |= SET_MDAY;
|
||||
break;
|
||||
case 'H' :
|
||||
case 'k' :
|
||||
|
@ -238,6 +257,7 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
return NULL;
|
||||
timeptr->tm_yday = ret - 1;
|
||||
buf = s;
|
||||
ymd |= SET_YDAY;
|
||||
break;
|
||||
case 'm' :
|
||||
ret = strtol (buf, &s, 10);
|
||||
|
@ -245,6 +265,7 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
return NULL;
|
||||
timeptr->tm_mon = ret - 1;
|
||||
buf = s;
|
||||
ymd |= SET_MON;
|
||||
break;
|
||||
case 'M' :
|
||||
ret = strtol (buf, &s, 10);
|
||||
|
@ -306,6 +327,7 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
return NULL;
|
||||
timeptr->tm_wday = ret - 1;
|
||||
buf = s;
|
||||
ymd |= SET_WDAY;
|
||||
break;
|
||||
case 'w' :
|
||||
ret = strtol (buf, &s, 10);
|
||||
|
@ -313,6 +335,7 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
return NULL;
|
||||
timeptr->tm_wday = ret;
|
||||
buf = s;
|
||||
ymd |= SET_WDAY;
|
||||
break;
|
||||
case 'U' :
|
||||
ret = strtol (buf, &s, 10);
|
||||
|
@ -320,6 +343,7 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
return NULL;
|
||||
set_week_number_sun (timeptr, ret);
|
||||
buf = s;
|
||||
ymd |= SET_YDAY;
|
||||
break;
|
||||
case 'V' :
|
||||
ret = strtol (buf, &s, 10);
|
||||
|
@ -327,6 +351,7 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
return NULL;
|
||||
set_week_number_mon4 (timeptr, ret);
|
||||
buf = s;
|
||||
ymd |= SET_YDAY;
|
||||
break;
|
||||
case 'W' :
|
||||
ret = strtol (buf, &s, 10);
|
||||
|
@ -334,12 +359,14 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
return NULL;
|
||||
set_week_number_mon (timeptr, ret);
|
||||
buf = s;
|
||||
ymd |= SET_YDAY;
|
||||
break;
|
||||
case 'x' :
|
||||
s = strptime (buf, _ctloc (x_fmt), timeptr);
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
buf = s;
|
||||
ymd |= SET_YMD;
|
||||
break;
|
||||
case 'X' :
|
||||
s = strptime (buf, _ctloc (X_fmt), timeptr);
|
||||
|
@ -356,6 +383,7 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
else
|
||||
timeptr->tm_year = ret;
|
||||
buf = s;
|
||||
ymd |= SET_YEAR;
|
||||
break;
|
||||
case 'Y' :
|
||||
ret = strtol (buf, &s, 10);
|
||||
|
@ -363,6 +391,7 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
return NULL;
|
||||
timeptr->tm_year = ret - tm_year_base;
|
||||
buf = s;
|
||||
ymd |= SET_YEAR;
|
||||
break;
|
||||
case 'Z' :
|
||||
/* Unsupported. Just ignore. */
|
||||
|
@ -390,6 +419,58 @@ _DEFUN (strptime, (buf, format, timeptr),
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ymd & SET_YMD) == SET_YMD) {
|
||||
/* all of tm_year, tm_mon and tm_mday, but... */
|
||||
|
||||
if (!(ymd & SET_YDAY)) {
|
||||
/* ...not tm_yday, so fill it in */
|
||||
timeptr->tm_yday = _DAYS_BEFORE_MONTH[timeptr->tm_mon]
|
||||
+ timeptr->tm_mday;
|
||||
if (!is_leap_year (timeptr->tm_year + tm_year_base)
|
||||
|| timeptr->tm_mon < 2)
|
||||
{
|
||||
timeptr->tm_yday--;
|
||||
}
|
||||
ymd |= SET_YDAY;
|
||||
}
|
||||
}
|
||||
else if ((ymd & (SET_YEAR | SET_YDAY)) == (SET_YEAR | SET_YDAY)) {
|
||||
/* both of tm_year and tm_yday, but... */
|
||||
|
||||
if (!(ymd & SET_MON)) {
|
||||
/* ...not tm_mon, so fill it in, and/or... */
|
||||
if (timeptr->tm_yday < _DAYS_BEFORE_MONTH[1])
|
||||
timeptr->tm_mon = 0;
|
||||
else {
|
||||
int leap = is_leap_year (timeptr->tm_year + tm_year_base);
|
||||
int i;
|
||||
for (i = 2; i < 12; ++i) {
|
||||
if (timeptr->tm_yday < _DAYS_BEFORE_MONTH[i] + leap)
|
||||
break;
|
||||
}
|
||||
timeptr->tm_mon = i - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(ymd & SET_MDAY)) {
|
||||
/* ...not tm_mday, so fill it in */
|
||||
timeptr->tm_mday = timeptr->tm_yday
|
||||
- _DAYS_BEFORE_MONTH[timeptr->tm_mon];
|
||||
if (!is_leap_year (timeptr->tm_year + tm_year_base)
|
||||
|| timeptr->tm_mon < 2)
|
||||
{
|
||||
timeptr->tm_mday++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((ymd & (SET_YEAR | SET_YDAY | SET_WDAY)) == (SET_YEAR | SET_YDAY)) {
|
||||
/* fill in tm_wday */
|
||||
int fday = first_day (timeptr->tm_year + tm_year_base);
|
||||
timeptr->tm_wday = (fday + timeptr->tm_yday) % 7;
|
||||
}
|
||||
|
||||
return (char *)buf;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue