int TimestampParser::Format()

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