static absl::Status ComputeYearMonthDayFromISOParts()

in sql_utils/public/functions/parse_date_time.cc [792:858]


static absl::Status ComputeYearMonthDayFromISOParts(
    int64_t* year, int* month, int* mday, DateParseContext* date_parse_context) {
  std::optional<ParseElementInfo> iso_year_info;
  std::optional<ParseElementInfo> iso_week_info;
  std::optional<ParseElementInfo> weekday_info;
  std::optional<ParseElementInfo> iso_dayofyear_info;

  for (const auto& element : date_parse_context->elements) {
    switch (element.fmt) {
      case 'A':  // Full weekday name
      case 'a':  // Abbreviated weekday name
      case 'u':  // weekday number 1-7, starting Monday
      case 'w':  // weekday number 0-6, starting Sunday
        weekday_info = element;
        break;
      case 'G':  // ISO 8601 year with century, e.g., 2019
      case 'g':  // ISO 8601 year without century, e.g., 19
        iso_year_info = element;
        break;
      case 'J':  // ISO day of year
        iso_dayofyear_info = element;
        break;
      case 'V':  // ISO 8601 week number of the ISO YEAR
        iso_week_info = element;
        break;
      default:
        SQL_RET_CHECK_FAIL() << "Unexpected format element: '" << element.fmt
                         << "'";
    }
  }
  // The canonicalized date parse context should ensure that only one of
  // week or day of year is set, so we validate that here.
  SQL_RET_CHECK(!iso_week_info.has_value() || !iso_dayofyear_info.has_value());

  absl::CivilDay civil_day;
  SQL_RET_CHECK(iso_year_info.has_value());

  // Valid combinations are:
  // 1) ISO week - interpreted as the first day of this ISO week
  // 2) ISO week and day of week
  // 4) ISO day of year
  // 3) ISO year only - interpreted as the first day of the ISO year
  if (iso_week_info.has_value()) {
    SQL_RET_CHECK(!iso_dayofyear_info.has_value());
    // Covers year/week, and year/week/weekday.
    SQL_RETURN_IF_ERROR(ComputeDateFromISOYearWeekAndWeekday(
        iso_year_info.value(), iso_week_info.value(), weekday_info,
        &civil_day));
  } else {
    // Covers year, and year/dayofyear.
    SQL_RET_CHECK(!iso_week_info.has_value());
    SQL_RET_CHECK(!weekday_info.has_value());
    // Compute date from ISO year and day of year (optional).
    SQL_RETURN_IF_ERROR(ComputeDateFromISOYearAndDayOfYear(
        iso_year_info.value(), iso_dayofyear_info, &civil_day));
  }
  *year = civil_day.year();
  *month = civil_day.month();
  *mday = civil_day.day();
  // Verify that the result date is valid.
  if (!IsValidDay(*year, *month, *mday)) {
    return MakeEvalError()
           << "Out-of-range datetime field in parsing function; year: " << *year
           << ", month: " << *month << ", day: " << *mday;
  }
  return absl::OkStatus();
}