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