📄 simpledateformat.java
字号:
} i--; } continue; } int tag; if ((tag = formatData.patternChars.indexOf(c)) == -1) { throw new IllegalArgumentException("Illegal pattern character " + "'" + c + "'"); } if (lastTag == -1 || lastTag == tag) { lastTag = tag; count++; continue; } encode(lastTag, count, compiledPattern); lastTag = tag; count = 1; } if (inQuote) { throw new IllegalArgumentException("Unterminated quote"); } if (count != 0) { encode(lastTag, count, compiledPattern); } // Copy the compiled pattern to a char array int len = compiledPattern.length(); char[] r = new char[len]; compiledPattern.getChars(0, len, r, 0); return r; } /** * Encodes the given tag and length and puts encoded char(s) into buffer. */ private static final void encode(int tag, int length, StringBuffer buffer) { if (length < 255) { buffer.append((char)(tag << 8 | length)); } else { buffer.append((char)((tag << 8) | 0xff)); buffer.append((char)(length >>> 16)); buffer.append((char)(length & 0xffff)); } } /* Initialize the fields we use to disambiguate ambiguous years. Separate * so we can call it from readObject(). */ private void initializeDefaultCentury() { calendar.setTime( new Date() ); calendar.add( Calendar.YEAR, -80 ); parseAmbiguousDatesAsAfter(calendar.getTime()); } /* Define one-century window into which to disambiguate dates using * two-digit years. */ private void parseAmbiguousDatesAsAfter(Date startDate) { defaultCenturyStart = startDate; calendar.setTime(startDate); defaultCenturyStartYear = calendar.get(Calendar.YEAR); } /** * Sets the 100-year period 2-digit years will be interpreted as being in * to begin on the date the user specifies. * * @param startDate During parsing, two digit years will be placed in the range * <code>startDate</code> to <code>startDate + 100 years</code>. * @see #get2DigitYearStart * @since 1.2 */ public void set2DigitYearStart(Date startDate) { parseAmbiguousDatesAsAfter(startDate); } /** * Returns the beginning date of the 100-year period 2-digit years are interpreted * as being within. * * @return the start of the 100-year period into which two digit years are * parsed * @see #set2DigitYearStart * @since 1.2 */ public Date get2DigitYearStart() { return defaultCenturyStart; } /** * Formats the given <code>Date</code> into a date/time string and appends * the result to the given <code>StringBuffer</code>. * * @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. * @exception NullPointerException if the given date is null */ public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) { pos.beginIndex = pos.endIndex = 0; return format(date, toAppendTo, pos.getFieldDelegate()); } // Called from Format after creating a FieldDelegate private StringBuffer format(Date date, StringBuffer toAppendTo, FieldDelegate delegate) { // Convert input date to time field list calendar.setTime(date); for (int i = 0; i < compiledPattern.length; ) { int tag = compiledPattern[i] >>> 8; int count = compiledPattern[i++] & 0xff; if (count == 255) { count = compiledPattern[i++] << 16; count |= compiledPattern[i++]; } switch (tag) { case TAG_QUOTE_ASCII_CHAR: toAppendTo.append((char)count); break; case TAG_QUOTE_CHARS: toAppendTo.append(compiledPattern, i, count); i += count; break; default: subFormat(tag, count, delegate, toAppendTo); break; } } return toAppendTo; } /** * Formats an Object producing an <code>AttributedCharacterIterator</code>. * You can use the returned <code>AttributedCharacterIterator</code> * to build the resulting String, as well as to determine information * about the resulting String. * <p> * Each attribute key of the AttributedCharacterIterator will be of type * <code>DateFormat.Field</code>, with the corresponding attribute value * being the same as the attribute key. * * @exception NullPointerException if obj is null. * @exception IllegalArgumentException if the Format cannot format the * given object, or if the Format's pattern string is invalid. * @param obj The object to format * @return AttributedCharacterIterator describing the formatted value. * @since 1.4 */ public AttributedCharacterIterator formatToCharacterIterator(Object obj) { StringBuffer sb = new StringBuffer(); CharacterIteratorFieldDelegate delegate = new CharacterIteratorFieldDelegate(); if (obj instanceof Date) { format((Date)obj, sb, delegate); } else if (obj instanceof Number) { format(new Date(((Number)obj).longValue()), sb, delegate); } else if (obj == null) { throw new NullPointerException( "formatToCharacterIterator must be passed non-null object"); } else { throw new IllegalArgumentException( "Cannot format given Object as a Date"); } return delegate.getIterator(sb.toString()); } // 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, 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, DateFormat.TIMEZONE_FIELD, }; // Maps from DecimalFormatSymbols index to Field constant private static final Field[] PATTERN_INDEX_TO_DATE_FORMAT_FIELD_ID = { Field.ERA, Field.YEAR, Field.MONTH, Field.DAY_OF_MONTH, Field.HOUR_OF_DAY1, Field.HOUR_OF_DAY0, Field.MINUTE, Field.SECOND, Field.MILLISECOND, Field.DAY_OF_WEEK, Field.DAY_OF_YEAR, Field.DAY_OF_WEEK_IN_MONTH, Field.WEEK_OF_YEAR, Field.WEEK_OF_MONTH, Field.AM_PM, Field.HOUR1, Field.HOUR0, Field.TIME_ZONE, Field.TIME_ZONE, }; /** * Private member function that does the real date/time formatting. */ private void subFormat(int patternCharIndex, int count, FieldDelegate delegate, StringBuffer buffer) { int maxIntCount = Integer.MAX_VALUE; String current = null; int beginOffset = buffer.length(); int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex]; int value = calendar.get(field); // Note: zeroPaddingNumber() assumes that maxDigits is either // 2 or maxIntCount. If we make any changes to this, // zeroPaddingNumber() must be fixed. switch (patternCharIndex) { case 0: // 'G' - ERA current = formatData.eras[value]; break; case 1: // 'y' - YEAR if (count >= 4) zeroPaddingNumber(value, count, maxIntCount, buffer); else // count < 4 zeroPaddingNumber(value, 2, 2, buffer); // 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 zeroPaddingNumber(value+1, count, maxIntCount, buffer); break; case 4: // 'k' - HOUR_OF_DAY: 1-based. eg, 23:59 + 1 hour =>> 24:59 if (value == 0) zeroPaddingNumber(calendar.getMaximum(Calendar.HOUR_OF_DAY)+1, count, maxIntCount, buffer); else zeroPaddingNumber(value, count, maxIntCount, buffer); 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) zeroPaddingNumber(calendar.getLeastMaximum(Calendar.HOUR)+1, count, maxIntCount, buffer); else zeroPaddingNumber(value, count, maxIntCount, buffer); 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. value = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); if (value < 0) { buffer.append(GMT_MINUS); value = -value; // suppress the '-' sign for text display. } else { buffer.append(GMT_PLUS); } int num = value / millisPerHour; if (num < 10) { buffer.append('0'); } buffer.append(num); buffer.append(':'); num = (value % millisPerHour) / millisPerMinute; if (num < 10) { buffer.append('0'); } buffer.append(num); } 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; case 18: // 'Z' - ZONE_OFFSET ("-/+hhmm" form) value = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); if (value < 0) { buffer.append('-'); value = -value; // suppress the '-' sign for text display. } else { buffer.append('+'); } int num = value / millisPerHour; if (num < 10) { buffer.append('0');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -