absl::Status CanonicalizeDateParseContext()

in sql_utils/public/functions/parse_date_time.cc [403:471]


absl::Status CanonicalizeDateParseContext(
    DateParseContext* date_parse_context) {
  if (date_parse_context->elements.empty()) {
    // If there are no entries then there is nothing to canonicalize.
    // Note that if there is 1 entry we still might need to canonicalize it,
    // for example in the case where the only element present is day of week,
    // which should be removed/ignored.
    return absl::OkStatus();
  }
  int64_t weekday_idx = -1;
  int64_t iso_year_idx = -1;
  int64_t non_iso_dayofyear_idx = -1;
  int64_t non_iso_week_idx = -1;
  int64_t iso_week_idx = -1;
  int64_t iso_dayofyear_idx = -1;

  // Loop through the elements and record the last position of each of
  // the elements.
  for (int64_t idx = 0; idx < date_parse_context->elements.size(); ++idx) {
    switch (date_parse_context->elements[idx].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_idx = idx;
        break;
      case 'G':  // ISO 8601 year with century, e.g., 2019
      case 'g':  // ISO 8601 year without century, e.g., 19
        iso_year_idx = idx;
        break;
      case 'J':  // ISO day of year
        // We ignore ISO elements if non-ISO elements are present.
        iso_dayofyear_idx = idx;
        break;
      case 'j':  // Non-ISO day of year
        non_iso_dayofyear_idx = idx;
        break;
      case 'U':  // Non-ISO week number of the year (starting Sunday) 00-53
      case 'W':  // Non-ISO week number of the year (starting Monday) 00-53
        non_iso_week_idx = idx;
        break;
      case 'V':  // ISO 8601 week number of the ISO YEAR
        // We ignore ISO elements if non-ISO elements are present.
        iso_week_idx = idx;
        break;
      default:
        SQL_RET_CHECK_FAIL() << "Unexpected format element: '"
                         << date_parse_context->elements[idx].fmt << "'";
    }
  }

  // Ignore ISO parts if non-ISO parts are present.
  if (date_parse_context->non_iso_date_part_present) {
    iso_year_idx = -1;
    iso_week_idx = -1;
    iso_dayofyear_idx = -1;
  }

  if (iso_year_idx >= 0) {
    // We have an ISO date.
    return CanonicalizeISODateParseContext(iso_year_idx, iso_week_idx,
                                           iso_dayofyear_idx, weekday_idx,
                                           date_parse_context);
  }

  // Otherise we have a non-ISO date.
  return CanonicalizeNonISODateParseContext(
      non_iso_week_idx, non_iso_dayofyear_idx, weekday_idx, date_parse_context);
}