in sql_utils/public/interval_value.cc [735:803]
absl::StatusOr<IntervalValue> IntervalValue::ParseFromString(
absl::string_view input) {
// We can unambiguously determine possible datetime fields by counting number
// of spaces, colons and dashes after digit in the input
// (dash before digit could be a minus sign)
//
// ------------------+-------------+--------+--------+--------------------+
// Datetime fields | Format | Spaces | Colons | Dashes after digit |
// ------------------+-------------+--------+--------+--------------------+
// YEAR TO SECOND | Y-M D H:M:S | 2 | 2 | 1 |
// YEAR TO MINUTE | Y-M D H:M | 2 | 1 | 1 |
// YEAR TO HOUR | Y-M D H | 2 | 0 | 1 |
// YEAR TO DAY | Y-M D | 1 | 0 | 1 |
// YEAR TO MONTH | Y-M | 0 | 0 | 1 |
// MONTH TO HOUR | M D H | 2 | 0 | 0 |
// MONTH TO MINUTE | M D H:M | 2 | 1 | 0 |
// MONTH TO SECOND | M D H:M:S | 2 | 2 | 0 |
// DAY TO MINUTE | D H:M | 1 | 1 | 0 |
// DAY TO SECOND | D H:M:S | 1 | 2 | 0 |
// HOUR TO SECOND | H:M:S | 0 | 2 | 0 |
// ------------------+-------------+--------+--------+--------------------+
char p = '\0';
int spaces = 0;
int colons = 0;
int dashes = 0;
for (char c : input) {
if (c == ' ') {
spaces++;
} else if (c == ':') {
colons++;
} else if (c == '-' && std::isdigit(p)) {
dashes++;
}
p = c;
}
#define SCD(s, c, d) ((s)*100 + (c)*10 + d)
using functions::DAY;
using functions::HOUR;
using functions::MINUTE;
using functions::MONTH;
using functions::SECOND;
using functions::YEAR;
switch (SCD(spaces, colons, dashes)) {
case SCD(2, 2, 1):
return IntervalValue::ParseFromString(input, YEAR, SECOND);
case SCD(2, 1, 1):
return IntervalValue::ParseFromString(input, YEAR, MINUTE);
case SCD(2, 0, 1):
return IntervalValue::ParseFromString(input, YEAR, HOUR);
case SCD(1, 0, 1):
return IntervalValue::ParseFromString(input, YEAR, DAY);
case SCD(0, 0, 1):
return IntervalValue::ParseFromString(input, YEAR, MONTH);
case SCD(2, 0, 0):
return IntervalValue::ParseFromString(input, MONTH, HOUR);
case SCD(2, 1, 0):
return IntervalValue::ParseFromString(input, MONTH, MINUTE);
case SCD(2, 2, 0):
return IntervalValue::ParseFromString(input, MONTH, SECOND);
case SCD(1, 1, 0):
return IntervalValue::ParseFromString(input, DAY, MINUTE);
case SCD(1, 2, 0):
return IntervalValue::ParseFromString(input, DAY, SECOND);
case SCD(0, 2, 0):
return IntervalValue::ParseFromString(input, HOUR, SECOND);
}
#undef SCD
return MakeIntervalParsingError(input);
}