absl::Status ExpandPercentZQJ()

in sql_utils/public/functions/date_time_util.cc [4519:4585]


absl::Status ExpandPercentZQJ(absl::string_view format_string,
                              absl::Time base_time, absl::TimeZone timezone,
                              const ExpansionOptions& expansion_options,
                              std::string* expanded_format_string) {
  SQL_RET_CHECK(expanded_format_string->empty());
  if (format_string.empty()) {
    return absl::OkStatus();
  }
  expanded_format_string->reserve(format_string.size());

  for (size_t index = 0;; index += 2) {
    const size_t pct = format_string.find('%', index);
    if (pct == format_string.size() - 1 ||
        pct == std::string::npos) {  // no "%?"
      absl::StrAppend(
          expanded_format_string,
          format_string.substr(index, format_string.size() - index));
      break;
    }
    if (pct != index) {
      absl::StrAppend(expanded_format_string,
                      format_string.substr(index, pct - index));
      index = pct;
    }
    if (expansion_options.expand_quarter && format_string[pct + 1] == 'Q') {
      // Handle %Q, computing quarter from month.
      absl::StrAppend(
          expanded_format_string,
          absl::StrFormat(
              "%d",
              (absl::ToCivilMonth(base_time, timezone).month() - 1) / 3 + 1));
    } else if (format_string[pct + 1] == 'Z') {
      // Handle %Z, computing the SQL defined timezone format.
      absl::StrAppend(expanded_format_string, "UTC");
      if (int seconds = timezone.At(base_time).offset) {
        const char sign = (seconds < 0 ? '-' : '+');
        int minutes = seconds / 60;
        seconds %= 60;
        if (sign == '-') {
          if (seconds > 0) {
            seconds -= 60;
            minutes += 1;
          }
          seconds = -seconds;
          minutes = -minutes;
        }
        int hours = minutes / 60;
        minutes %= 60;
        expanded_format_string->push_back(sign);
        SQL_RET_CHECK_EQ(seconds, 0);
        if (minutes != 0) {
          absl::StrAppend(expanded_format_string,
                          absl::StrFormat("%02d%02d", hours, minutes));
        } else {
          absl::StrAppend(expanded_format_string, absl::StrFormat("%d", hours));
        }
      }
    } else if (expansion_options.expand_iso_dayofyear &&
               format_string[pct + 1] == 'J') {
      return MakeEvalError() << "Format element %J not supported yet";
    } else {
      // None of %J, %Q, %Z. Copy as is.
      absl::StrAppend(expanded_format_string, format_string.substr(index, 2));
    }
  }
  return absl::OkStatus();
}