📄 simpledateformat.java
字号:
*/ private int serialVersionOnStream = currentSerialVersion; /** * The pattern string of this formatter. This is always a non-localized * pattern. May not be null. See class documentation for details. * @serial */ private String pattern; /** * The compiled pattern. */ transient private char[] compiledPattern; /** * Tags for the compiled pattern. */ private final static int TAG_QUOTE_ASCII_CHAR = 100; private final static int TAG_QUOTE_CHARS = 101; /** * Locale dependent digit zero. * @see #zeroPaddingNumber * @see java.text.DecimalFormatSymbols#getZeroDigit */ transient private char zeroDigit; /** * The symbols used by this formatter for week names, month names, * etc. May not be null. * @serial * @see java.text.DateFormatSymbols */ private DateFormatSymbols formatData; /** * We map dates with two-digit years into the century starting at * <code>defaultCenturyStart</code>, which may be any date. May * not be null. * @serial * @since JDK1.1.4 */ private Date defaultCenturyStart; transient private int defaultCenturyStartYear; private static final int millisPerHour = 60 * 60 * 1000; private static final int millisPerMinute = 60 * 1000; // For time zones that have no names, use strings GMT+minutes and // GMT-minutes. For instance, in France the time zone is GMT+60. private static final String GMT_PLUS = "GMT+"; private static final String GMT_MINUS = "GMT-"; private static final String GMT = "GMT"; /** * Cache to hold the DateTimePatterns of a Locale. */ private static Hashtable cachedLocaleData = new Hashtable(3); /** * Cache NumberFormat instances with Locale key. */ private static Hashtable cachedNumberFormatData = new Hashtable(3); /** * Constructs a <code>SimpleDateFormat</code> using the default pattern and * date format symbols for the default locale. * <b>Note:</b> This constructor may not support all locales. * For full coverage, use the factory methods in the {@link DateFormat} * class. */ public SimpleDateFormat() { this(SHORT, SHORT, Locale.getDefault()); } /** * Constructs a <code>SimpleDateFormat</code> using the given pattern and * the default date format symbols for the default locale. * <b>Note:</b> This constructor may not support all locales. * For full coverage, use the factory methods in the {@link DateFormat} * class. * * @param pattern the pattern describing the date and time format * @exception NullPointerException if the given pattern is null * @exception IllegalArgumentException if the given pattern is invalid */ public SimpleDateFormat(String pattern) { this(pattern, Locale.getDefault()); } /** * Constructs a <code>SimpleDateFormat</code> using the given pattern and * the default date format symbols for the given locale. * <b>Note:</b> This constructor may not support all locales. * For full coverage, use the factory methods in the {@link DateFormat} * class. * * @param pattern the pattern describing the date and time format * @param locale the locale whose date format symbols should be used * @exception NullPointerException if the given pattern is null * @exception IllegalArgumentException if the given pattern is invalid */ public SimpleDateFormat(String pattern, Locale locale) { this.pattern = pattern; this.formatData = new DateFormatSymbols(locale); initialize(locale); } /** * Constructs a <code>SimpleDateFormat</code> using the given pattern and * date format symbols. * * @param pattern the pattern describing the date and time format * @param formatSymbols the date format symbols to be used for formatting * @exception NullPointerException if the given pattern or formatSymbols is null * @exception IllegalArgumentException if the given pattern is invalid */ public SimpleDateFormat(String pattern, DateFormatSymbols formatSymbols) { this.pattern = pattern; this.formatData = (DateFormatSymbols) formatSymbols.clone(); initialize(Locale.getDefault()); } /* Package-private, called by DateFormat factory methods */ SimpleDateFormat(int timeStyle, int dateStyle, Locale loc) { /* try the cache first */ String[] dateTimePatterns = (String[]) cachedLocaleData.get(loc); if (dateTimePatterns == null) { /* cache miss */ ResourceBundle r = LocaleData.getLocaleElements(loc); dateTimePatterns = r.getStringArray("DateTimePatterns"); /* update cache */ cachedLocaleData.put(loc, dateTimePatterns); } formatData = new DateFormatSymbols(loc); if ((timeStyle >= 0) && (dateStyle >= 0)) { Object[] dateTimeArgs = {dateTimePatterns[timeStyle], dateTimePatterns[dateStyle + 4]}; pattern = MessageFormat.format(dateTimePatterns[8], dateTimeArgs); } else if (timeStyle >= 0) { pattern = dateTimePatterns[timeStyle]; } else if (dateStyle >= 0) { pattern = dateTimePatterns[dateStyle + 4]; } else { throw new IllegalArgumentException("No date or time style specified"); } initialize(loc); } /* Initialize calendar and numberFormat fields */ private void initialize(Locale loc) { // Verify and compile the given pattern. compiledPattern = compile(pattern); // The format object must be constructed using the symbols for this zone. // However, the calendar should use the current default TimeZone. // If this is not contained in the locale zone strings, then the zone // will be formatted using generic GMT+/-H:MM nomenclature. calendar = Calendar.getInstance(TimeZone.getDefault(), loc); /* try the cache first */ numberFormat = (NumberFormat) cachedNumberFormatData.get(loc); if (numberFormat == null) { /* cache miss */ numberFormat = NumberFormat.getIntegerInstance(loc); numberFormat.setGroupingUsed(false); /* update cache */ cachedNumberFormatData.put(loc, numberFormat); } numberFormat = (NumberFormat) numberFormat.clone(); initializeDefaultCentury(); } /** * Returns the compiled form of the given pattern. The syntax of * the compiled pattern is: * <blockquote> * CompiledPattern: * EntryList * EntryList: * Entry * EntryList Entry * Entry: * TagField * TagField data * TagField: * Tag Length * TaggedData * Tag: * pattern_char_index * TAG_QUOTE_CHARS * Length: * short_length * long_length * TaggedData: * TAG_QUOTE_ASCII_CHAR ascii_char * * </blockquote> * * where `short_length' is an 8-bit unsigned integer between 0 and * 254. `long_length' is a sequence of an 8-bit integer 255 and a * 32-bit signed integer value which is split into upper and lower * 16-bit fields in two char's. `pattern_char_index' is an 8-bit * integer between 0 and 18. `ascii_char' is an 7-bit ASCII * character value. `data' depends on its Tag value. * <p> * If Length is short_length, Tag and short_length are packed in a * single char, as illustrated below. * <blockquote> * char[0] = (Tag << 8) | short_length; * </blockquote> * * If Length is long_length, Tag and 255 are packed in the first * char and a 32-bit integer, as illustrated below. * <blockquote> * char[0] = (Tag << 8) | 255; * char[1] = (char) (long_length >>> 16); * char[2] = (char) (long_length & 0xffff); * </blockquote> * <p> * If Tag is a pattern_char_index, its Length is the number of * pattern characters. For example, if the given pattern is * "yyyy", Tag is 1 and Length is 4, followed by no data. * <p> * If Tag is TAG_QUOTE_CHARS, its Length is the number of char's * following the TagField. For example, if the given pattern is * "'o''clock'", Length is 7 followed by a char sequence of * <code>o&nbs;'&nbs;c&nbs;l&nbs;o&nbs;c&nbs;k</code>. * <p> * TAG_QUOTE_ASCII_CHAR is a special tag and has an ASCII * character in place of Length. For example, if the given pattern * is "'o'", the TaggedData entry is * <code>((TAG_QUOTE_ASCII_CHAR&nbs;<<&nbs;8)&nbs;|&nbs;'o')</code>. * * @exception NullPointerException if the given pattern is null * @exception IllegalArgumentException if the given pattern is invalid */ private char[] compile(String pattern) { int length = pattern.length(); boolean inQuote = false; StringBuffer compiledPattern = new StringBuffer(length * 2); StringBuffer tmpBuffer = null; int count = 0; int lastTag = -1; for (int i = 0; i < length; i++) { char c = pattern.charAt(i); if (c == '\'') { // '' is treated as a single quote regardless of being // in a quoted section. if ((i + 1) < length) { c = pattern.charAt(i + 1); if (c == '\'') { i++; if (count != 0) { encode(lastTag, count, compiledPattern); lastTag = -1; count = 0; } if (inQuote) { tmpBuffer.append(c); } else { compiledPattern.append((char)(TAG_QUOTE_ASCII_CHAR << 8 | c)); } continue; } } if (!inQuote) { if (count != 0) { encode(lastTag, count, compiledPattern); lastTag = -1; count = 0; } if (tmpBuffer == null) { tmpBuffer = new StringBuffer(length); } else { tmpBuffer.setLength(0); } inQuote = true; } else { int len = tmpBuffer.length(); if (len == 1) { char ch = tmpBuffer.charAt(0); if (ch < 128) { compiledPattern.append((char)(TAG_QUOTE_ASCII_CHAR << 8 | ch)); } else { compiledPattern.append((char)(TAG_QUOTE_CHARS << 8 | 1)); compiledPattern.append(ch); } } else { encode(TAG_QUOTE_CHARS, len, compiledPattern); compiledPattern.append(tmpBuffer); } inQuote = false; } continue; } if (inQuote) { tmpBuffer.append(c); continue; } if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) { if (count != 0) { encode(lastTag, count, compiledPattern); lastTag = -1; count = 0; } if (c < 128) { // In most cases, c would be a delimiter, such as ':'. compiledPattern.append((char)(TAG_QUOTE_ASCII_CHAR << 8 | c)); } else { // Take any contiguous non-ASCII alphabet characters and // put them in a single TAG_QUOTE_CHARS. int j; for (j = i + 1; j < length; j++) { char d = pattern.charAt(j); if (d == '\'' || (d >= 'a' && d <= 'z' || d >= 'A' && d <= 'Z')) { break; } } compiledPattern.append((char)(TAG_QUOTE_CHARS << 8 | (j - i))); for (; i < j; i++) { compiledPattern.append(pattern.charAt(i));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -