in android/text/format/TimeFormatter.java [147:388]
private boolean handleToken(CharBuffer formatBuffer, ZoneInfo.WallTime wallTime,
ZoneInfo zoneInfo) {
// The char at formatBuffer.position() is expected to be '%' at this point.
int modifier = 0;
while (formatBuffer.remaining() > 1) {
// Increment the position then get the new current char.
formatBuffer.position(formatBuffer.position() + 1);
char currentChar = formatBuffer.get(formatBuffer.position());
switch (currentChar) {
case 'A':
modifyAndAppend((wallTime.getWeekDay() < 0
|| wallTime.getWeekDay() >= DAYSPERWEEK)
? "?" : localeData.longWeekdayNames[wallTime.getWeekDay() + 1],
modifier);
return false;
case 'a':
modifyAndAppend((wallTime.getWeekDay() < 0
|| wallTime.getWeekDay() >= DAYSPERWEEK)
? "?" : localeData.shortWeekdayNames[wallTime.getWeekDay() + 1],
modifier);
return false;
case 'B':
if (modifier == '-') {
modifyAndAppend((wallTime.getMonth() < 0
|| wallTime.getMonth() >= MONSPERYEAR)
? "?"
: localeData.longStandAloneMonthNames[wallTime.getMonth()],
modifier);
} else {
modifyAndAppend((wallTime.getMonth() < 0
|| wallTime.getMonth() >= MONSPERYEAR)
? "?" : localeData.longMonthNames[wallTime.getMonth()],
modifier);
}
return false;
case 'b':
case 'h':
modifyAndAppend((wallTime.getMonth() < 0 || wallTime.getMonth() >= MONSPERYEAR)
? "?" : localeData.shortMonthNames[wallTime.getMonth()],
modifier);
return false;
case 'C':
outputYear(wallTime.getYear(), true, false, modifier);
return false;
case 'c':
formatInternal(dateTimeFormat, wallTime, zoneInfo);
return false;
case 'D':
formatInternal("%m/%d/%y", wallTime, zoneInfo);
return false;
case 'd':
numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
wallTime.getMonthDay());
return false;
case 'E':
case 'O':
// C99 locale modifiers are not supported.
continue;
case '_':
case '-':
case '0':
case '^':
case '#':
modifier = currentChar;
continue;
case 'e':
numberFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"),
wallTime.getMonthDay());
return false;
case 'F':
formatInternal("%Y-%m-%d", wallTime, zoneInfo);
return false;
case 'H':
numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
wallTime.getHour());
return false;
case 'I':
int hour = (wallTime.getHour() % 12 != 0) ? (wallTime.getHour() % 12) : 12;
numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), hour);
return false;
case 'j':
int yearDay = wallTime.getYearDay() + 1;
numberFormatter.format(getFormat(modifier, "%03d", "%3d", "%d", "%03d"),
yearDay);
return false;
case 'k':
numberFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"),
wallTime.getHour());
return false;
case 'l':
int n2 = (wallTime.getHour() % 12 != 0) ? (wallTime.getHour() % 12) : 12;
numberFormatter.format(getFormat(modifier, "%2d", "%2d", "%d", "%02d"), n2);
return false;
case 'M':
numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
wallTime.getMinute());
return false;
case 'm':
numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
wallTime.getMonth() + 1);
return false;
case 'n':
outputBuilder.append('\n');
return false;
case 'p':
modifyAndAppend((wallTime.getHour() >= (HOURSPERDAY / 2)) ? localeData.amPm[1]
: localeData.amPm[0], modifier);
return false;
case 'P':
modifyAndAppend((wallTime.getHour() >= (HOURSPERDAY / 2)) ? localeData.amPm[1]
: localeData.amPm[0], FORCE_LOWER_CASE);
return false;
case 'R':
formatInternal("%H:%M", wallTime, zoneInfo);
return false;
case 'r':
formatInternal("%I:%M:%S %p", wallTime, zoneInfo);
return false;
case 'S':
numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
wallTime.getSecond());
return false;
case 's':
int timeInSeconds = wallTime.mktime(zoneInfo);
outputBuilder.append(Integer.toString(timeInSeconds));
return false;
case 'T':
formatInternal("%H:%M:%S", wallTime, zoneInfo);
return false;
case 't':
outputBuilder.append('\t');
return false;
case 'U':
numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"),
(wallTime.getYearDay() + DAYSPERWEEK - wallTime.getWeekDay())
/ DAYSPERWEEK);
return false;
case 'u':
int day = (wallTime.getWeekDay() == 0) ? DAYSPERWEEK : wallTime.getWeekDay();
numberFormatter.format("%d", day);
return false;
case 'V': /* ISO 8601 week number */
case 'G': /* ISO 8601 year (four digits) */
case 'g': /* ISO 8601 year (two digits) */
{
int year = wallTime.getYear();
int yday = wallTime.getYearDay();
int wday = wallTime.getWeekDay();
int w;
while (true) {
int len = isLeap(year) ? DAYSPERLYEAR : DAYSPERNYEAR;
// What yday (-3 ... 3) does the ISO year begin on?
int bot = ((yday + 11 - wday) % DAYSPERWEEK) - 3;
// What yday does the NEXT ISO year begin on?
int top = bot - (len % DAYSPERWEEK);
if (top < -3) {
top += DAYSPERWEEK;
}
top += len;
if (yday >= top) {
++year;
w = 1;
break;
}
if (yday >= bot) {
w = 1 + ((yday - bot) / DAYSPERWEEK);
break;
}
--year;
yday += isLeap(year) ? DAYSPERLYEAR : DAYSPERNYEAR;
}
if (currentChar == 'V') {
numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), w);
} else if (currentChar == 'g') {
outputYear(year, false, true, modifier);
} else {
outputYear(year, true, true, modifier);
}
return false;
}
case 'v':
formatInternal("%e-%b-%Y", wallTime, zoneInfo);
return false;
case 'W':
int n = (wallTime.getYearDay() + DAYSPERWEEK - (
wallTime.getWeekDay() != 0 ? (wallTime.getWeekDay() - 1)
: (DAYSPERWEEK - 1))) / DAYSPERWEEK;
numberFormatter.format(getFormat(modifier, "%02d", "%2d", "%d", "%02d"), n);
return false;
case 'w':
numberFormatter.format("%d", wallTime.getWeekDay());
return false;
case 'X':
formatInternal(timeOnlyFormat, wallTime, zoneInfo);
return false;
case 'x':
formatInternal(dateOnlyFormat, wallTime, zoneInfo);
return false;
case 'y':
outputYear(wallTime.getYear(), false, true, modifier);
return false;
case 'Y':
outputYear(wallTime.getYear(), true, true, modifier);
return false;
case 'Z':
if (wallTime.getIsDst() < 0) {
return false;
}
boolean isDst = wallTime.getIsDst() != 0;
modifyAndAppend(zoneInfo.getDisplayName(isDst, TimeZone.SHORT), modifier);
return false;
case 'z': {
if (wallTime.getIsDst() < 0) {
return false;
}
int diff = wallTime.getGmtOffset();
char sign;
if (diff < 0) {
sign = '-';
diff = -diff;
} else {
sign = '+';
}
outputBuilder.append(sign);
diff /= SECSPERMIN;
diff = (diff / MINSPERHOUR) * 100 + (diff % MINSPERHOUR);
numberFormatter.format(getFormat(modifier, "%04d", "%4d", "%d", "%04d"), diff);
return false;
}
case '+':
formatInternal("%a %b %e %H:%M:%S %Z %Y", wallTime, zoneInfo);
return false;
case '%':
// If conversion char is undefined, behavior is undefined. Print out the
// character itself.
default:
return true;
}
}
return true;
}