in sql_utils/public/functions/date_time_util.cc [2657:2758]
absl::Status ExtractFromDatetime(DateTimestampPart part,
const DatetimeValue& datetime,
int32_t* output) {
SQL_RET_CHECK(part != TIME)
<< "Use ExtractTimeFromDatetime() for extracting time from datetime";
if (!datetime.IsValid()) {
return MakeEvalError() << "Invalid datetime value: "
<< datetime.DebugString();
}
switch (part) {
case YEAR:
*output = datetime.Year();
break;
case QUARTER:
*output = (datetime.Month() - 1) / 3 + 1;
break;
case MONTH:
*output = datetime.Month();
break;
case DAY:
*output = datetime.Day();
break;
case HOUR:
*output = datetime.Hour();
break;
case MINUTE:
*output = datetime.Minute();
break;
case SECOND:
*output = datetime.Second();
break;
case MILLISECOND:
*output = datetime.Microseconds() / 1000;
break;
case MICROSECOND:
*output = datetime.Microseconds();
break;
case NANOSECOND:
*output = datetime.Nanoseconds();
break;
case DATE:
SQL_RETURN_IF_ERROR(ConstructDate(datetime.Year(), datetime.Month(),
datetime.Day(), output));
break;
case DAYOFWEEK:
*output = internal_functions::DayOfWeekIntegerSunToSat1To7(
absl::GetWeekday(absl::CivilDay(datetime.Year(), datetime.Month(),
datetime.Day())));
break;
case DAYOFYEAR:
*output = absl::GetYearDay(
absl::CivilDay(datetime.Year(), datetime.Month(), datetime.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(datetime.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);
const absl::CivilDay day(datetime.Year(), datetime.Month(),
datetime.Day());
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 ISOYEAR:
// cast is safe, year "guaranteed" safe by method contract.
*output = static_cast<int32_t>(GetIsoYear(
absl::CivilDay(datetime.Year(), datetime.Month(), datetime.Day())));
break;
case ISOWEEK:
*output = GetIsoWeek(
absl::CivilDay(datetime.Year(), datetime.Month(), datetime.Day()));
break;
case DATETIME:
return MakeEvalError()
<< "Unsupported DateTimestampPart " << DateTimestampPart_Name(part)
<< " to extract from datetime";
case TIME:
// Should never reach this.
SQL_RET_CHECK_FAIL()
<< "Use ExtractTimeFromDatetime() for extracting time from datetime";
break;
default:
return MakeEvalError()
<< "Unexpected DateTimestampPart " << DateTimestampPart_Name(part);
}
return absl::OkStatus();
}