SimpleDateFormatpublic class SimpleDateFormat extends DateFormat A concrete class for formatting and parsing dates in a locale-sensitive
manner. It allows for formatting (date to text), parsing (text to date) and
normalization.
{@code SimpleDateFormat} 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
getDateInstance}, or {@code getDateTimeInstance} in {@code DateFormat}. 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} methods as desired. For more information on using these
methods, see {@link DateFormat}.
Time Format Syntax
To specify the time format, use a time pattern string. In this
pattern, all ASCII letters are reserved as pattern letters, which are defined
as follows:
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 |
fractional second |
(Number) |
978 |
E |
day of 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 |
Z |
time zone (RFC 822) |
(Number) |
-0800 |
v |
time zone (generic) |
(Text) |
Pacific Time |
V |
time zone (location) |
(Text) |
United States (Los Angeles) |
' |
escape for text |
(Delimiter) |
'Date=' |
'' |
single quote |
(Literal) |
'o''clock' |
The count of pattern letters determines the format:
(Text): 4 or more pattern letters → use the full form,
less than 4 pattern letters → use a short or abbreviated form if one
exists.
(Number): 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. (if "yyyy" produces
"1997", "yy" produces "97".) Unlike other fields, fractional seconds are
padded on the right with zero.
(Text & Number): 3 or over, use text, otherwise use number.
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.
A pattern containing any invalid pattern letter will result in an exception
thrown during formatting or parsing.
Examples Using the US Locale
Format Pattern Result
-------------- -------
"yyyy.MM.dd G 'at' HH:mm:ss vvvv" → 1996.07.10 AD at 15:08:56 Pacific Time
"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, vvv" → 0:00 PM, PT
"yyyyy.MMMMM.dd GGG hh:mm aaa" → 01996.July.10 AD 12:08 PM
Code Sample:
SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, "PST");
pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
// Format the current time.
SimpleDateFormat formatter = new SimpleDateFormat(
"yyyy.MM.dd G '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);
In the example, the time value {@code currentTime_2} obtained from parsing
will be equal to {@code currentTime_1}. 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.
When parsing a date string using the abbreviated year pattern ("yy"), {@code
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 {@code SimpleDateFormat} instance is created. For
example, using a pattern of "MM/dd/yy" and a {@code 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. During parsing, only strings consisting of exactly two digits, as
defined by {@link java.lang.Character#isDigit(char)}, will be parsed into the
default century. Any other numeric string, such as a one digit string, a
three or more digit string, or a two digit string that isn't all digits (for
example, "-1"), is interpreted literally. So "01/02/3" or "01/02/003" are
parsed, using the same pattern, as Jan 2, 3 AD. Likewise, "01/02/-3" is
parsed as Jan 2, 4 BC.
If the year pattern does not have exactly two 'y' characters, the year is
interpreted literally, regardless of the number of digits. So using the
pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.
When numeric fields are adjacent directly, with no intervening delimiter
characters, they constitute a run of adjacent numeric fields. Such runs are
parsed specially. For example, the format "HHmmss" parses the input text
"123456" to 12:34:56, parses the input text "12345" to 1:23:45, and fails to
parse "1234". In other words, the leftmost field of the run is flexible,
while the others keep a fixed width. If the parse fails anywhere in the run,
then the leftmost field is shortened by one character, and the entire run is
parsed again. This is repeated until either the parse succeeds or the
leftmost field is one character in length. If the parse still fails at that
point, the parse of the run fails.
For time zones that have no names, use the strings "GMT+hours:minutes" or
"GMT-hours:minutes".
The calendar defines 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.
Synchronization Date formats are not synchronized. It is recommended
to create separate format instances for each thread. If multiple threads
access a format concurrently, it must be synchronized externally. |
Fields Summary |
---|
private static final long | serialVersionUID | private static final String | patternChars | private String | pattern | private DateFormatSymbols | formatData | private transient int | creationYear | private Date | defaultCenturyStart | private static final ObjectStreamField[] | serialPersistentFields |
Constructors Summary |
---|
public SimpleDateFormat()Constructs a new {@code SimpleDateFormat} for formatting and parsing
dates and times in the {@code SHORT} style for the default locale.
this(Locale.getDefault());
pattern = defaultPattern();
formatData = new DateFormatSymbols(Locale.getDefault());
| public SimpleDateFormat(String pattern)Constructs a new {@code SimpleDateFormat} using the specified
non-localized pattern and the {@code DateFormatSymbols} and {@code
Calendar} for the default locale.
this(pattern, Locale.getDefault());
| public SimpleDateFormat(String template, DateFormatSymbols value)Constructs a new {@code SimpleDateFormat} using the specified
non-localized pattern and {@code DateFormatSymbols} and the {@code
Calendar} for the default locale.
this(Locale.getDefault());
validatePattern(template);
pattern = template;
formatData = (DateFormatSymbols) value.clone();
| public SimpleDateFormat(String template, Locale locale)Constructs a new {@code SimpleDateFormat} using the specified
non-localized pattern and the {@code DateFormatSymbols} and {@code
Calendar} for the specified locale.
this(locale);
validatePattern(template);
pattern = template;
formatData = new DateFormatSymbols(locale);
| private SimpleDateFormat(Locale locale)
numberFormat = NumberFormat.getInstance(locale);
numberFormat.setParseIntegerOnly(true);
numberFormat.setGroupingUsed(false);
calendar = new GregorianCalendar(locale);
calendar.add(Calendar.YEAR, -80);
creationYear = calendar.get(Calendar.YEAR);
defaultCenturyStart = calendar.getTime();
|
Methods Summary |
---|
private void | append(java.lang.StringBuffer buffer, java.text.FieldPosition position, java.util.Vector fields, char format, int count)
int field = -1;
int index = patternChars.indexOf(format);
if (index == -1) {
// text.03=Unknown pattern character - '{0}'
throw new IllegalArgumentException(Messages.getString(
"text.03", format)); //$NON-NLS-1$
}
int beginPosition = buffer.length();
Field dateFormatField = null;
switch (index) {
case ERA_FIELD:
dateFormatField = Field.ERA;
buffer.append(formatData.eras[calendar.get(Calendar.ERA)]);
break;
case YEAR_FIELD:
dateFormatField = Field.YEAR;
int year = calendar.get(Calendar.YEAR);
if (count < 4) {
appendNumber(buffer, 2, year %= 100);
} else {
appendNumber(buffer, count, year);
}
break;
case MONTH_FIELD:
dateFormatField = Field.MONTH;
int month = calendar.get(Calendar.MONTH);
if (count <= 2) {
appendNumber(buffer, count, month + 1);
} else if (count == 3) {
buffer.append(formatData.shortMonths[month]);
} else {
buffer.append(formatData.months[month]);
}
break;
case DATE_FIELD:
dateFormatField = Field.DAY_OF_MONTH;
field = Calendar.DATE;
break;
case HOUR_OF_DAY1_FIELD: // k
dateFormatField = Field.HOUR_OF_DAY1;
int hour = calendar.get(Calendar.HOUR_OF_DAY);
appendNumber(buffer, count, hour == 0 ? 24 : hour);
break;
case HOUR_OF_DAY0_FIELD: // H
dateFormatField = Field.HOUR_OF_DAY0;
field = Calendar.HOUR_OF_DAY;
break;
case MINUTE_FIELD:
dateFormatField = Field.MINUTE;
field = Calendar.MINUTE;
break;
case SECOND_FIELD:
dateFormatField = Field.SECOND;
field = Calendar.SECOND;
break;
case MILLISECOND_FIELD:
dateFormatField = Field.MILLISECOND;
int value = calendar.get(Calendar.MILLISECOND);
appendNumber(buffer, count, value);
break;
case DAY_OF_WEEK_FIELD:
dateFormatField = Field.DAY_OF_WEEK;
int day = calendar.get(Calendar.DAY_OF_WEEK);
if (count < 4) {
buffer.append(formatData.shortWeekdays[day]);
} else {
buffer.append(formatData.weekdays[day]);
}
break;
case DAY_OF_YEAR_FIELD:
dateFormatField = Field.DAY_OF_YEAR;
field = Calendar.DAY_OF_YEAR;
break;
case DAY_OF_WEEK_IN_MONTH_FIELD:
dateFormatField = Field.DAY_OF_WEEK_IN_MONTH;
field = Calendar.DAY_OF_WEEK_IN_MONTH;
break;
case WEEK_OF_YEAR_FIELD:
dateFormatField = Field.WEEK_OF_YEAR;
field = Calendar.WEEK_OF_YEAR;
break;
case WEEK_OF_MONTH_FIELD:
dateFormatField = Field.WEEK_OF_MONTH;
field = Calendar.WEEK_OF_MONTH;
break;
case AM_PM_FIELD:
dateFormatField = Field.AM_PM;
buffer.append(formatData.ampms[calendar.get(Calendar.AM_PM)]);
break;
case HOUR1_FIELD: // h
dateFormatField = Field.HOUR1;
hour = calendar.get(Calendar.HOUR);
appendNumber(buffer, count, hour == 0 ? 12 : hour);
break;
case HOUR0_FIELD: // K
dateFormatField = Field.HOUR0;
field = Calendar.HOUR;
break;
case TIMEZONE_FIELD: // z
dateFormatField = Field.TIME_ZONE;
appendTimeZone(buffer, count, true);
break;
case (TIMEZONE_FIELD + 1): // Z
dateFormatField = Field.TIME_ZONE;
appendTimeZone(buffer, count, false);
break;
}
if (field != -1) {
appendNumber(buffer, count, calendar.get(field));
}
if (fields != null) {
position = new FieldPosition(dateFormatField);
position.setBeginIndex(beginPosition);
position.setEndIndex(buffer.length());
fields.add(position);
} else {
// Set to the first occurrence
if ((position.getFieldAttribute() == dateFormatField || (position
.getFieldAttribute() == null && position.getField() == index))
&& position.getEndIndex() == 0) {
position.setBeginIndex(beginPosition);
position.setEndIndex(buffer.length());
}
}
| private void | appendNumber(java.lang.StringBuffer buffer, int count, int value)
int minimumIntegerDigits = numberFormat.getMinimumIntegerDigits();
numberFormat.setMinimumIntegerDigits(count);
numberFormat.format(new Integer(value), buffer, new FieldPosition(0));
numberFormat.setMinimumIntegerDigits(minimumIntegerDigits);
| private void | appendTimeZone(java.lang.StringBuffer buffer, int count, boolean generalTimezone)
// cannot call TimeZone.getDisplayName() because it would not use
// the DateFormatSymbols of this SimpleDateFormat
if (generalTimezone) {
String id = calendar.getTimeZone().getID();
// BEGIN android-changed
String[][] zones = formatData.internalZoneStrings();
// END android-changed
String[] zone = null;
for (String[] element : zones) {
if (id.equals(element[0])) {
zone = element;
break;
}
}
if (zone == null) {
int offset = calendar.get(Calendar.ZONE_OFFSET)
+ calendar.get(Calendar.DST_OFFSET);
char sign = '+";
if (offset < 0) {
sign = '-";
offset = -offset;
}
buffer.append("GMT"); //$NON-NLS-1$
buffer.append(sign);
appendNumber(buffer, 2, offset / 3600000);
buffer.append(':");
appendNumber(buffer, 2, (offset % 3600000) / 60000);
} else {
int daylight = calendar.get(Calendar.DST_OFFSET) == 0 ? 0 : 2;
if (count < 4) {
buffer.append(zone[2 + daylight]);
} else {
buffer.append(zone[1 + daylight]);
}
}
} else {
int offset = calendar.get(Calendar.ZONE_OFFSET)
+ calendar.get(Calendar.DST_OFFSET);
char sign = '+";
if (offset < 0) {
sign = '-";
offset = -offset;
}
buffer.append(sign);
appendNumber(buffer, 2, offset / 3600000);
appendNumber(buffer, 2, (offset % 3600000) / 60000);
}
| public void | applyLocalizedPattern(java.lang.String template)Changes the pattern of this simple date format to the specified pattern
which uses localized pattern characters.
pattern = convertPattern(template, formatData.getLocalPatternChars(),
patternChars, true);
| public void | applyPattern(java.lang.String template)Changes the pattern of this simple date format to the specified pattern
which uses non-localized pattern characters.
validatePattern(template);
pattern = template;
| public java.lang.Object | clone()Returns a new {@code SimpleDateFormat} with the same pattern and
properties as this simple date format.
SimpleDateFormat clone = (SimpleDateFormat) super.clone();
clone.formatData = (DateFormatSymbols) formatData.clone();
clone.defaultCenturyStart = new Date(defaultCenturyStart.getTime());
return clone;
| private static java.lang.String | defaultPattern()
ResourceBundle bundle = getBundle(Locale.getDefault());
String styleName = getStyleName(SHORT);
return bundle.getString("Date_" + styleName) + " " //$NON-NLS-1$ //$NON-NLS-2$
+ bundle.getString("Time_" + styleName); //$NON-NLS-1$
| public boolean | equals(java.lang.Object object)Compares the specified object with this simple date format and indicates
if they are equal. In order to be equal, {@code object} must be an
instance of {@code SimpleDateFormat} and have the same {@code DateFormat}
properties, pattern, {@code DateFormatSymbols} and creation year.
if (this == object) {
return true;
}
if (!(object instanceof SimpleDateFormat)) {
return false;
}
SimpleDateFormat simple = (SimpleDateFormat) object;
return super.equals(object) && pattern.equals(simple.pattern)
&& formatData.equals(simple.formatData);
| private java.util.Date | error(java.text.ParsePosition position, int offset, java.util.TimeZone zone)
position.setErrorIndex(offset);
calendar.setTimeZone(zone);
return null;
| public java.lang.StringBuffer | format(java.util.Date date, java.lang.StringBuffer buffer, java.text.FieldPosition field)Formats the specified date as a string using the pattern of this date
format and appends the string to the specified string buffer.
If the {@code field} member of {@code field} contains a value specifying
a format field, then its {@code beginIndex} and {@code endIndex} members
will be updated with the position of the first occurrence of this field
in the formatted text.
return formatImpl(date, buffer, field, null);
| private java.lang.StringBuffer | formatImpl(java.util.Date date, java.lang.StringBuffer buffer, java.text.FieldPosition field, java.util.Vector fields)Formats the date.
If the FieldPosition {@code field} is not null, and the field
specified by this FieldPosition is formatted, set the begin and end index
of the formatted field in the FieldPosition.
If the Vector {@code fields} is not null, find fields of this
date, set FieldPositions with these fields, and add them to the fields
vector.
boolean quote = false;
int next, last = -1, count = 0;
calendar.setTime(date);
if (field != null) {
field.clear();
}
final int patternLength = pattern.length();
for (int i = 0; i < patternLength; i++) {
next = (pattern.charAt(i));
if (next == '\'") {
if (count > 0) {
append(buffer, field, fields, (char) last, count);
count = 0;
}
if (last == next) {
buffer.append('\'");
last = -1;
} else {
last = next;
}
quote = !quote;
continue;
}
if (!quote
&& (last == next || (next >= 'a" && next <= 'z") || (next >= 'A" && next <= 'Z"))) {
if (last == next) {
count++;
} else {
if (count > 0) {
append(buffer, field, fields, (char) last, count);
}
last = next;
count = 1;
}
} else {
if (count > 0) {
append(buffer, field, fields, (char) last, count);
count = 0;
}
last = -1;
buffer.append((char) next);
}
}
if (count > 0) {
append(buffer, field, fields, (char) last, count);
}
return buffer;
| public java.text.AttributedCharacterIterator | formatToCharacterIterator(java.lang.Object object)Formats the specified object using the rules of this simple date format
and returns an {@code AttributedCharacterIterator} with the formatted
date and attributes.
if (object == null) {
throw new NullPointerException();
}
if (object instanceof Date) {
return formatToCharacterIteratorImpl((Date) object);
}
if (object instanceof Number) {
return formatToCharacterIteratorImpl(new Date(((Number) object)
.longValue()));
}
throw new IllegalArgumentException();
| private java.text.AttributedCharacterIterator | formatToCharacterIteratorImpl(java.util.Date date)
StringBuffer buffer = new StringBuffer();
Vector<FieldPosition> fields = new Vector<FieldPosition>();
// format the date, and find fields
formatImpl(date, buffer, null, fields);
// create and AttributedString with the formatted buffer
AttributedString as = new AttributedString(buffer.toString());
// add DateFormat field attributes to the AttributedString
for (int i = 0; i < fields.size(); i++) {
FieldPosition pos = fields.elementAt(i);
Format.Field attribute = pos.getFieldAttribute();
as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos
.getEndIndex());
}
// return the CharacterIterator from AttributedString
return as.getIterator();
| public java.util.Date | get2DigitYearStart()Returns the date which is the start of the one hundred year period for
two digits year values.
return defaultCenturyStart;
| public java.text.DateFormatSymbols | getDateFormatSymbols()Returns the {@code DateFormatSymbols} used by this simple date format.
// Return a clone so the arrays in the ResourceBundle are not modified
return (DateFormatSymbols) formatData.clone();
| public int | hashCode()
return super.hashCode() + pattern.hashCode() + formatData.hashCode()
+ creationYear;
| private int | parse(java.lang.String string, int offset, char format, int count)
int index = patternChars.indexOf(format);
if (index == -1) {
// text.03=Unknown pattern character - '{0}'
throw new IllegalArgumentException(Messages.getString(
"text.03", format)); //$NON-NLS-1$
}
int field = -1;
int absolute = 0;
if (count < 0) {
count = -count;
absolute = count;
}
switch (index) {
case ERA_FIELD:
return parseText(string, offset, formatData.eras, Calendar.ERA);
case YEAR_FIELD:
if (count >= 3) {
field = Calendar.YEAR;
} else {
ParsePosition position = new ParsePosition(offset);
Number result = parseNumber(absolute, string, position);
if (result == null) {
return -position.getErrorIndex() - 1;
}
int year = result.intValue();
// A two digit year must be exactly two digits, i.e. 01
if ((position.getIndex() - offset) == 2 && year >= 0) {
year += creationYear / 100 * 100;
if (year < creationYear) {
year += 100;
}
}
calendar.set(Calendar.YEAR, year);
return position.getIndex();
}
break;
case MONTH_FIELD:
if (count <= 2) {
return parseNumber(absolute, string, offset,
Calendar.MONTH, -1);
}
index = parseText(string, offset, formatData.months,
Calendar.MONTH);
if (index < 0) {
return parseText(string, offset, formatData.shortMonths,
Calendar.MONTH);
}
return index;
case DATE_FIELD:
field = Calendar.DATE;
break;
case HOUR_OF_DAY1_FIELD:
ParsePosition position = new ParsePosition(offset);
Number result = parseNumber(absolute, string, position);
if (result == null) {
return -position.getErrorIndex() - 1;
}
int hour = result.intValue();
if (hour == 24) {
hour = 0;
}
calendar.set(Calendar.HOUR_OF_DAY, hour);
return position.getIndex();
case HOUR_OF_DAY0_FIELD:
field = Calendar.HOUR_OF_DAY;
break;
case MINUTE_FIELD:
field = Calendar.MINUTE;
break;
case SECOND_FIELD:
field = Calendar.SECOND;
break;
case MILLISECOND_FIELD:
field = Calendar.MILLISECOND;
break;
case DAY_OF_WEEK_FIELD:
index = parseText(string, offset, formatData.weekdays,
Calendar.DAY_OF_WEEK);
if (index < 0) {
return parseText(string, offset, formatData.shortWeekdays,
Calendar.DAY_OF_WEEK);
}
return index;
case DAY_OF_YEAR_FIELD:
field = Calendar.DAY_OF_YEAR;
break;
case DAY_OF_WEEK_IN_MONTH_FIELD:
field = Calendar.DAY_OF_WEEK_IN_MONTH;
break;
case WEEK_OF_YEAR_FIELD:
field = Calendar.WEEK_OF_YEAR;
break;
case WEEK_OF_MONTH_FIELD:
field = Calendar.WEEK_OF_MONTH;
break;
case AM_PM_FIELD:
return parseText(string, offset, formatData.ampms,
Calendar.AM_PM);
case HOUR1_FIELD:
position = new ParsePosition(offset);
result = parseNumber(absolute, string, position);
if (result == null) {
return -position.getErrorIndex() - 1;
}
hour = result.intValue();
if (hour == 12) {
hour = 0;
}
calendar.set(Calendar.HOUR, hour);
return position.getIndex();
case HOUR0_FIELD:
field = Calendar.HOUR;
break;
case TIMEZONE_FIELD:
return parseTimeZone(string, offset);
case (TIMEZONE_FIELD + 1):
return parseTimeZone(string, offset);
}
if (field != -1) {
return parseNumber(absolute, string, offset, field, 0);
}
return offset;
| public java.util.Date | parse(java.lang.String string, java.text.ParsePosition position)Parses a date from the specified string starting at the index specified
by {@code position}. If the string is successfully parsed then the index
of the {@code ParsePosition} is updated to the index following the parsed
text. On error, the index is unchanged and the error index of {@code
ParsePosition} is set to the index where the error occurred.
boolean quote = false;
int next, last = -1, count = 0, offset = position.getIndex();
int length = string.length();
calendar.clear();
TimeZone zone = calendar.getTimeZone();
final int patternLength = pattern.length();
for (int i = 0; i < patternLength; i++) {
next = pattern.charAt(i);
if (next == '\'") {
if (count > 0) {
if ((offset = parse(string, offset, (char) last, count)) < 0) {
return error(position, -offset - 1, zone);
}
count = 0;
}
if (last == next) {
if (offset >= length || string.charAt(offset) != '\'") {
return error(position, offset, zone);
}
offset++;
last = -1;
} else {
last = next;
}
quote = !quote;
continue;
}
if (!quote
&& (last == next || (next >= 'a" && next <= 'z") || (next >= 'A" && next <= 'Z"))) {
if (last == next) {
count++;
} else {
if (count > 0) {
if ((offset = parse(string, offset, (char) last, -count)) < 0) {
return error(position, -offset - 1, zone);
}
}
last = next;
count = 1;
}
} else {
if (count > 0) {
if ((offset = parse(string, offset, (char) last, count)) < 0) {
return error(position, -offset - 1, zone);
}
count = 0;
}
last = -1;
if (offset >= length || string.charAt(offset) != next) {
return error(position, offset, zone);
}
offset++;
}
}
if (count > 0) {
if ((offset = parse(string, offset, (char) last, count)) < 0) {
return error(position, -offset - 1, zone);
}
}
Date date;
try {
date = calendar.getTime();
} catch (IllegalArgumentException e) {
return error(position, offset, zone);
}
position.setIndex(offset);
calendar.setTimeZone(zone);
return date;
| private java.lang.Number | parseNumber(int max, java.lang.String string, java.text.ParsePosition position)
int digit, length = string.length(), result = 0;
int index = position.getIndex();
if (max > 0 && max < length - index) {
length = index + max;
}
while (index < length
&& (string.charAt(index) == ' " || string.charAt(index) == '\t")) {
index++;
}
if (max == 0) {
position.setIndex(index);
return numberFormat.parse(string, position);
}
while (index < length
&& (digit = Character.digit(string.charAt(index), 10)) != -1) {
index++;
result = result * 10 + digit;
}
if (index == position.getIndex()) {
position.setErrorIndex(index);
return null;
}
position.setIndex(index);
return new Integer(result);
| private int | parseNumber(int max, java.lang.String string, int offset, int field, int skew)
ParsePosition position = new ParsePosition(offset);
Number result = parseNumber(max, string, position);
if (result == null) {
return -position.getErrorIndex() - 1;
}
calendar.set(field, result.intValue() + skew);
return position.getIndex();
| private int | parseText(java.lang.String string, int offset, java.lang.String[] text, int field)
int found = -1;
for (int i = 0; i < text.length; i++) {
if (text[i].length() == 0) {
continue;
}
if (string
.regionMatches(true, offset, text[i], 0, text[i].length())) {
// Search for the longest match, in case some fields are subsets
if (found == -1 || text[i].length() > text[found].length()) {
found = i;
}
}
}
if (found != -1) {
calendar.set(field, found);
return offset + text[found].length();
}
return -offset - 1;
| private int | parseTimeZone(java.lang.String string, int offset)
// BEGIN android-changed
String[][] zones = formatData.internalZoneStrings();
// END android-changed
boolean foundGMT = string.regionMatches(offset, "GMT", 0, 3); //$NON-NLS-1$
if (foundGMT) {
offset += 3;
}
char sign;
if (offset < string.length()
&& ((sign = string.charAt(offset)) == '+" || sign == '-")) {
ParsePosition position = new ParsePosition(offset + 1);
Number result = numberFormat.parse(string, position);
if (result == null) {
return -position.getErrorIndex() - 1;
}
int hour = result.intValue();
int raw = hour * 3600000;
int index = position.getIndex();
if (index < string.length() && string.charAt(index) == ':") {
position.setIndex(index + 1);
result = numberFormat.parse(string, position);
if (result == null) {
return -position.getErrorIndex() - 1;
}
int minute = result.intValue();
raw += minute * 60000;
} else if (hour >= 24) {
raw = (hour / 100 * 3600000) + (hour % 100 * 60000);
}
if (sign == '-") {
raw = -raw;
}
calendar.setTimeZone(new SimpleTimeZone(raw, "")); //$NON-NLS-1$
return position.getIndex();
}
if (foundGMT) {
calendar.setTimeZone(TimeZone.getTimeZone("GMT")); //$NON-NLS-1$
return offset;
}
for (String[] element : zones) {
for (int j = 1; j < 5; j++) {
if (string.regionMatches(true, offset, element[j], 0,
element[j].length())) {
TimeZone zone = TimeZone.getTimeZone(element[0]);
if (zone == null) {
return -offset - 1;
}
int raw = zone.getRawOffset();
if (j >= 3 && zone.useDaylightTime()) {
raw += 3600000;
}
calendar.setTimeZone(new SimpleTimeZone(raw, "")); //$NON-NLS-1$
return offset + element[j].length();
}
}
}
return -offset - 1;
| private void | readObject(java.io.ObjectInputStream stream)
ObjectInputStream.GetField fields = stream.readFields();
int version = fields.get("serialVersionOnStream", 0); //$NON-NLS-1$
Date date;
if (version > 0) {
date = (Date) fields.get("defaultCenturyStart", new Date()); //$NON-NLS-1$
} else {
date = new Date();
}
set2DigitYearStart(date);
formatData = (DateFormatSymbols) fields.get("formatData", null); //$NON-NLS-1$
pattern = (String) fields.get("pattern", ""); //$NON-NLS-1$ //$NON-NLS-2$
| public void | set2DigitYearStart(java.util.Date date)Sets the date which is the start of the one hundred year period for two
digits year values.
defaultCenturyStart = date;
Calendar cal = new GregorianCalendar();
cal.setTime(date);
creationYear = cal.get(Calendar.YEAR);
| public void | setDateFormatSymbols(java.text.DateFormatSymbols value)Sets the {@code DateFormatSymbols} used by this simple date format.
formatData = (DateFormatSymbols) value.clone();
| public java.lang.String | toLocalizedPattern()Returns the pattern of this simple date format using localized pattern
characters.
return convertPattern(pattern, patternChars, formatData
.getLocalPatternChars(), false);
| public java.lang.String | toPattern()Returns the pattern of this simple date format using non-localized
pattern characters.
return pattern;
| private void | validateFormat(char format)Validates the format character.
int index = patternChars.indexOf(format);
if (index == -1) {
// text.03=Unknown pattern character - '{0}'
throw new IllegalArgumentException(Messages.getString(
"text.03", format)); //$NON-NLS-1$
}
| private void | validatePattern(java.lang.String template)Validates the pattern.
boolean quote = false;
int next, last = -1, count = 0;
final int patternLength = template.length();
for (int i = 0; i < patternLength; i++) {
next = (template.charAt(i));
if (next == '\'") {
if (count > 0) {
validateFormat((char) last);
count = 0;
}
if (last == next) {
last = -1;
} else {
last = next;
}
quote = !quote;
continue;
}
if (!quote
&& (last == next || (next >= 'a" && next <= 'z") || (next >= 'A" && next <= 'Z"))) {
if (last == next) {
count++;
} else {
if (count > 0) {
validateFormat((char) last);
}
last = next;
count = 1;
}
} else {
if (count > 0) {
validateFormat((char) last);
count = 0;
}
last = -1;
}
}
if (count > 0) {
validateFormat((char) last);
}
if (quote) {
// text.04=Unterminated quote {0}
throw new IllegalArgumentException(Messages.getString("text.04")); //$NON-NLS-1$
}
| private void | writeObject(java.io.ObjectOutputStream stream) //$NON-NLS-1$
ObjectOutputStream.PutField fields = stream.putFields();
fields.put("defaultCenturyStart", defaultCenturyStart); //$NON-NLS-1$
fields.put("formatData", formatData); //$NON-NLS-1$
fields.put("pattern", pattern); //$NON-NLS-1$
fields.put("serialVersionOnStream", 1); //$NON-NLS-1$
stream.writeFields();
|
|