📄 simpledateformat.java
字号:
/**
* Overrides DateFormat
* <p>Formats a date or time, which is the standard millis
* since January 1, 1970, 00:00:00 GMT.
* <p>Example: using the US locale:
* "yyyy.MM.dd e 'at' HH:mm:ss zzz" ->> 1996.07.10 AD at 15:08:56 PDT
* @param date the date-time value to be formatted into a date-time string.
* @param toAppendTo where the new date-time text is to be appended.
* @param pos the formatting position. On input: an alignment field,
* if desired. On output: the offsets of the alignment field.
* @return the formatted date-time string.
* @see java.util.DateFormat
*/
public StringBuffer format(Date date, StringBuffer toAppendTo,
FieldPosition pos)
{
// Initialize
pos.beginIndex = pos.endIndex = 0;
// Convert input date to time field list
calendar.setTime(date);
boolean inQuote = false; // inQuote set true when hits 1st single quote
char prevCh = 0;
int count = 0; // number of time pattern characters repeated
int interQuoteCount = 1; // Number of characters between quotes
for (int i=0; i<pattern.length(); ++i)
{
char ch = pattern.charAt(i);
if (inQuote)
{
if (ch == '\'')
{
// ends with 2nd single quote
inQuote = false;
if (count == 0)
toAppendTo.append(ch); // two consecutive quotes outside a quote: ''
else count = 0;
interQuoteCount = 0;
}
else
{
toAppendTo.append(ch);
count++;
}
}
else // !inQuote
{
if (ch == '\'')
{
inQuote = true;
if (count > 0) // handle cases like: yyyy'....
{
toAppendTo.append(subFormat(prevCh, count,
toAppendTo.length(),
pos));
count = 0;
prevCh = 0;
}
// We count characters between quotes so we can recognize
// two single quotes inside a quote. Example: 'o''clock'.
if (interQuoteCount == 0)
{
toAppendTo.append(ch);
count = 1; // Make it look like we never left.
}
}
else if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')
{
// ch is a date-time pattern
if (ch != prevCh && count > 0) //handle cases: eg, yyyyMMdd
{
toAppendTo.append(subFormat(prevCh, count,
toAppendTo.length(),
pos));
prevCh = ch;
count = 1;
}
else
{
if (ch != prevCh)
prevCh = ch;
count++;
}
}
else if (count > 0) // handle cases like: MM-dd-yy or HH:mm:ss
{
toAppendTo.append(subFormat(prevCh, count,
toAppendTo.length(),
pos));
toAppendTo.append(ch);
prevCh = 0;
count = 0;
}
else // any other unquoted characters
toAppendTo.append(ch);
++interQuoteCount;
}
}
// Format the last item in the pattern
if (count > 0)
{
toAppendTo.append(subFormat(prevCh, count,
toAppendTo.length(), pos));
}
return toAppendTo;
}
// Map index into pattern character string to Calendar field number
private static final int[] PATTERN_INDEX_TO_CALENDAR_FIELD =
{
Calendar.ERA, Calendar.YEAR, Calendar.MONTH, Calendar.DATE,
Calendar.HOUR_OF_DAY, Calendar.HOUR_OF_DAY, Calendar.MINUTE,
Calendar.SECOND, Calendar.MILLISECOND, Calendar.DAY_OF_WEEK,
Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK_IN_MONTH,
Calendar.WEEK_OF_YEAR, Calendar.WEEK_OF_MONTH,
Calendar.AM_PM, Calendar.HOUR, Calendar.HOUR, Calendar.ZONE_OFFSET
};
// Map index into pattern character string to DateFormat field number
private static final int[] PATTERN_INDEX_TO_DATE_FORMAT_FIELD = {
DateFormat.ERA_FIELD, DateFormat.YEAR_FIELD, DateFormat.MONTH_FIELD,
DateFormat.DATE_FIELD, DateFormat.HOUR_OF_DAY1_FIELD,
DateFormat.HOUR_OF_DAY0_FIELD, DateFormat.MINUTE_FIELD,
DateFormat.SECOND_FIELD, DateFormat.MILLISECOND_FIELD,
DateFormat.DAY_OF_WEEK_FIELD, DateFormat.DAY_OF_YEAR_FIELD,
DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD, DateFormat.WEEK_OF_YEAR_FIELD,
DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.AM_PM_FIELD,
DateFormat.HOUR1_FIELD, DateFormat.HOUR0_FIELD,
DateFormat.TIMEZONE_FIELD,
};
// Private member function that does the real date/time formatting.
private String subFormat(char ch, int count, int beginOffset,
FieldPosition pos)
throws IllegalArgumentException
{
int patternCharIndex = -1;
int maxIntCount = 10;
String current = "";
if ((patternCharIndex=formatData.patternChars.indexOf(ch)) == -1)
throw new IllegalArgumentException("Illegal pattern character " +
"'" + ch + "'");
int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
int value = calendar.get(field);
switch (patternCharIndex) {
case 0: // 'G' - ERA
current = formatData.eras[value];
break;
case 1: // 'y' - YEAR
if (count >= 4)
// current = zeroPaddingNumber(value, 4, count);
current = zeroPaddingNumber(value, 4, maxIntCount);
else // count < 4
current = zeroPaddingNumber(value, 2, 2); // clip 1996 to 96
break;
case 2: // 'M' - MONTH
if (count >= 4)
current = formatData.months[value];
else if (count == 3)
current = formatData.shortMonths[value];
else
current = zeroPaddingNumber(value+1, count, maxIntCount);
break;
case 4: // 'k' - HOUR_OF_DAY: 1-based. eg, 23:59 + 1 hour =>> 24:59
if (value == 0)
current = zeroPaddingNumber(
calendar.getMaximum(Calendar.HOUR_OF_DAY)+1,
count, maxIntCount);
else
current = zeroPaddingNumber(value, count, maxIntCount);
break;
case 8: // 'S' - MILLISECOND
if (count > 3)
count = 3;
else if (count == 2)
value = value / 10;
else if (count == 1)
value = value / 100;
current = zeroPaddingNumber(value, count, maxIntCount);
break;
case 9: // 'E' - DAY_OF_WEEK
if (count >= 4)
current = formatData.weekdays[value];
else // count < 4, use abbreviated form if exists
current = formatData.shortWeekdays[value];
break;
case 14: // 'a' - AM_PM
current = formatData.ampms[value];
break;
case 15: // 'h' - HOUR:1-based. eg, 11PM + 1 hour =>> 12 AM
if (value == 0)
current = zeroPaddingNumber(
calendar.getLeastMaximum(Calendar.HOUR)+1,
count, maxIntCount);
else
current = zeroPaddingNumber(value, count, maxIntCount);
break;
case 17: // 'z' - ZONE_OFFSET
int zoneIndex
= formatData.getZoneIndex (calendar.getTimeZone().getID());
if (zoneIndex == -1)
{
// For time zones that have no names, use strings
// GMT+hours:minutes and GMT-hours:minutes.
// For instance, France time zone uses GMT+01:00.
StringBuffer zoneString = new StringBuffer();
value = calendar.get(Calendar.ZONE_OFFSET) +
calendar.get(Calendar.DST_OFFSET);
if (value < 0)
{
zoneString.append(GMT_MINUS);
value = -value; // suppress the '-' sign for text display.
}
else
zoneString.append(GMT_PLUS);
zoneString.append(
zeroPaddingNumber((int)(value/millisPerHour), 2, 2));
zoneString.append(':');
zoneString.append(
zeroPaddingNumber(
(int)((value%millisPerHour)/millisPerMinute), 2, 2));
current = zoneString.toString();
}
else if (calendar.get(Calendar.DST_OFFSET) != 0)
{
if (count >= 4)
current = formatData.zoneStrings[zoneIndex][3];
else
// count < 4, use abbreviated form if exists
current = formatData.zoneStrings[zoneIndex][4];
}
else
{
if (count >= 4)
current = formatData.zoneStrings[zoneIndex][1];
else
current = formatData.zoneStrings[zoneIndex][2];
}
break;
default:
// case 3: // 'd' - DATE
// case 5: // 'H' - HOUR_OF_DAY:0-based. eg, 23:59 + 1 hour =>> 00:59
// case 6: // 'm' - MINUTE
// case 7: // 's' - SECOND
// case 10: // 'D' - DAY_OF_YEAR
// case 11: // 'F' - DAY_OF_WEEK_IN_MONTH
// case 12: // 'w' - WEEK_OF_YEAR
// case 13: // 'W' - WEEK_OF_MONTH
// case 16: // 'K' - HOUR: 0-based. eg, 11PM + 1 hour =>> 0 AM
current = zeroPaddingNumber(value, count, maxIntCount);
break;
} // switch (patternCharIndex)
if (pos.field == PATTERN_INDEX_TO_DATE_FORMAT_FIELD[patternCharIndex]) {
// set for the first occurence only.
if (pos.beginIndex == 0 && pos.endIndex == 0) {
pos.beginIndex = beginOffset;
pos.endIndex = beginOffset + current.length();
}
}
return current;
}
// Pad the shorter numbers up to maxCount digits.
private String zeroPaddingNumber(long value, int minDigits, int maxDigits)
{
numberFormat.setMinimumIntegerDigits(minDigits);
numberFormat.setMaximumIntegerDigits(maxDigits);
return numberFormat.format(value);
}
/**
* Overrides DateFormat
* @see java.util.DateFormat
*/
public Date parse(String text, ParsePosition pos)
{
int start = pos.index;
int oldStart = start;
boolean[] ambiguousYear = {false};
calendar.clear(); // Clears all the time fields
boolean inQuote = false; // inQuote set true when hits 1st single quote
char prevCh = 0;
int count = 0;
int interQuoteCount = 1; // Number of chars between quotes
for (int i=0; i<pattern.length(); ++i)
{
char ch = pattern.charAt(i);
if (inQuote)
{
if (ch == '\'')
{
// ends with 2nd single quote
inQuote = false;
// two consecutive quotes outside a quote means we have
// a quote literal we need to match.
if (count == 0)
{
if (ch != text.charAt(start))
{
pos.index = oldStart;
return null;
}
++start;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -