static absl::Status DiffWithPartsSmallerThanDay()

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();
}