/**
   * Formats the date input according to the format string in use, appending to the specified
   * StringBuffer. The input StringBuffer is returned as output for convenience.
   */
  private void formatWithAttribute(Date date, FormatBuffer buffer, FieldPosition pos) {
    String temp;
    AttributedCharacterIterator.Attribute attribute;
    calendar.setTime(date);

    // go through vector, filling in fields where applicable, else toString
    Iterator iter = tokens.iterator();
    while (iter.hasNext()) {
      Object o = iter.next();
      if (o instanceof CompiledField) {
        CompiledField cf = (CompiledField) o;
        int beginIndex = buffer.length();

        switch (cf.getField()) {
          case ERA_FIELD:
            buffer.append(formatData.eras[calendar.get(Calendar.ERA)], DateFormat.Field.ERA);
            break;
          case YEAR_FIELD:
            // If we have two digits, then we truncate.  Otherwise, we
            // use the size of the pattern, and zero pad.
            buffer.setDefaultAttribute(DateFormat.Field.YEAR);
            if (cf.getSize() == 2) {
              temp = String.valueOf(calendar.get(Calendar.YEAR));
              buffer.append(temp.substring(temp.length() - 2));
            } else withLeadingZeros(calendar.get(Calendar.YEAR), cf.getSize(), buffer);
            break;
          case MONTH_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.MONTH);
            if (cf.getSize() < 3)
              withLeadingZeros(calendar.get(Calendar.MONTH) + 1, cf.getSize(), buffer);
            else if (cf.getSize() < 4)
              buffer.append(formatData.shortMonths[calendar.get(Calendar.MONTH)]);
            else buffer.append(formatData.months[calendar.get(Calendar.MONTH)]);
            break;
          case DATE_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.DAY_OF_MONTH);
            withLeadingZeros(calendar.get(Calendar.DATE), cf.getSize(), buffer);
            break;
          case HOUR_OF_DAY1_FIELD: // 1-24
            buffer.setDefaultAttribute(DateFormat.Field.HOUR_OF_DAY1);
            withLeadingZeros(
                ((calendar.get(Calendar.HOUR_OF_DAY) + 23) % 24) + 1, cf.getSize(), buffer);
            break;
          case HOUR_OF_DAY0_FIELD: // 0-23
            buffer.setDefaultAttribute(DateFormat.Field.HOUR_OF_DAY0);
            withLeadingZeros(calendar.get(Calendar.HOUR_OF_DAY), cf.getSize(), buffer);
            break;
          case MINUTE_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.MINUTE);
            withLeadingZeros(calendar.get(Calendar.MINUTE), cf.getSize(), buffer);
            break;
          case SECOND_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.SECOND);
            withLeadingZeros(calendar.get(Calendar.SECOND), cf.getSize(), buffer);
            break;
          case MILLISECOND_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.MILLISECOND);
            withLeadingZeros(calendar.get(Calendar.MILLISECOND), cf.getSize(), buffer);
            break;
          case DAY_OF_WEEK_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.DAY_OF_WEEK);
            if (cf.getSize() < 4)
              buffer.append(formatData.shortWeekdays[calendar.get(Calendar.DAY_OF_WEEK)]);
            else buffer.append(formatData.weekdays[calendar.get(Calendar.DAY_OF_WEEK)]);
            break;
          case DAY_OF_YEAR_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.DAY_OF_YEAR);
            withLeadingZeros(calendar.get(Calendar.DAY_OF_YEAR), cf.getSize(), buffer);
            break;
          case DAY_OF_WEEK_IN_MONTH_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.DAY_OF_WEEK_IN_MONTH);
            withLeadingZeros(calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH), cf.getSize(), buffer);
            break;
          case WEEK_OF_YEAR_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.WEEK_OF_YEAR);
            withLeadingZeros(calendar.get(Calendar.WEEK_OF_YEAR), cf.getSize(), buffer);
            break;
          case WEEK_OF_MONTH_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.WEEK_OF_MONTH);
            withLeadingZeros(calendar.get(Calendar.WEEK_OF_MONTH), cf.getSize(), buffer);
            break;
          case AM_PM_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.AM_PM);
            buffer.append(formatData.ampms[calendar.get(Calendar.AM_PM)]);
            break;
          case HOUR1_FIELD: // 1-12
            buffer.setDefaultAttribute(DateFormat.Field.HOUR1);
            withLeadingZeros(((calendar.get(Calendar.HOUR) + 11) % 12) + 1, cf.getSize(), buffer);
            break;
          case HOUR0_FIELD: // 0-11
            buffer.setDefaultAttribute(DateFormat.Field.HOUR0);
            withLeadingZeros(calendar.get(Calendar.HOUR), cf.getSize(), buffer);
            break;
          case TIMEZONE_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.TIME_ZONE);
            TimeZone zone = calendar.getTimeZone();
            boolean isDST = calendar.get(Calendar.DST_OFFSET) != 0;
            // FIXME: XXX: This should be a localized time zone.
            String zoneID =
                zone.getDisplayName(isDST, cf.getSize() > 3 ? TimeZone.LONG : TimeZone.SHORT);
            buffer.append(zoneID);
            break;
          case RFC822_TIMEZONE_FIELD:
            buffer.setDefaultAttribute(DateFormat.Field.RFC822_TIME_ZONE);
            int pureMinutes =
                (calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET))
                    / (1000 * 60);
            String sign = (pureMinutes < 0) ? "-" : "+";
            int hours = pureMinutes / 60;
            int minutes = pureMinutes % 60;
            buffer.append(sign);
            withLeadingZeros(hours, 2, buffer);
            withLeadingZeros(minutes, 2, buffer);
            break;
          default:
            throw new IllegalArgumentException("Illegal pattern character " + cf.getCharacter());
        }
        if (pos != null
            && (buffer.getDefaultAttribute() == pos.getFieldAttribute()
                || cf.getField() == pos.getField())) {
          pos.setBeginIndex(beginIndex);
          pos.setEndIndex(buffer.length());
        }
      } else {
        buffer.append(o.toString(), null);
      }
    }
  }