static absl::Status AddTimeInternal()

in sql_utils/public/functions/date_time_util.cc [3665:3730]


static absl::Status AddTimeInternal(const TimeValue& time,
                                    DateTimestampPart part, int64_t interval,
                                    TimeValue* output) {
  if (!time.IsValid()) {
    return MakeEvalError() << "Invalid time value: " << time.DebugString();
  }
  if (!(part == HOUR || part == MINUTE || part == SECOND ||
        part == MILLISECOND || part == MICROSECOND || part == NANOSECOND)) {
    return MakeEvalError() << "Unsupported DateTimestampPart "
                           << DateTimestampPart_Name(part);
  }

  int hour = time.Hour();
  int minute = time.Minute();
  int second = time.Second();
  int nanoseconds = time.Nanoseconds();
  while (interval != 0 && part != DAY) {
    switch (part) {
      case NANOSECOND:
        AddOnField(interval, 1000000000, &nanoseconds, &interval);
        part = SECOND;
        break;
      case MICROSECOND: {
        int microseconds = 0;
        int64_t carry_1;
        AddOnField(interval, 1000000, &microseconds, &carry_1);
        int64_t carry_2;
        AddOnField(microseconds * 1000, 1000000000, &nanoseconds, &carry_2);
        interval = carry_1 + carry_2;
        part = SECOND;
        break;
      }
      case MILLISECOND: {
        int millisecond = 0;
        int64_t carry_1;
        AddOnField(interval, 1000, &millisecond, &carry_1);
        int64_t carry_2;
        AddOnField(millisecond * 1000000, 1000000000, &nanoseconds, &carry_2);
        interval = carry_1 + carry_2;
        part = SECOND;
        break;
      }
      case SECOND: {
        AddOnField(interval, 60, &second, &interval);
        part = MINUTE;
        break;
      }
      case MINUTE: {
        AddOnField(interval, 60, &minute, &interval);
        part = HOUR;
        break;
      }
      case HOUR: {
        AddOnField(interval, 24, &hour, &interval);
        part = DAY;
        break;
      }
      default:
        break;
    }
  }
  *output = TimeValue::FromHMSAndNanos(hour, minute, second, nanoseconds);
  // This check should never fail as all fields should be in range.
  SQL_DCHECK(output->IsValid()) << output->DebugString();
  return absl::OkStatus();
}