Пример #1
0
ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
strptime (const char *buf, const char *format, struct tm *timeptr)
{
    char c;

    for (; (c = *format) != '\0'; ++format) {
	char *s;
	int ret;

	if (isspace ((unsigned char)c)) {
	    while (isspace ((unsigned char)*buf))
		++buf;
	} else if (c == '%' && format[1] != '\0') {
	    c = *++format;
	    if (c == 'E' || c == 'O')
		c = *++format;
	    switch (c) {
	    case 'A' :
		ret = match_string (&buf, full_weekdays);
		if (ret < 0)
		    return NULL;
		timeptr->tm_wday = ret;
		break;
	    case 'a' :
		ret = match_string (&buf, abb_weekdays);
		if (ret < 0)
		    return NULL;
		timeptr->tm_wday = ret;
		break;
	    case 'B' :
		ret = match_string (&buf, full_month);
		if (ret < 0)
		    return NULL;
		timeptr->tm_mon = ret;
		break;
	    case 'b' :
	    case 'h' :
		ret = match_string (&buf, abb_month);
		if (ret < 0)
		    return NULL;
		timeptr->tm_mon = ret;
		break;
	    case 'C' :
		if (parse_number(&buf, 2, &ret))
		    return NULL;
		timeptr->tm_year = (ret * 100) - tm_year_base;
		break;
	    case 'c' :
		abort ();
	    case 'D' :		/* %m/%d/%y */
		s = strptime (buf, "%m/%d/%y", timeptr);
		if (s == NULL)
		    return NULL;
		buf = s;
		break;
	    case 'd' :
	    case 'e' :
		if (parse_number(&buf, 2, &ret))
		    return NULL;
		timeptr->tm_mday = ret;
		break;
	    case 'H' :
	    case 'k' :
		if (parse_number(&buf, 2, &ret))
		    return NULL;
		timeptr->tm_hour = ret;
		break;
	    case 'I' :
	    case 'l' :
		if (parse_number(&buf, 2, &ret))
		    return NULL;
		if (ret == 12)
		    timeptr->tm_hour = 0;
		else
		    timeptr->tm_hour = ret;
		break;
	    case 'j' :
		if (parse_number(&buf, 3, &ret))
		    return NULL;
		if (ret == 0)
		    return NULL;
		timeptr->tm_yday = ret - 1;
		break;
	    case 'm' :
		if (parse_number(&buf, 2, &ret))
		    return NULL;
		if (ret == 0)
		    return NULL;
		timeptr->tm_mon = ret - 1;
		break;
	    case 'M' :
		if (parse_number(&buf, 2, &ret))
		    return NULL;
		timeptr->tm_min = ret;
		break;
	    case 'n' :
		while (isspace ((unsigned char)*buf))
		    buf++;
		break;
	    case 'p' :
		ret = match_string (&buf, ampm);
		if (ret < 0)
		    return NULL;
		if (timeptr->tm_hour == 0) {
		    if (ret == 1)
			timeptr->tm_hour = 12;
		} else
		    timeptr->tm_hour += 12;
		break;
	    case 'r' :		/* %I:%M:%S %p */
		s = strptime (buf, "%I:%M:%S %p", timeptr);
		if (s == NULL)
		    return NULL;
		buf = s;
		break;
	    case 'R' :		/* %H:%M */
		s = strptime (buf, "%H:%M", timeptr);
		if (s == NULL)
		    return NULL;
		buf = s;
		break;
	    case 'S' :
		if (parse_number(&buf, 2, &ret))
		    return NULL;
		timeptr->tm_sec = ret;
		break;
	    case 't' :
		while (isspace ((unsigned char)*buf))
		    buf++;
		break;
	    case 'T' :		/* %H:%M:%S */
	    case 'X' :
		s = strptime (buf, "%H:%M:%S", timeptr);
		if (s == NULL)
		    return NULL;
		buf = s;
		break;
	    case 'u' :
		if (parse_number(&buf, 1, &ret))
		    return NULL;
		if (ret <= 0)
		    return NULL;
		timeptr->tm_wday = ret - 1;
		break;
	    case 'w' :
		if (parse_number(&buf, 1, &ret))
		    return NULL;
		timeptr->tm_wday = ret;
		break;
	    case 'U' :
		if (parse_number(&buf, 2, &ret))
		    return NULL;
		set_week_number_sun (timeptr, ret);
		break;
	    case 'V' :
		if (parse_number(&buf, 2, &ret))
		    return NULL;
		set_week_number_mon4 (timeptr, ret);
		break;
	    case 'W' :
		if (parse_number(&buf, 2, &ret))
		    return NULL;
		set_week_number_mon (timeptr, ret);
		break;
	    case 'x' :
		s = strptime (buf, "%Y:%m:%d", timeptr);
		if (s == NULL)
		    return NULL;
		buf = s;
		break;
	    case 'y' :
		if (parse_number(&buf, 2, &ret))
		    return NULL;
		if (ret < 70)
		    timeptr->tm_year = 100 + ret;
		else
		    timeptr->tm_year = ret;
		break;
	    case 'Y' :
		if (parse_number(&buf, 4, &ret))
		    return NULL;
		timeptr->tm_year = ret - tm_year_base;
		break;
	    case 'Z' :
		abort ();
	    case '\0' :
		--format;
		/* FALLTHROUGH */
	    case '%' :
		if (*buf == '%')
		    ++buf;
		else
		    return NULL;
		break;
	    default :
		if (*buf == '%' || *++buf == c)
		    ++buf;
		else
		    return NULL;
		break;
	    }
	} else {
	    if (*buf == c)
		++buf;
	    else
		return NULL;
	}
    }
    return rk_UNCONST(buf);
}
Пример #2
0
HTTPCHAR *__strptime(HTTPCSTR buf, HTTPCSTR format, struct tm *timeptr) {
HTTPCHAR c;

for (; (c = *format) != _T('\0'); ++format) {
HTTPCHAR *s;
int ret;

if (isspace(c)) {
	while (isspace(*buf))
		++buf;
}
else if (c == _T('%') && format[1] != _T('\0')) {
	c = *++format;
	if (c == _T('E') || c == _T('O'))
		c = *++format;
	switch (c) {
	case _T('A'):
		ret = match_string(&buf, full_weekdays);
		if (ret < 0)
			return NULL;
		timeptr->tm_wday = ret;
		break;
	case _T('a'):
		ret = match_string(&buf, abb_weekdays);
		if (ret < 0)
			return NULL;
		timeptr->tm_wday = ret;
		break;
	case _T('B'):
		ret = match_string(&buf, full_month);
		if (ret < 0)
			return NULL;
		timeptr->tm_mon = ret;
		break;
	case _T('b'):
	case _T('h'):
		ret = match_string(&buf, abb_month);
		if (ret < 0)
			return NULL;
		timeptr->tm_mon = ret;
		break;
	case _T('C'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		timeptr->tm_year = (ret * 100) - tm_year_base;
		buf = s;
		break;
	case _T('c'):
		abort();
	case _T('D'): /* %m/%d/%y */
		s = __strptime(buf, _T("%m/%d/%y"), timeptr);
		if (s == NULL)
			return NULL;
		buf = s;
		break;
	case _T('d'):
	case _T('e'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		timeptr->tm_mday = ret;
		buf = s;
		break;
	case _T('H'):
	case _T('k'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		timeptr->tm_hour = ret;
		buf = s;
		break;
	case _T('I'):
	case _T('l'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		if (ret == 12)
			timeptr->tm_hour = 0;
		else
			timeptr->tm_hour = ret;
		buf = s;
		break;
	case _T('j'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		timeptr->tm_yday = ret - 1;
		buf = s;
		break;
	case _T('m'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		timeptr->tm_mon = ret - 1;
		buf = s;
		break;
	case _T('M'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		timeptr->tm_min = ret;
		buf = s;
		break;
	case _T('n'):
		if (*buf == _T('\n'))
			++buf;
		else
			return NULL;
		break;
	case _T('p'):
		ret = match_string(&buf, ampm);
		if (ret < 0)
			return NULL;
		if (timeptr->tm_hour == 0) {
			if (ret == 1)
				timeptr->tm_hour = 12;
		}
		else
			timeptr->tm_hour += 12;
		break;
	case _T('r'): /* %I:%M:%S %p */
		s = __strptime(buf, _T("%I:%M:%S %p"), timeptr);
		if (s == NULL)
			return NULL;
		buf = s;
		break;
	case _T('R'): /* %H:%M */
		s = __strptime(buf, _T("%H:%M"), timeptr);
		if (s == NULL)
			return NULL;
		buf = s;
		break;
	case _T('S'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		timeptr->tm_sec = ret;
		buf = s;
		break;
	case _T('t'):
		if (*buf == _T('\t'))
			++buf;
		else
			return NULL;
		break;
	case _T('T'): /* %H:%M:%S */
	case _T('X'):
		s = __strptime(buf, _T("%H:%M:%S"), timeptr);
		if (s == NULL)
			return NULL;
		buf = s;
		break;
	case _T('u'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		timeptr->tm_wday = ret - 1;
		buf = s;
		break;
	case _T('w'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		timeptr->tm_wday = ret;
		buf = s;
		break;
	case _T('U'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		set_week_number_sun(timeptr, ret);
		buf = s;
		break;
	case _T('V'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		set_week_number_mon4(timeptr, ret);
		buf = s;
		break;
	case _T('W'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		set_week_number_mon(timeptr, ret);
		buf = s;
		break;
	case _T('x'):
		s = __strptime(buf, _T("%Y:%m:%d"), timeptr);
		if (s == NULL)
			return NULL;
		buf = s;
		break;
	case _T('y'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		if (ret < 70)
			timeptr->tm_year = 100 + ret;
		else
			timeptr->tm_year = ret;
		buf = s;
		break;
	case _T('Y'):
		ret = _tcstol(buf, &s, 10);
		if (s == buf)
			return NULL;
		timeptr->tm_year = ret - tm_year_base;
		buf = s;
		break;
	case _T('Z'):
		abort();
	case _T('\0'):
		--format;
		/* FALLTHROUGH */
	case _T('%'):
		if (*buf == _T('%'))
			++buf;
		else
			return NULL;
		break;
	default:
		if (*buf == _T('%') || *++buf == c)
			++buf;
		else
			return NULL;
		break;
	}
}
else {
	if (*buf == c)
		++buf;
	else
		return NULL;
}
}
return (HTTPCHAR *)buf;
}
Пример #3
0
char *
xstrptime(const char *buf, const char *format, struct tm *timeptr)
{
  char c;
  char t[33];

  memset(timeptr, 0, sizeof(struct tm));

  for (; (c = *format) != '\0'; format++){
    char *s;
    int ret;

    if (isspace(c)){
      while (isspace(*buf))
        buf++;
    }
    else if (c == '%' && format[1] != '\0'){
      c = *++format;

      if (c == 'E' || c == 'O')
        c = *++format;

RETRY:
      memset(t, '\0', 33);

      switch (c){
        case 'A':
          ret = match_string(&buf, full_weekdays);
          if (ret < 0)
            return NULL;
          timeptr->tm_wday = ret;
          break;

        case 'a':
          ret = match_string(&buf, abb_weekdays);
          if (ret < 0)
            return NULL;
          timeptr->tm_mon = ret;
          break;

        case 'B':
          ret = match_string(&buf, full_month);
          if (ret < 0)
            return NULL;
          timeptr->tm_mon = ret;
          break;

        case 'b':
        case 'h':
          ret = match_string(&buf, abb_month);
          if (ret < 0){
              c = 'H';
              goto RETRY;
          }
          else{
            timeptr->tm_mon = ret;
            break;
          }

        case 'C':
          ret = strtol(buf, &s, 10);
          if (s == buf)
            return NULL;
          timeptr->tm_year = (ret * 100) - tm_year_base;
          buf = s;
          break;

        // This also designates MySQL ordinal date
        case 'D':
          s = xstrptime(buf, "%m/%d/%y", timeptr);
          if (s == NULL){
            ret = strtol(buf, &s, 10);
            if (s == buf)
              return NULL;

            timeptr->tm_mday = ret;
            buf = s+2;
          }
          else{
            buf = s;
          }

          break;

        case 'd':
        case 'e':
          strncpy(t, buf, 2);
          ret = strtol(t, &s, 10);
          if (s == t)
            return NULL;
          timeptr->tm_mday = ret;
          buf += 2;
          break;

        case 'H':
        case 'k':
          strncpy(t, buf, 2);
          ret = strtol(t, &s, 10);
          if (s == t)
            return NULL;
          timeptr->tm_hour = ret;
          buf += 2;
          break;

        case 'I':
        case 'l':
          ret = strtol(buf, &s, 10);
          if (s == buf)
            return NULL;
          if (ret == 12)
            timeptr->tm_hour = 0;
          else
            timeptr->tm_hour = ret;
          buf = s;
          break;

        case 'j':
          ret = strtol(buf, &s, 10);
          if (s == buf)
            return NULL;
          timeptr->tm_yday = ret - 1;
          buf = s;
          break;

        case 'm':
        case 'c':
          strncpy(t, buf, 2);
          ret = strtol(t, &s, 10);
          if (s == t)
            return NULL;

          if ((ret < 1) || (ret > 12))
            return NULL;

          timeptr->tm_mon = ret - 1;
          buf += 2;
          break;

        case 'M':
        case 'i':
          strncpy(t, buf, 2);
          ret = strtol(t, &s, 10);
          if ((s == t) && (c == 'M')){
            c = 'B';
            goto RETRY;
          }
          timeptr->tm_min = ret;
          buf += 2;
          break;

        case 'n':
          if (*buf == '\n')
            ++buf;
          else
            return NULL;
          break;

        case 'p':
          ret = match_string(&buf, ampm);
          if (ret < 0)
            return NULL;
          if (timeptr->tm_hour == 0){
            if (ret == 1)
              timeptr->tm_hour = 12;
          }
          else{
            timeptr->tm_hour += 12;
          }
          break;

        case 'r':
          s = xstrptime(buf, "%I:%M:%S %p", timeptr);
          if (s == NULL)
            return NULL;
          buf = s;
          break;

        case 'R':
          s = xstrptime(buf, "%H:%M", timeptr);
          if (s == NULL)
            return NULL;
          buf = s;
          break;

        case 'S':
        case 's':
          strncpy(t, buf, 2);
          ret = strtol(t, &s, 10);
          if (s == t)
            return NULL;
          timeptr->tm_sec = ret;
          buf += 2;
          break;

        case 't':
          if (*buf == '\t')
            ++buf;
          else
            return NULL;
          break;

        case 'T':
        case 'X':
          s = xstrptime(buf, "%H:%M:%S", timeptr);
          if (s == NULL)
            return NULL;
          buf = s;
          break;

        case 'u':
          ret = strtol(buf, &s, 10);
          if (s == buf)
            return NULL;
          timeptr->tm_wday = ret - 1;
          buf = s;
          break;

        case 'w':
          ret = strtol(buf, &s, 10);
          if (s == buf)
            return NULL;
          timeptr->tm_wday = ret;
          buf = s;
          break;

        case 'U':
          ret = strtol(buf, &s, 10);
          if (s == buf)
            return NULL;
          set_week_number_sun(timeptr, ret);
          buf = s;
          break;

        case 'V':
          ret = strtol(buf, &s, 10);
          if (s == buf)
            return NULL;
          set_week_number_mon4(timeptr, ret);
          buf = s;
          break;

        case 'W':
          ret = strtol(buf, &s, 10);
          if (s == buf){
            c = 'B';
            goto RETRY;
          }
          set_week_number_mon(timeptr, ret);
          buf = s;
          break;

        case 'x':
          s = xstrptime(buf, "%Y:%m:%d", timeptr);
          if (s == NULL)
            return NULL;
          buf = s;
          break;

        case 'y':
          strncpy(t, buf, 2);
          ret = strtol(t, &s, 10);
          if (s == t)
            return NULL;
          if (ret < 70)
            timeptr->tm_year = 100 + ret;
          else
            timeptr->tm_year = ret;
          buf += 2;
          break;

        case 'Y':
          strncpy(t, buf, 4);
          ret = strtol(t, &s, 10);
          if (s == t)
            return NULL;
          timeptr->tm_year = ret - tm_year_base;
          buf += 4;
          break;

        case 'Z':
#if defined (__GLIBC__)
          ret = match_string(&buf, tzoffsets);

          if (ret < 0)
            return NULL;

          timeptr->tm_zone = tzoffsets[ret];
#endif
          buf += 3;
          break;

        case '\0':
          --format;

        case '%':
          if (*buf == '%')
            ++buf;
          else
            return NULL;
          break;
      }
    }
    else{
      if (*buf == c)
        ++buf;
      else
        return NULL;
    }

	}

  return (char*)buf;
}
Пример #4
0
char *strptime (const char *buf, const char *format, struct tm *timeptr)
{
    char c;

    if (strcmp(format, "%Y%m%d") == 0) {
	/* the case where the format contains no punctuation
	   is not handled correctly below 
	*/
	return parse_iso_basic(buf, timeptr);
    }

    for (; (c = *format) != '\0'; ++format) {
	char *s;
	int ret;

	if (isspace(c)) {
	    while (isspace (*buf))
		++buf;
	} else if (c == '%' && format[1] != '\0') {
	    c = *++format;
	    if (c == 'E' || c == 'O')
		c = *++format;
	    switch (c) {
	    case 'A' :
		ret = match_string(&buf, full_weekdays);
		if (ret < 0)
		    return NULL;
		timeptr->tm_wday = ret;
		break;
	    case 'a' :
		ret = match_string(&buf, abb_weekdays);
		if (ret < 0)
		    return NULL;
		timeptr->tm_wday = ret;
		break;
	    case 'B' :
		ret = match_string(&buf, full_month);
		if (ret < 0)
		    return NULL;
		timeptr->tm_mon = ret;
		break;
	    case 'b' :
	    case 'h' :
		ret = match_string(&buf, abb_month);
		if (ret < 0)
		    return NULL;
		timeptr->tm_mon = ret;
		break;
	    case 'C' :
		ret = my_strtoi(buf, &s, 2);
		if (s == buf)
		    return NULL;
		timeptr->tm_year = (ret * 100) - tm_year_base;
		buf = s;
		break;
	    case 'c' :
		abort ();
	    case 'D' :		/* %m/%d/%y */
		s = strptime(buf, "%m/%d/%y", timeptr);
		if (s == NULL)
		    return NULL;
		buf = s;
		break;
	    case 'd' :
	    case 'e' :
		ret = my_strtoi(buf, &s, 2);
		if (s == buf)
		    return NULL;
		timeptr->tm_mday = ret;
		buf = s;
		break;
	    case 'H' :
	    case 'k' :
		ret = my_strtoi(buf, &s, 2);
		if (s == buf)
		    return NULL;
		timeptr->tm_hour = ret;
		buf = s;
		break;
	    case 'I' :
	    case 'l' :
		ret = my_strtoi(buf, &s, 2);
		if (s == buf)
		    return NULL;
		if (ret == 12)
		    timeptr->tm_hour = 0;
		else
		    timeptr->tm_hour = ret;
		buf = s;
		break;
	    case 'j' :
		ret = my_strtoi(buf, &s, 3);
		if (s == buf)
		    return NULL;
		timeptr->tm_yday = ret - 1;
		buf = s;
		break;
	    case 'm' :
		ret = my_strtoi(buf, &s, 2);
		if (s == buf)
		    return NULL;
		timeptr->tm_mon = ret - 1;
		buf = s;
		break;
	    case 'M' :
		ret = my_strtoi(buf, &s, 2);
		if (s == buf)
		    return NULL;
		timeptr->tm_min = ret;
		buf = s;
		break;
	    case 'n' :
		if (*buf == '\n')
		    ++buf;
		else
		    return NULL;
		break;
	    case 'p' :
		ret = match_string(&buf, ampm);
		if (ret < 0)
		    return NULL;
		if (timeptr->tm_hour == 0) {
		    if (ret == 1)
			timeptr->tm_hour = 12;
		} else
		    timeptr->tm_hour += 12;
		break;
	    case 'r' :		/* %I:%M:%S %p */
		s = strptime(buf, "%I:%M:%S %p", timeptr);
		if (s == NULL)
		    return NULL;
		buf = s;
		break;
	    case 'R' :		/* %H:%M */
		s = strptime(buf, "%H:%M", timeptr);
		if (s == NULL)
		    return NULL;
		buf = s;
		break;
	    case 'S' :
		ret = my_strtoi(buf, &s, 2);
		if (s == buf)
		    return NULL;
		timeptr->tm_sec = ret;
		buf = s;
		break;
	    case 't' :
		if (*buf == '\t')
		    ++buf;
		else
		    return NULL;
		break;
	    case 'T' :		/* %H:%M:%S */
	    case 'X' :
		s = strptime(buf, "%H:%M:%S", timeptr);
		if (s == NULL)
		    return NULL;
		buf = s;
		break;
	    case 'u' :
		ret = my_strtoi(buf, &s, 1);
		if (s == buf)
		    return NULL;
		timeptr->tm_wday = ret - 1;
		buf = s;
		break;
	    case 'w' :
		ret = my_strtoi(buf, &s, 1);
		if (s == buf)
		    return NULL;
		timeptr->tm_wday = ret;
		buf = s;
		break;
	    case 'U' :
		ret = my_strtoi(buf, &s, 2);
		if (s == buf)
		    return NULL;
		set_week_number_sun(timeptr, ret);
		buf = s;
		break;
	    case 'V' :
		ret = my_strtoi(buf, &s, 2);
		if (s == buf)
		    return NULL;
		set_week_number_mon4(timeptr, ret);
		buf = s;
		break;
	    case 'W' :
		ret = my_strtoi(buf, &s, 2);
		if (s == buf)
		    return NULL;
		set_week_number_mon(timeptr, ret);
		buf = s;
		break;
	    case 'x' :
		s = strptime(buf, "%Y:%m:%d", timeptr);
		if (s == NULL)
		    return NULL;
		buf = s;
		break;
	    case 'y' :
		ret = my_strtoi(buf, &s, 2);
		if (s == buf)
		    return NULL;
		if (ret < 70)
		    timeptr->tm_year = 100 + ret;
		else
		    timeptr->tm_year = ret;
		buf = s;
		break;
	    case 'Y' :
		ret = my_strtoi(buf, &s, 4);
		if (s == buf)
		    return NULL;
		timeptr->tm_year = ret - tm_year_base;
		buf = s;
		break;
	    case '\0' :
		--format;
		/* FALLTHROUGH */
	    case '%' :
		if (*buf == '%')
		    ++buf;
		else
		    return NULL;
		break;
	    default :
		if (*buf == '%' || *++buf == c)
		    ++buf;
		else
		    return NULL;
		break;
	    }
	} else {
	    if (*buf == c)
		++buf;
	    else
		return NULL;
	}
    }

    return (char *) buf;
}
Пример #5
0
char *
strptime(const char *buf, const char *fmt, struct tm *timeptr) {
    char c;

    for (; (c = *fmt) != '\0'; ++fmt) {
        char *s;
        int ret;

        if (isspace(c)) {
            while (isspace(*buf))
                ++buf;
        } else if (c == '%' && fmt[1] != '\0') {
            c = *++fmt;
            if (c == 'E' || c == 'O')
                c = *++fmt;
            switch (c) {
            case 'A':
                ret = match_string(&buf, full_weekdays);
                if (ret < 0)
                    return nullptr;
                timeptr->tm_wday = ret;
                break;
            case 'a':
                ret = match_string(&buf, abb_weekdays);
                if (ret < 0)
                    return nullptr;
                timeptr->tm_wday = ret;
                break;
            case 'B':
                ret = match_string(&buf, full_month);
                if (ret < 0)
                    return nullptr;
                timeptr->tm_mon = ret;
                break;
            case 'b':
            case 'h':
                ret = match_string(&buf, abb_month);
                if (ret < 0)
                    return nullptr;
                timeptr->tm_mon = ret;
                break;
            case 'C':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                timeptr->tm_year = (ret * 100) - tm_year_base;
                buf = s;
                break;
            case 'c':
                abort();
            case 'D': /* %m/%d/%y */
                s = strptime(buf, "%m/%d/%y", timeptr);
                if (s == nullptr)
                    return nullptr;
                buf = s;
                break;
            case 'd':
            case 'e':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                timeptr->tm_mday = ret;
                buf = s;
                break;
            case 'H':
            case 'k':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                timeptr->tm_hour = ret;
                buf = s;
                break;
            case 'I':
            case 'l':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                if (ret == 12)
                    timeptr->tm_hour = 0;
                else
                    timeptr->tm_hour = ret;
                buf = s;
                break;
            case 'j':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                timeptr->tm_yday = ret - 1;
                buf = s;
                break;
            case 'm':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                timeptr->tm_mon = ret - 1;
                buf = s;
                break;
            case 'M':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                timeptr->tm_min = ret;
                buf = s;
                break;
            case 'n':
                if (*buf == '\n')
                    ++buf;
                else
                    return nullptr;
                break;
            case 'p':
                ret = match_string(&buf, ampm);
                if (ret < 0)
                    return nullptr;
                if (timeptr->tm_hour == 0) {
                    if (ret == 1)
                        timeptr->tm_hour = 12;
                } else
                    timeptr->tm_hour += 12;
                break;
            case 'r': /* %I:%M:%S %p */
                s = strptime(buf, "%I:%M:%S %p", timeptr);
                if (s == nullptr)
                    return nullptr;
                buf = s;
                break;
            case 'R': /* %H:%M */
                s = strptime(buf, "%H:%M", timeptr);
                if (s == nullptr)
                    return nullptr;
                buf = s;
                break;
            case 'S':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                timeptr->tm_sec = ret;
                buf = s;
                break;
            case 't':
                if (*buf == '\t')
                    ++buf;
                else
                    return nullptr;
                break;
            case 'T': /* %H:%M:%S */
            case 'X':
                s = strptime(buf, "%H:%M:%S", timeptr);
                if (s == nullptr)
                    return nullptr;
                buf = s;
                break;
            case 'u':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                timeptr->tm_wday = ret - 1;
                buf = s;
                break;
            case 'w':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                timeptr->tm_wday = ret;
                buf = s;
                break;
            case 'U':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                set_week_number_sun(timeptr, ret);
                buf = s;
                break;
            case 'V':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                set_week_number_mon4(timeptr, ret);
                buf = s;
                break;
            case 'W':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                set_week_number_mon(timeptr, ret);
                buf = s;
                break;
            case 'x':
                s = strptime(buf, "%Y:%m:%d", timeptr);
                if (s == nullptr)
                    return nullptr;
                buf = s;
                break;
            case 'y':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                if (ret < 70)
                    timeptr->tm_year = 100 + ret;
                else
                    timeptr->tm_year = ret;
                buf = s;
                break;
            case 'Y':
                ret = strtol(buf, &s, 10);
                if (s == buf)
                    return nullptr;
                timeptr->tm_year = ret - tm_year_base;
                buf = s;
                break;
            case 'Z':
                abort();
            case '\0':
                --fmt;
            /* FALLTHROUGH */
            case '%':
                if (*buf == '%')
                    ++buf;
                else
                    return nullptr;
                break;
            default:
                if (*buf == '%' || *++buf == c)
                    ++buf;
                else
                    return nullptr;
                break;
            }
        } else {
            if (*buf == c)
                ++buf;
            else
                return nullptr;
        }
    }
    return (char *) buf;
}