in be/src/runtime/timestamp-parse-util.cc [257:377]
int TimestampParser::Format(const DateTimeFormatContext& dt_ctx, const date& d,
const time_duration& t, int max_length, char* dst) {
DCHECK(dt_ctx.toks.size() > 0);
if (dt_ctx.has_date_toks && d.is_special()) return -1;
if (dt_ctx.has_time_toks && t.is_special()) return -1;
int pos = 0;
char buff[12];
for (const DateTimeFormatToken& tok: dt_ctx.toks) {
int32_t num_val = -1;
switch (tok.type) {
case YEAR:
case ROUND_YEAR: {
num_val = AdjustYearToLength(d.year(), tok.divisor);
break;
}
case QUARTER_OF_YEAR: {
num_val = GetQuarter(d.month());
break;
}
case MONTH_IN_YEAR: num_val = d.month().as_number(); break;
case MONTH_NAME:
case MONTH_NAME_SHORT: {
AppendToBuffer(FormatMonthName(d.month().as_number(), tok), dst, pos, max_length);
break;
}
case WEEK_OF_YEAR: {
num_val = GetWeekOfYear(d.year(), d.month(), d.day());
break;
}
case WEEK_OF_MONTH: {
num_val = GetWeekOfMonth(d.day());
break;
}
case DAY_OF_WEEK: {
// Value in [1-7] where 1 represents Sunday, 2 represents Monday, etc.
num_val = d.day_of_week() + 1;
break;
}
case DAY_IN_MONTH: num_val = d.day(); break;
case DAY_IN_YEAR: {
num_val = GetDayInYear(d.year(), d.month(), d.day());
break;
}
case DAY_NAME:
case DAY_NAME_SHORT: {
AppendToBuffer(FormatDayName(d.day_of_week() + 1, tok), dst, pos, max_length);
break;
}
case HOUR_IN_DAY: num_val = t.hours(); break;
case HOUR_IN_HALF_DAY: {
num_val = t.hours();
if (num_val == 0) num_val = 12;
if (num_val > 12) num_val -= 12;
break;
}
case MERIDIEM_INDICATOR: {
const MERIDIEM_INDICATOR_TEXT* indicator_txt = (tok.len == 2) ? &AM : &AM_LONG;
if (t.hours() >= 12) {
indicator_txt = (tok.len == 2) ? &PM : &PM_LONG;
}
AppendToBuffer((isupper(*tok.val)) ? indicator_txt->first : indicator_txt->second,
tok.len, dst, pos, max_length);
break;
}
case MINUTE_IN_HOUR: num_val = t.minutes(); break;
case SECOND_IN_MINUTE: num_val = t.seconds(); break;
case SECOND_IN_DAY: {
num_val = t.hours() * 3600 + t.minutes() * 60 + t.seconds();
break;
}
case FRACTION: {
num_val = t.fractional_seconds();
if (num_val > 0 && tok.divisor > 1) num_val /= tok.divisor;
break;
}
case SEPARATOR:
case ISO8601_TIME_INDICATOR:
case ISO8601_ZULU_INDICATOR: {
AppendToBuffer(tok.val, tok.len, dst, pos, max_length);
break;
}
case TZ_OFFSET: {
break;
}
case TEXT: {
AppendToBuffer(FormatTextToken(tok), dst, pos, max_length);
break;
}
case ISO8601_WEEK_NUMBERING_YEAR: {
num_val = AdjustYearToLength(GetIso8601WeekNumberingYear(d), tok.divisor);
break;
}
case ISO8601_WEEK_OF_YEAR: {
num_val = d.week_number();
break;
}
case ISO8601_DAY_OF_WEEK: {
// day_of_week() returns 0 for Sunday, 1 for Monday and 6 for Saturday.
num_val = d.day_of_week();
// We need to output 1 for Monday and 7 for Sunday.
if (num_val == 0) num_val = 7;
break;
}
default: DCHECK(false) << "Unknown date/time format token";
}
if (num_val > -1) {
char* buff_end = FastInt32ToBufferLeft(num_val, &buff[0]);
int written_length = buff_end - (&buff[0]);
DCHECK_GT(written_length, 0);
if (!tok.fm_modifier && written_length < tok.len) {
for (int i = (tok.len - written_length); (i > 0) && (pos < max_length); i--) {
*(dst + pos) = '0';
pos++;
}
}
AppendToBuffer(&buff[0], written_length, dst, pos, max_length);
}
DCHECK_LE(pos, max_length) << "Maximum buffer length exceeded!";
}
return pos;
}