bool tryParseDateString()

in velox/type/TimestampConversion.cpp [148:263]


bool tryParseDateString(
    const char* buf,
    size_t len,
    size_t& pos,
    int32_t& daysSinceEpoch,
    bool strict) {
  pos = 0;
  if (len == 0) {
    return false;
  }

  int32_t day = 0;
  int32_t month = -1;
  int32_t year = 0;
  bool yearneg = false;
  int sep;

  // Skip leading spaces.
  while (pos < len && characterIsSpace(buf[pos])) {
    pos++;
  }

  if (pos >= len) {
    return false;
  }
  if (buf[pos] == '-') {
    yearneg = true;
    pos++;
    if (pos >= len) {
      return false;
    }
  }
  if (!characterIsDigit(buf[pos])) {
    return false;
  }
  // First parse the year.
  for (; pos < len && characterIsDigit(buf[pos]); pos++) {
    year = (buf[pos] - '0') + year * 10;
    if (year > kMaxYear) {
      break;
    }
  }
  if (yearneg) {
    year = -year;
    if (year < kMinYear) {
      return false;
    }
  }

  if (pos >= len) {
    return false;
  }

  // Fetch the separator.
  sep = buf[pos++];
  if (sep != ' ' && sep != '-' && sep != '/' && sep != '\\') {
    // Invalid separator.
    return false;
  }

  // Parse the month.
  if (!parseDoubleDigit(buf, len, pos, month)) {
    return false;
  }

  if (pos >= len) {
    return false;
  }

  if (buf[pos++] != sep) {
    return false;
  }

  if (pos >= len) {
    return false;
  }

  // Now parse the day.
  if (!parseDoubleDigit(buf, len, pos, day)) {
    return false;
  }

  // Check for an optional trailing " (BC)".
  if (len - pos >= 5 && characterIsSpace(buf[pos]) && buf[pos + 1] == '(' &&
      buf[pos + 2] == 'B' && buf[pos + 3] == 'C' && buf[pos + 4] == ')') {
    if (yearneg || year == 0) {
      return false;
    }
    year = -year + 1;
    pos += 5;

    if (year < kMinYear) {
      return false;
    }
  }

  // In strict mode, check remaining string for non-space characters.
  if (strict) {
    // Skip trailing spaces.
    while (pos < len && characterIsSpace(buf[pos])) {
      pos++;
    }
    // Check position. if end was not reached, non-space chars remaining.
    if (pos < len) {
      return false;
    }
  } else {
    // In non-strict mode, check for any direct trailing digits.
    if (pos < len && characterIsDigit(buf[pos])) {
      return false;
    }
  }

  daysSinceEpoch = fromDate(year, month, day);
  return true;
}