in sql_utils/public/functions/date_time_util.cc [1823:1913]
absl::Status ConvertTimestampMicrosToStringWithTruncation(
int64_t timestamp, absl::TimeZone timezone, std::string* out) {
absl::Time time = absl::FromUnixMicros(timestamp);
if (ABSL_PREDICT_FALSE(!IsValidTime(time))) {
return MakeEvalError() << "Invalid timestamp value: " << timestamp;
}
absl::TimeZone normalized_timezone =
internal_functions::GetNormalizedTimeZone(time, timezone);
absl::TimeZone::CivilInfo info = normalized_timezone.At(time);
// YYYY-mm-dd HH:MM:SS.ssssss+oo:oo
// 01234567890123456789012345678901
// 0 1 2 3
// Maximum possible string size for the result.
static constexpr size_t kFormatYMDHMSSize = 32;
out->resize(kFormatYMDHMSSize);
char* data = out->data();
// YYYY-mm-dd HH:MM:SS.ssssss+oooo
// 0123456789012345678901234567890
// 0 1 2
// Carefully put characters corresponding to different parts of formatted
// string to the right positions.
data[0] = info.cs.year() / 1000 + '0';
data[1] = (info.cs.year() % 1000) / 100 + '0';
data[2] = (info.cs.year() % 100) / 10 + '0';
data[3] = info.cs.year() % 10 + '0';
data[4] = '-';
data[5] = info.cs.month() / 10 + '0';
data[6] = info.cs.month() % 10 + '0';
data[7] = '-';
data[8] = info.cs.day() / 10 + '0';
data[9] = info.cs.day() % 10 + '0';
data[10] = ' ';
data[11] = info.cs.hour() / 10 + '0';
data[12] = info.cs.hour() % 10 + '0';
data[13] = ':';
data[14] = info.cs.minute() / 10 + '0';
data[15] = info.cs.minute() % 10 + '0';
data[16] = ':';
data[17] = info.cs.second() / 10 + '0';
data[18] = info.cs.second() % 10 + '0';
// Deal with subsecond truncation to 0, 3 or 6 digits.
size_t pos = 19;
int64_t sub_seconds = timestamp % 1000000;
if (sub_seconds < 0) {
sub_seconds += 1000000;
}
if (sub_seconds > 0) {
data[19] = '.';
if (sub_seconds % 1000 > 0) {
for (int i = 5; i >= 0; i--) {
data[20 + i] = (sub_seconds % 10) + '0';
sub_seconds /= 10;
}
pos += 7;
} else {
sub_seconds /= 1000;
for (int i = 2; i >= 0; i--) {
data[20 + i] = (sub_seconds % 10) + '0';
sub_seconds /= 10;
}
pos += 4;
}
}
bool positive_offset;
int32_t hour_offset;
int32_t minute_offset;
internal_functions::GetSignHourAndMinuteTimeZoneOffset(
info, &positive_offset, &hour_offset, &minute_offset);
if (positive_offset) {
data[pos++] = '+';
} else {
data[pos++] = '-';
}
// Write timezone offset using HH:mm format
data[pos++] = hour_offset / 10 + '0';
data[pos++] = hour_offset % 10 + '0';
if (minute_offset > 0) {
data[pos++] = ':';
data[pos++] = minute_offset / 10 + '0';
data[pos++] = minute_offset % 10 + '0';
}
// Initially we resized result for maximum possible size, here we set actual
// size.
out->resize(pos);
return absl::OkStatus();
}