in source/date_time.c [315:433]
static int s_parse_iso_8601(const struct aws_byte_cursor *date_str_cursor, struct tm *parsed_time) {
size_t index = 0;
size_t state_start_index = 0;
enum parser_state state = ON_YEAR;
bool error = false;
bool advance = true;
AWS_ZERO_STRUCT(*parsed_time);
while (state < FINISHED && !error && index < date_str_cursor->len) {
char c = date_str_cursor->ptr[index];
switch (state) {
case ON_YEAR:
if (c == '-' && index - state_start_index == 4) {
state = ON_MONTH;
state_start_index = index + 1;
parsed_time->tm_year -= 1900;
} else if (aws_isdigit(c)) {
parsed_time->tm_year = parsed_time->tm_year * 10 + (c - '0');
} else {
error = true;
}
break;
case ON_MONTH:
if (c == '-' && index - state_start_index == 2) {
state = ON_MONTH_DAY;
state_start_index = index + 1;
parsed_time->tm_mon -= 1;
} else if (aws_isdigit(c)) {
parsed_time->tm_mon = parsed_time->tm_mon * 10 + (c - '0');
} else {
error = true;
}
break;
case ON_MONTH_DAY:
if (c == 'T' && index - state_start_index == 2) {
state = ON_HOUR;
state_start_index = index + 1;
} else if (aws_isdigit(c)) {
parsed_time->tm_mday = parsed_time->tm_mday * 10 + (c - '0');
} else {
error = true;
}
break;
/* note: no time portion is spec compliant. */
case ON_HOUR:
/* time parts can be delimited by ':' or just concatenated together, but must always be 2 digits. */
if (index - state_start_index == 2) {
state = ON_MINUTE;
state_start_index = index + 1;
if (aws_isdigit(c)) {
state_start_index = index;
advance = false;
} else if (c != ':') {
error = true;
}
} else if (aws_isdigit(c)) {
parsed_time->tm_hour = parsed_time->tm_hour * 10 + (c - '0');
} else {
error = true;
}
break;
case ON_MINUTE:
/* time parts can be delimited by ':' or just concatenated together, but must always be 2 digits. */
if (index - state_start_index == 2) {
state = ON_SECOND;
state_start_index = index + 1;
if (aws_isdigit(c)) {
state_start_index = index;
advance = false;
} else if (c != ':') {
error = true;
}
} else if (aws_isdigit(c)) {
parsed_time->tm_min = parsed_time->tm_min * 10 + (c - '0');
} else {
error = true;
}
break;
case ON_SECOND:
if (c == 'Z' && index - state_start_index == 2) {
state = FINISHED;
state_start_index = index + 1;
} else if (c == '.' && index - state_start_index == 2) {
state = ON_TZ;
state_start_index = index + 1;
} else if (aws_isdigit(c)) {
parsed_time->tm_sec = parsed_time->tm_sec * 10 + (c - '0');
} else {
error = true;
}
break;
case ON_TZ:
if (c == 'Z') {
state = FINISHED;
state_start_index = index + 1;
} else if (!aws_isdigit(c)) {
error = true;
}
break;
default:
error = true;
break;
}
if (advance) {
index++;
} else {
advance = true;
}
}
/* ISO8601 supports date only with no time portion. state ==ON_MONTH_DAY catches this case. */
return (state == FINISHED || state == ON_MONTH_DAY) && !error ? AWS_OP_SUCCESS : AWS_OP_ERR;
}