absl::StatusOr IntervalValue::ParseFromString()

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);
}