absl::Status ExtractFromDate()

in sql_utils/public/functions/date_time_util.cc [2535:2605]


absl::Status ExtractFromDate(DateTimestampPart part, int32_t date,
                             int32_t* output) {
  if (!IsValidDate(date)) {
    return MakeEvalError() << "Invalid date value: " << date;
  }
  absl::CivilDay day = EpochDaysToCivilDay(date);
  switch (part) {
    case YEAR:
      // Year for valid dates fits into int32_t
      *output = static_cast<int32_t>(day.year());
      break;
    case QUARTER:
      *output = (day.month() - 1) / 3 + 1;
      break;
    case MONTH:
      *output = day.month();
      break;
    case DAY:
      *output = day.day();
      break;
    case ISOYEAR:
      // Year for valid dates fits into int32_t
      *output = static_cast<int32_t>(GetIsoYear(day));
      break;
    case WEEK:
    case WEEK_MONDAY:
    case WEEK_TUESDAY:
    case WEEK_WEDNESDAY:
    case WEEK_THURSDAY:
    case WEEK_FRIDAY:
    case WEEK_SATURDAY: {
      const absl::CivilDay first_calendar_day_of_year(day.year(), 1, 1);
      SQL_ASSIGN_OR_RETURN(const absl::Weekday weekday,
                       GetFirstWeekDayOfWeek(part));
      const absl::CivilDay effective_first_day_of_year =
          NextWeekdayOrToday(first_calendar_day_of_year, weekday);
      if (day < effective_first_day_of_year) {
        *output = 0;
      } else {
        // cast is safe, guaranteed to be less than 52.
        *output =
            static_cast<int32_t>(((day - effective_first_day_of_year) / 7) + 1);
      }
      break;
    }
    case ISOWEEK:
      *output = GetIsoWeek(day);
      break;
    case DAYOFWEEK:
      *output = internal_functions::DayOfWeekIntegerSunToSat1To7(
          absl::GetWeekday(day));
      break;
    case DAYOFYEAR:
      *output = absl::GetYearDay(day);
      break;
    case DATE:
    case HOUR:
    case MINUTE:
    case SECOND:
    case MILLISECOND:
    case MICROSECOND:
    case NANOSECOND:
      return MakeEvalError()
             << "Unsupported DateTimestampPart " << DateTimestampPart_Name(part)
             << " to extract from date";
    default:
      return MakeEvalError()
             << "Unexpected DateTimestampPart " << DateTimestampPart_Name(part);
  }
  return absl::OkStatus();
}