in sql_utils/public/functions/date_time_util.cc [3179:3235]
static absl::Status DiffWithPartsSmallerThanDay(
const absl::CivilSecond civil_second_1, int64_t nanosecond_1,
const absl::CivilSecond civil_second_2, int64_t nanosecond_2,
DateTimestampPart part,
const std::function<absl::Status()>& nano_overflow_error_maker,
int64_t* output) {
if (part == HOUR) {
*output = absl::CivilHour(civil_second_1) - absl::CivilHour(civil_second_2);
} else if (part == MINUTE) {
*output =
absl::CivilMinute(civil_second_1) - absl::CivilMinute(civil_second_2);
} else {
int64_t diff_in_seconds = civil_second_1 - civil_second_2;
switch (part) {
case NANOSECOND:
if (std::numeric_limits<int64_t>::lowest() / powers_of_ten[9] <=
diff_in_seconds &&
std::numeric_limits<int64_t>::max() / powers_of_ten[9] >=
diff_in_seconds) {
// std::numeric_limits<int64_t>::lowest() < nano_diff_1 <
// std::numeric_limits<int64_t>::max() should always hold.
int64_t nano_diff_1 = diff_in_seconds * powers_of_ten[9];
int64_t nano_diff_2 = nanosecond_1 - nanosecond_2;
// The output is valid only when
// std::numeric_limits<int64_t>::lowest() <= nano_diff_1 + nano_diff_2
// <= std::numeric_limits<int64_t>::max()
if ((nano_diff_2 >= 0 &&
std::numeric_limits<int64_t>::max() - nano_diff_2 >=
nano_diff_1) ||
(nano_diff_2 < 0 &&
std::numeric_limits<int64_t>::lowest() - nano_diff_2 <=
nano_diff_1)) {
*output = nano_diff_1 + nano_diff_2;
return absl::OkStatus();
}
}
return nano_overflow_error_maker();
case MICROSECOND:
*output =
diff_in_seconds * powers_of_ten[6] +
(nanosecond_1 / powers_of_ten[3] - nanosecond_2 / powers_of_ten[3]);
break;
case MILLISECOND:
*output =
diff_in_seconds * powers_of_ten[3] +
(nanosecond_1 / powers_of_ten[6] - nanosecond_2 / powers_of_ten[6]);
break;
case SECOND:
*output = diff_in_seconds;
break;
default:
SQL_RET_CHECK_FAIL() << "Unexpected DateTimestampPart "
<< DateTimestampPart_Name(part);
}
}
return absl::OkStatus();
}