📄 simpledateformat.java
字号:
/*
* @(#)SimpleDateFormat.java 1.31 98/08/27
*
* (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
* (C) Copyright IBM Corp. 1996 - All Rights Reserved
*
* Portions copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
*
* The original version of this source code and documentation is copyrighted
* and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
* materials are provided under terms of a License Agreement between Taligent
* and Sun. This technology is protected by multiple US and International
* patents. This notice and attribution to Taligent may not be removed.
* Taligent is a registered trademark of Taligent, Inc.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies. Please refer to the file "copyright.html"
* for further important copyright and licensing information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package java.text;
import java.util.TimeZone;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.SimpleTimeZone;
import java.util.GregorianCalendar;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.lang.ClassNotFoundException;
import java.util.Hashtable;
/**
* <code>SimpleDateFormat</code> is a concrete class for formatting and
* parsing dates in a locale-sensitive manner. It allows for formatting
* (date -> text), parsing (text -> date), and normalization.
*
* <p>
* <code>SimpleDateFormat</code> allows you to start by choosing
* any user-defined patterns for date-time formatting. However, you
* are encouraged to create a date-time formatter with either
* <code>getTimeInstance</code>, <code>getDateInstance</code>, or
* <code>getDateTimeInstance</code> in <code>DateFormat</code>. Each
* of these class methods can return a date/time formatter initialized
* with a default format pattern. You may modify the format pattern
* using the <code>applyPattern</code> methods as desired.
* For more information on using these methods, see
* <a href="java.text.DateFormat.html"><code>DateFormat</code></a>.
*
* <p>
* <strong>Time Format Syntax:</strong>
* <p>
* To specify the time format use a <em>time pattern</em> string.
* In this pattern, all ASCII letters are reserved as pattern letters,
* which are defined as the following:
* <blockquote>
* <pre>
* Symbol Meaning Presentation Example
* ------ ------- ------------ -------
* G era designator (Text) AD
* y year (Number) 1996
* M month in year (Text & Number) July & 07
* d day in month (Number) 10
* h hour in am/pm (1~12) (Number) 12
* H hour in day (0~23) (Number) 0
* m minute in hour (Number) 30
* s second in minute (Number) 55
* S millisecond (Number) 978
* E day in week (Text) Tuesday
* D day in year (Number) 189
* F day of week in month (Number) 2 (2nd Wed in July)
* w week in year (Number) 27
* W week in month (Number) 2
* a am/pm marker (Text) PM
* k hour in day (1~24) (Number) 24
* K hour in am/pm (0~11) (Number) 0
* z time zone (Text) Pacific Standard Time
* ' escape for text (Delimiter)
* '' single quote (Literal) '
* </pre>
* </blockquote>
* The count of pattern letters determine the format.
* <p>
* <strong>(Text)</strong>: 4 or more pattern letters--use full form,
* < 4--use short or abbreviated form if one exists.
* <p>
* <strong>(Number)</strong>: the minimum number of digits. Shorter
* numbers are zero-padded to this amount. Year is handled specially;
* that is, if the count of 'y' is 2, the Year will be truncated to 2 digits.
* <p>
* <strong>(Text & Number)</strong>: 3 or over, use text, otherwise use number.
* <p>
* Any characters in the pattern that are not in the ranges of ['a'..'z']
* and ['A'..'Z'] will be treated as quoted text. For instance, characters
* like ':', '.', ' ', '#' and '@' will appear in the resulting time text
* even they are not embraced within single quotes.
* <p>
* A pattern containing any invalid pattern letter will result in a thrown
* exception during formatting or parsing.
*
* <p>
* <strong>Examples Using the US Locale:</strong>
* <blockquote>
* <pre>
* Format Pattern Result
* -------------- -------
* "yyyy.MM.dd G 'at' hh:mm:ss z" ->> 1996.07.10 AD at 15:08:56 PDT
* "EEE, MMM d, ''yy" ->> Wed, July 10, '96
* "h:mm a" ->> 12:08 PM
* "hh 'o''clock' a, zzzz" ->> 12 o'clock PM, Pacific Daylight Time
* "K:mm a, z" ->> 0:00 PM, PST
* "yyyyy.MMMMM.dd GGG hh:mm aaa" ->> 1996.July.10 AD 12:08 PM
* </pre>
* </blockquote>
* <strong>Code Sample:</strong>
* <pre>
* <blockquote>
* SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, "PST");
* pdt.setStartRule(DateFields.APRIL, 1, DateFields.SUNDAY, 2*60*60*1000);
* pdt.setEndRule(DateFields.OCTOBER, -1, DateFields.SUNDAY, 2*60*60*1000);
*
* // Format the current time.
* SimpleDateFormat formatter
* = new SimpleDateFormat ("yyyy.mm.dd e 'at' hh:mm:ss a zzz");
* Date currentTime_1 = new Date();
* String dateString = formatter.format(currentTime_1);
*
* // Parse the previous string back into a Date.
* ParsePosition pos = new ParsePosition(0);
* Date currentTime_2 = formatter.parse(dateString, pos);
* </pre>
* </blockquote>
* In the example, the time value <code>currentTime_2</code> obtained from
* parsing will be equal to <code>currentTime_1</code>. However, they may not be
* equal if the am/pm marker 'a' is left out from the format pattern while
* the "hour in am/pm" pattern symbol is used. This information loss can
* happen when formatting the time in PM.
*
* <p>
* When parsing a date string using the abbreviated year pattern,
* SimpleDateFormat must interpret the abbreviated year
* relative to some century. It does this by adjusting dates to be
* within 80 years before and 20 years after the time the SimpleDateFormat
* instance is created. For example, using a pattern of MM/dd/yy and a
* SimpleDateFormat instance created on Jan 1, 1997, the string
* "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64"
* would be interpreted as May 4, 1964.
*
* <p>
* For time zones that have no names, use strings GMT+hours:minutes or
* GMT-hours:minutes.
*
* <p>
* The calendar defines what is the first day of the week, the first week
* of the year, whether hours are zero based or not (0 vs 12 or 24), and the
* time zone. There is one common decimal format to handle all the numbers;
* the digit count is handled programmatically according to the pattern.
*
* @see java.util.Calendar
* @see java.util.GregorianCalendar
* @see java.util.TimeZone
* @see DateFormat
* @see DateFormatSymbols
* @see DecimalFormat
* @version 1.31 08/27/98
* @author Mark Davis, Chen-Lieh Huang, Alan Liu
*/
public class SimpleDateFormat extends DateFormat {
// the official serial version ID which says cryptically
// which version we're compatible with
static final long serialVersionUID = 4774881970558875024L;
// the internal serial version which says which version was written
// - 0 (default) for version up to JDK 1.1.3
// - 1 for version from JDK 1.1.4, which includes a new field
static final int currentSerialVersion = 1;
private int serialVersionOnStream = currentSerialVersion;
private String pattern;
private DateFormatSymbols formatData;
// if dates have ambiguous years, we map them into the century starting
// at defaultCenturyStart, which may be any date.
private Date defaultCenturyStart; // field new in JDK 1.1.4
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 final Hashtable cachedLocaleData = new Hashtable(3);
/**
* Construct a SimpleDateFormat using the default pattern for the default
* locale. <b>Note:</b> Not all locales support SimpleDateFormat; for full
* generality, use the factory methods in the DateFormat class.
*
* @see java.text.DateFormat
*/
public SimpleDateFormat() {
this(SHORT, SHORT + 4, Locale.getDefault());
}
/**
* Construct a SimpleDateFormat using the given pattern in the default
* locale. <b>Note:</b> Not all locales support SimpleDateFormat; for full
* generality, use the factory methods in the DateFormat class.
*/
public SimpleDateFormat(String pattern)
{
this(pattern, Locale.getDefault());
}
/**
* Construct a SimpleDateFormat using the given pattern and locale.
* <b>Note:</b> Not all locales support SimpleDateFormat; for full
* generality, use the factory methods in the DateFormat class.
*/
public SimpleDateFormat(String pattern, Locale loc)
{
this.pattern = pattern;
this.formatData = new DateFormatSymbols(loc);
initialize(loc);
}
/**
* Construct a SimpleDateFormat using the given pattern and
* locale-specific symbol data.
*/
public SimpleDateFormat(String pattern, DateFormatSymbols formatData)
{
this.pattern = pattern;
this.formatData = (DateFormatSymbols) formatData.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 = ResourceBundle.getBundle
("java.text.resources.LocaleElements", 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]};
pattern = MessageFormat.format(dateTimePatterns[8], dateTimeArgs);
}
else if (timeStyle >= 0)
pattern = dateTimePatterns[timeStyle];
else if (dateStyle >= 0)
pattern = dateTimePatterns[dateStyle];
else
throw new IllegalArgumentException("No date or time style specified");
initialize(loc);
}
/* Initialize calendar and numberFormat fields */
private void initialize(Locale loc) {
// 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);
numberFormat = NumberFormat.getInstance(loc);
numberFormat.setGroupingUsed(false);
if (numberFormat instanceof DecimalFormat)
((DecimalFormat)numberFormat).setDecimalSeparatorAlwaysShown(false);
numberFormat.setParseIntegerOnly(true); /* So that dd.mm.yy can be parsed */
numberFormat.setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
initializeDefaultCentury();
}
/* 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. Make public in JDK 1.2.
*/
private void parseAmbiguousDatesAsAfter(Date startDate) {
defaultCenturyStart = startDate;
calendar.setTime(startDate);
defaultCenturyStartYear = calendar.get(Calendar.YEAR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -