ICU-9108 Cleaned up some garbages and made minor improvements. Ready for review.
X-SVN-Rev: 31463
This commit is contained in:
parent
47890124a7
commit
08b039b84a
@ -351,8 +351,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
|
||||
// We need to preserve time zone type when parsing specific
|
||||
// time zone text (xxx Standard Time vs xxx Daylight Time)
|
||||
private static final int TZTYPE_UNK = 0, TZTYPE_STD = 1, TZTYPE_DST = 2;
|
||||
private transient int tztype = TZTYPE_UNK;
|
||||
private transient TimeType tztype = TimeType.UNKNOWN;
|
||||
|
||||
private static final int millisPerHour = 60 * 60 * 1000;
|
||||
|
||||
@ -1416,7 +1415,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
int start = pos;
|
||||
|
||||
// Reset tztype
|
||||
tztype = TZTYPE_UNK;
|
||||
tztype = TimeType.UNKNOWN;
|
||||
boolean[] ambiguousYear = { false };
|
||||
|
||||
// item index for the first numeric field within a contiguous numeric run
|
||||
@ -1606,7 +1605,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
// front or the back of the default century. This only works because we adjust
|
||||
// the year correctly to start with in other cases -- see subParse().
|
||||
try {
|
||||
if (ambiguousYear[0] || tztype != TZTYPE_UNK) {
|
||||
if (ambiguousYear[0] || tztype != TimeType.UNKNOWN) {
|
||||
// We need a copy of the fields, and we need to avoid triggering a call to
|
||||
// complete(), which will recalculate the fields. Since we can't access
|
||||
// the fields[] array in Calendar, we clone the entire object. This will
|
||||
@ -1620,7 +1619,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
cal.set(Calendar.YEAR, getDefaultCenturyStartYear() + 100);
|
||||
}
|
||||
}
|
||||
if (tztype != TZTYPE_UNK) {
|
||||
if (tztype != TimeType.UNKNOWN) {
|
||||
copy = (Calendar)cal.clone();
|
||||
TimeZone tz = copy.getTimeZone();
|
||||
BasicTimeZone btz = null;
|
||||
@ -1637,7 +1636,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
// matches the rule used by the parsed time zone.
|
||||
int[] offsets = new int[2];
|
||||
if (btz != null) {
|
||||
if (tztype == TZTYPE_STD) {
|
||||
if (tztype == TimeType.STANDARD) {
|
||||
btz.getOffsetFromLocal(localMillis,
|
||||
BasicTimeZone.LOCAL_STD, BasicTimeZone.LOCAL_STD, offsets);
|
||||
} else {
|
||||
@ -1649,8 +1648,8 @@ public class SimpleDateFormat extends DateFormat {
|
||||
// but following code work in most case.
|
||||
tz.getOffset(localMillis, true, offsets);
|
||||
|
||||
if (tztype == TZTYPE_STD && offsets[1] != 0
|
||||
|| tztype == TZTYPE_DST && offsets[1] == 0) {
|
||||
if (tztype == TimeType.STANDARD && offsets[1] != 0
|
||||
|| tztype == TimeType.DAYLIGHT && offsets[1] == 0) {
|
||||
// Roll back one day and try it again.
|
||||
// Note: This code assumes 1. timezone transition only happens
|
||||
// once within 24 hours at max
|
||||
@ -1663,7 +1662,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
// Now, compare the results with parsed type, either standard or
|
||||
// daylight saving time
|
||||
int resolvedSavings = offsets[1];
|
||||
if (tztype == TZTYPE_STD) {
|
||||
if (tztype == TimeType.STANDARD) {
|
||||
if (offsets[1] != 0) {
|
||||
// Override DST_OFFSET = 0 in the result calendar
|
||||
resolvedSavings = 0;
|
||||
@ -2212,11 +2211,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
Style style = (count < 4) ? Style.SPECIFIC_SHORT : Style.SPECIFIC_LONG;
|
||||
TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType);
|
||||
if (tz != null) {
|
||||
if (tzTimeType.value == TimeType.STANDARD) {
|
||||
tztype = TZTYPE_STD;
|
||||
} else if (tzTimeType.value == TimeType.DAYLIGHT) {
|
||||
tztype = TZTYPE_DST;
|
||||
}
|
||||
tztype = tzTimeType.value;
|
||||
cal.setTimeZone(tz);
|
||||
return pos.getIndex();
|
||||
}
|
||||
@ -2228,11 +2223,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
Style style = (count < 4) ? Style.RFC822 : ((count == 5) ? Style.ISO8601 : Style.LOCALIZED_GMT);
|
||||
TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType);
|
||||
if (tz != null) {
|
||||
if (tzTimeType.value == TimeType.STANDARD) {
|
||||
tztype = TZTYPE_STD;
|
||||
} else if (tzTimeType.value == TimeType.DAYLIGHT) {
|
||||
tztype = TZTYPE_DST;
|
||||
}
|
||||
tztype = tzTimeType.value;
|
||||
cal.setTimeZone(tz);
|
||||
return pos.getIndex();
|
||||
}
|
||||
@ -2245,11 +2236,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
Style style = (count < 4) ? Style.GENERIC_SHORT : Style.GENERIC_LONG;
|
||||
TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType);
|
||||
if (tz != null) {
|
||||
if (tzTimeType.value == TimeType.STANDARD) {
|
||||
tztype = TZTYPE_STD;
|
||||
} else if (tzTimeType.value == TimeType.DAYLIGHT) {
|
||||
tztype = TZTYPE_DST;
|
||||
}
|
||||
tztype = tzTimeType.value;
|
||||
cal.setTimeZone(tz);
|
||||
return pos.getIndex();
|
||||
}
|
||||
@ -2262,11 +2249,7 @@ public class SimpleDateFormat extends DateFormat {
|
||||
Style style = (count < 4) ? Style.SPECIFIC_SHORT : Style.GENERIC_LOCATION;
|
||||
TimeZone tz = tzFormat().parse(style, text, pos, tzTimeType);
|
||||
if (tz != null) {
|
||||
if (tzTimeType.value == TimeType.STANDARD) {
|
||||
tztype = TZTYPE_STD;
|
||||
} else if (tzTimeType.value == TimeType.DAYLIGHT) {
|
||||
tztype = TZTYPE_DST;
|
||||
}
|
||||
tztype = tzTimeType.value;
|
||||
cal.setTimeZone(tz);
|
||||
return pos.getIndex();
|
||||
}
|
||||
|
@ -244,7 +244,8 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
*/
|
||||
private transient volatile TimeZoneGenericNames _gnames;
|
||||
|
||||
private transient String[] _gmtPatternTokens;
|
||||
private transient String _gmtPatternPrefix;
|
||||
private transient String _gmtPatternSuffix;
|
||||
private transient Object[][] _gmtOffsetPatternItems;
|
||||
|
||||
private transient String _region;
|
||||
@ -273,15 +274,18 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
GMTOffsetPatternType.POSITIVE_HM, GMTOffsetPatternType.NEGATIVE_HM,
|
||||
};
|
||||
|
||||
private static final int MILLIS_PER_HOUR = 60 * 60 * 1000;
|
||||
private static final int MILLIS_PER_MINUTE = 60 * 1000;
|
||||
private static final int MILLIS_PER_SECOND = 1000;
|
||||
|
||||
// Maximum offset (exclusive) in millisecond supported by offset formats
|
||||
private static final int MAX_OFFSET = 24 * MILLIS_PER_HOUR;
|
||||
|
||||
// Maximum values for GMT offset fields
|
||||
private static final int MAX_OFFSET_HOUR = 23;
|
||||
private static final int MAX_OFFSET_MINUTE = 59;
|
||||
private static final int MAX_OFFSET_SECOND = 59;
|
||||
|
||||
private static final int MILLIS_PER_HOUR = 60 * 60 * 1000;
|
||||
private static final int MILLIS_PER_MINUTE = 60 * 1000;
|
||||
private static final int MILLIS_PER_SECOND = 1000;
|
||||
|
||||
private static final int UNKNOWN_OFFSET = Integer.MAX_VALUE;
|
||||
|
||||
private static TimeZoneFormatCache _tzfCache = new TimeZoneFormatCache();
|
||||
@ -621,13 +625,15 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
* @param offset the offset from GMT(UTC) in milliseconds.
|
||||
* @return the RFC822 style GMT(UTC) offset format.
|
||||
* @see #parseOffsetRFC822(String, ParsePosition)
|
||||
* @throws IllegalArgumentException if the specified offset is out of supported range
|
||||
* (-24 hours < offset < +24 hours).
|
||||
* @draft ICU 49
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public final String formatOffsetRFC822(int offset) {
|
||||
// Note: OffsetFields.HMS as maxFields is an ICU extension. RFC822 specification
|
||||
// defines exactly 4 digits for the offset field in HHss format.
|
||||
return formatOffsetWithASCIIDigits(offset, null, OffsetFields.HM, OffsetFields.HMS);
|
||||
return formatOffsetWithAsciiDigits(offset, null, OffsetFields.HM, OffsetFields.HMS);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -637,6 +643,8 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
* @param offset the offset from GMT(UTC) in milliseconds.
|
||||
* @return the ISO 8601 style GMT(UTC) offset format.
|
||||
* @see #parseOffsetISO8601(String, ParsePosition)
|
||||
* @throws IllegalArgumentException if the specified offset is out of supported range
|
||||
* (-24 hours < offset < +24 hours).
|
||||
* @draft ICU 49
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
@ -646,7 +654,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
}
|
||||
// Note: OffsetFields.HMS as maxFields is an ICU extension. ISO 8601 specification does
|
||||
// not support second field.
|
||||
return formatOffsetWithASCIIDigits(offset, ':', OffsetFields.HM, OffsetFields.HMS);
|
||||
return formatOffsetWithAsciiDigits(offset, ':', OffsetFields.HM, OffsetFields.HMS);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -661,6 +669,8 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
* @param offset the offset from GMT(UTC) in milliseconds.
|
||||
* @return the localized GMT format string
|
||||
* @see #parseOffsetLocalizedGMT(String, ParsePosition)
|
||||
* @throws IllegalArgumentException if the specified offset is out of supported range
|
||||
* (-24 hours < offset < +24 hours).
|
||||
* @draft ICU 49
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
@ -698,7 +708,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
}
|
||||
|
||||
// Building the GMT format string
|
||||
buf.append(_gmtPatternTokens[0]);
|
||||
buf.append(_gmtPatternPrefix);
|
||||
|
||||
for (Object item : offsetPatternItems) {
|
||||
if (item instanceof String) {
|
||||
@ -720,7 +730,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.append(_gmtPatternTokens[1]);
|
||||
buf.append(_gmtPatternSuffix);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@ -858,7 +868,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
|
||||
// Parse digits
|
||||
pos.setIndex(start + 1);
|
||||
int offset = parseContiguousAsciiDigitOffset(text, pos, OffsetFields.H, OffsetFields.HMS, false);
|
||||
int offset = parseAbuttingAsciiOffsetFields(text, pos, OffsetFields.H, OffsetFields.HMS, false);
|
||||
|
||||
if (pos.getErrorIndex() != -1) {
|
||||
pos.setIndex(start); // reset
|
||||
@ -906,206 +916,6 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
return parseOffsetLocalizedGMT(text, pos, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>TimeZone</code> by parsing the time zone string according to
|
||||
* the specified parse position, the style and the parse options.
|
||||
* <p>
|
||||
* <b>Note:</b>When the input text does not match the specified style, this method
|
||||
* evaluate the input using the following order and return the longest match.
|
||||
* <ol>
|
||||
* <li>ISO 8601 style time zone format</li>
|
||||
* <li>RFC822 style time zone format</li>
|
||||
* <li>Localized GMT offset format</li>
|
||||
* <li>Time zone display names available for the given <code>style</code> argument</li>
|
||||
* <li>When {@link ParseOption#ALL_STYLES} is enabled in the parse options, all time zone
|
||||
* display names other than the <code>style</code></li>
|
||||
* </ol>
|
||||
* @param text the text contains a time zone string at the position.
|
||||
* @param style the format style
|
||||
* @param pos the position.
|
||||
* @param options the parse options to be used, or null to use the default parse options.
|
||||
* @param timeType The output argument for receiving the time type (standard/daylight/unknown),
|
||||
* or specify null if the information is not necessary.
|
||||
* @return A <code>TimeZone</code>, or null if the input could not be parsed.
|
||||
* @see Style
|
||||
* @see ParseOption
|
||||
* @draft ICU 49
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public TimeZone parseX(Style style, String text, ParsePosition pos, EnumSet<ParseOption> options, Output<TimeType> timeType) {
|
||||
boolean parseAllStyles;
|
||||
if (options == null) {
|
||||
parseAllStyles = _parseAllStyles;
|
||||
} else {
|
||||
parseAllStyles = options.contains(ParseOption.ALL_STYLES);
|
||||
}
|
||||
|
||||
if (timeType != null) {
|
||||
timeType.value = TimeType.UNKNOWN;
|
||||
}
|
||||
|
||||
int startIdx = pos.getIndex();
|
||||
ParsePosition tmpPos = new ParsePosition(startIdx);
|
||||
|
||||
// try RFC822
|
||||
int offset = parseOffsetRFC822(text, tmpPos);
|
||||
if (tmpPos.getErrorIndex() < 0) {
|
||||
pos.setIndex(tmpPos.getIndex());
|
||||
return getTimeZoneForOffset(offset);
|
||||
}
|
||||
|
||||
// try Localized GMT
|
||||
int gmtZeroLen = 0;
|
||||
tmpPos.setErrorIndex(-1);
|
||||
tmpPos.setIndex(pos.getIndex());
|
||||
Output<Boolean> hasDigitOffset = new Output<Boolean>(false);
|
||||
offset = parseOffsetLocalizedGMT(text, tmpPos, hasDigitOffset);
|
||||
if (tmpPos.getErrorIndex() < 0) {
|
||||
if (hasDigitOffset.value || style == Style.LOCALIZED_GMT || style == Style.RFC822 || tmpPos.getIndex() == text.length()) {
|
||||
// When GMT zero format was detected, we won't try other styles if;
|
||||
// 1) LOCALIZED_GMT or RFC822 was requested.
|
||||
// 2) The input text was fully consumed.
|
||||
//
|
||||
// Note: Localized GMT format with offset numbers (such as "GMT+03:00") won't collide with other type of names
|
||||
// practically. But GMT zero formats (localized one + global ones - "GMT", "UTC", "UT") could - for example,
|
||||
// if a locale has a time zone name like "Utah Time", it should not be detected as GMT ("UT" matches the first
|
||||
// 2 letters).
|
||||
pos.setIndex(tmpPos.getIndex());
|
||||
return getTimeZoneForOffset(offset);
|
||||
} else {
|
||||
// Preserve the length of GMT zero format.
|
||||
// If no better matches are found later, GMT should be returned.
|
||||
gmtZeroLen = tmpPos.getIndex() - startIdx;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parseAllStyles && (style == Style.RFC822 || style == Style.LOCALIZED_GMT)) {
|
||||
pos.setErrorIndex(pos.getErrorIndex());
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find the best match within names which are possibly produced by the style
|
||||
if (style == Style.SPECIFIC_LONG || style == Style.SPECIFIC_SHORT) {
|
||||
// Specific styles
|
||||
EnumSet<NameType> nameTypes = null;
|
||||
switch (style) {
|
||||
case SPECIFIC_LONG:
|
||||
nameTypes = EnumSet.of(NameType.LONG_STANDARD, NameType.LONG_DAYLIGHT);
|
||||
break;
|
||||
case SPECIFIC_SHORT:
|
||||
nameTypes = EnumSet.of(NameType.SHORT_STANDARD, NameType.SHORT_DAYLIGHT);
|
||||
break;
|
||||
}
|
||||
Collection<MatchInfo> specificMatches = _tznames.find(text, startIdx, nameTypes);
|
||||
if (specificMatches != null) {
|
||||
int matchLen = 0;
|
||||
MatchInfo bestSpecific = null;
|
||||
for (MatchInfo match : specificMatches) {
|
||||
if (bestSpecific == null || match.matchLength() > matchLen) {
|
||||
bestSpecific = match;
|
||||
matchLen = match.matchLength();
|
||||
}
|
||||
}
|
||||
if (bestSpecific != null) {
|
||||
if (timeType != null) {
|
||||
timeType.value = getTimeType(bestSpecific.nameType());
|
||||
}
|
||||
pos.setIndex(startIdx + bestSpecific.matchLength());
|
||||
return TimeZone.getTimeZone(getTimeZoneID(bestSpecific.tzID(), bestSpecific.mzID()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Generic styles
|
||||
assert(style == Style.GENERIC_LOCATION || style == Style.GENERIC_LONG || style == Style.GENERIC_SHORT);
|
||||
EnumSet<GenericNameType> genericNameTypes = null;
|
||||
switch (style) {
|
||||
case GENERIC_LOCATION:
|
||||
genericNameTypes = EnumSet.of(GenericNameType.LOCATION);
|
||||
break;
|
||||
case GENERIC_LONG:
|
||||
genericNameTypes = EnumSet.of(GenericNameType.LONG, GenericNameType.LOCATION);
|
||||
break;
|
||||
case GENERIC_SHORT:
|
||||
genericNameTypes = EnumSet.of(GenericNameType.SHORT, GenericNameType.LOCATION);
|
||||
break;
|
||||
}
|
||||
GenericMatchInfo bestGeneric = getTimeZoneGenericNames().findBestMatch(text, startIdx, genericNameTypes);
|
||||
if (bestGeneric != null) {
|
||||
if (timeType != null) {
|
||||
timeType.value = bestGeneric.timeType();
|
||||
}
|
||||
pos.setIndex(startIdx + bestGeneric.matchLength());
|
||||
return TimeZone.getTimeZone(bestGeneric.tzID());
|
||||
}
|
||||
}
|
||||
|
||||
// If GMT zero format was detected at the beginning, but there was no better match found
|
||||
// in names available for the given style, then GMT is returned here.
|
||||
// This should be done before evaluating other names even parseAllStyles is true, because
|
||||
// all styles (except RFC822 and LOCALIZED_GMT itself) use LOCALIZED_GMT as the final
|
||||
// fallback.
|
||||
if (gmtZeroLen > 0) {
|
||||
pos.setIndex(startIdx + gmtZeroLen);
|
||||
return getTimeZoneForOffset(0);
|
||||
}
|
||||
|
||||
// If no match was found above, check if parseAllStyle is enabled.
|
||||
// If so, find the longest match in all possible names.
|
||||
|
||||
// For example, when style is GENERIC_LONG, "EST" (SPECIFIC_SHORT) is never
|
||||
// used for America/New_York. With parseAllStyles true, this code parses "EST"
|
||||
// as America/New_York.
|
||||
if (parseAllStyles) {
|
||||
int maxMatchLength = text.length() - startIdx;
|
||||
|
||||
// Try specific names first
|
||||
Collection<MatchInfo> specificMatches = _tznames.find(text, startIdx, ALL_SPECIFIC_NAME_TYPES);
|
||||
MatchInfo bestSpecific = null;
|
||||
if (specificMatches != null) {
|
||||
int matchLen = 0;
|
||||
for (MatchInfo match : specificMatches) {
|
||||
if (bestSpecific == null || match.matchLength() > matchLen) {
|
||||
bestSpecific = match;
|
||||
matchLen = match.matchLength();
|
||||
}
|
||||
}
|
||||
if (bestSpecific != null && bestSpecific.matchLength() == maxMatchLength) {
|
||||
// complete match
|
||||
if (timeType != null) {
|
||||
timeType.value = getTimeType(bestSpecific.nameType());
|
||||
}
|
||||
pos.setIndex(startIdx + bestSpecific.matchLength());
|
||||
return TimeZone.getTimeZone(getTimeZoneID(bestSpecific.tzID(), bestSpecific.mzID()));
|
||||
}
|
||||
}
|
||||
|
||||
// Then generic names
|
||||
GenericMatchInfo bestGeneric = getTimeZoneGenericNames().findBestMatch(text, startIdx, ALL_GENERIC_NAME_TYPES);
|
||||
|
||||
if (bestSpecific != null || bestGeneric != null) {
|
||||
if (bestGeneric == null ||
|
||||
(bestSpecific != null && bestSpecific.matchLength() > bestGeneric.matchLength())) {
|
||||
// the best specific match
|
||||
if (timeType != null) {
|
||||
timeType.value = getTimeType(bestSpecific.nameType());
|
||||
}
|
||||
pos.setIndex(startIdx + bestSpecific.matchLength());
|
||||
return TimeZone.getTimeZone(getTimeZoneID(bestSpecific.tzID(), bestSpecific.mzID()));
|
||||
} else if (bestGeneric != null){
|
||||
// the best generic match
|
||||
if (timeType != null) {
|
||||
timeType.value = bestGeneric.timeType();
|
||||
}
|
||||
pos.setIndex(startIdx + bestGeneric.matchLength());
|
||||
return TimeZone.getTimeZone(bestGeneric.tzID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos.setErrorIndex(startIdx);
|
||||
return null;
|
||||
}
|
||||
|
||||
public TimeZone parse(Style style, String text, ParsePosition pos, EnumSet<ParseOption> options, Output<TimeType> timeType) {
|
||||
if (timeType == null) {
|
||||
timeType = new Output<TimeType>(TimeType.UNKNOWN);
|
||||
@ -1189,13 +999,11 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
{
|
||||
// Specific styles
|
||||
EnumSet<NameType> nameTypes = null;
|
||||
switch (style) {
|
||||
case SPECIFIC_LONG:
|
||||
nameTypes = EnumSet.of(NameType.LONG_STANDARD, NameType.LONG_DAYLIGHT);
|
||||
break;
|
||||
case SPECIFIC_SHORT:
|
||||
if (style == Style.SPECIFIC_LONG) {
|
||||
nameTypes = EnumSet.of(NameType.LONG_STANDARD, NameType.LONG_DAYLIGHT);
|
||||
} else {
|
||||
assert style == Style.SPECIFIC_SHORT;
|
||||
nameTypes = EnumSet.of(NameType.SHORT_STANDARD, NameType.SHORT_DAYLIGHT);
|
||||
break;
|
||||
}
|
||||
Collection<MatchInfo> specificMatches = _tznames.find(text, startIdx, nameTypes);
|
||||
if (specificMatches != null) {
|
||||
@ -1600,13 +1408,12 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
throw new IllegalArgumentException("Bad localized GMT pattern: " + gmtPattern);
|
||||
}
|
||||
_gmtPattern = gmtPattern;
|
||||
_gmtPatternTokens = new String[2];
|
||||
_gmtPatternTokens[0] = unquote(gmtPattern.substring(0, idx));
|
||||
_gmtPatternTokens[1] = unquote(gmtPattern.substring(idx + 3));
|
||||
_gmtPatternPrefix = unquote(gmtPattern.substring(0, idx));
|
||||
_gmtPatternSuffix = unquote(gmtPattern.substring(idx + 3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unquotes the message format style pattern
|
||||
* Unquotes the message format style pattern.
|
||||
*
|
||||
* @param s the pattern
|
||||
* @return the unquoted pattern string
|
||||
@ -1760,8 +1567,8 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
}
|
||||
itemType = ch;
|
||||
itemLength = 1;
|
||||
checkBits.set(patFieldIdx);
|
||||
}
|
||||
checkBits.set(patFieldIdx);
|
||||
} else {
|
||||
// a string literal
|
||||
if (itemType != 0) {
|
||||
@ -1879,26 +1686,25 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
|
||||
do {
|
||||
// Prefix part
|
||||
int len = _gmtPatternTokens[0].length();
|
||||
if (len > 0 && !text.regionMatches(true, idx, _gmtPatternTokens[0], 0, len)) {
|
||||
int len = _gmtPatternPrefix.length();
|
||||
if (len > 0 && !text.regionMatches(true, idx, _gmtPatternPrefix, 0, len)) {
|
||||
// prefix match failed
|
||||
break;
|
||||
}
|
||||
idx += len;
|
||||
|
||||
// Offset part
|
||||
int[] tmpOffset = new int[1];
|
||||
int offsetLen = parseGMTOffset(text, idx, false, tmpOffset);
|
||||
if (offsetLen == 0) {
|
||||
int[] offsetLen = new int[1];
|
||||
offset = parseOffsetFields(text, idx, false, offsetLen);
|
||||
if (offsetLen[0] == 0) {
|
||||
// offset field match failed
|
||||
break;
|
||||
}
|
||||
offset = tmpOffset[0];
|
||||
idx += offsetLen;
|
||||
idx += offsetLen[0];
|
||||
|
||||
// Suffix part
|
||||
len = _gmtPatternTokens[1].length();
|
||||
if (len > 0 && !text.regionMatches(true, idx, _gmtPatternTokens[1], 0, len)) {
|
||||
len = _gmtPatternSuffix.length();
|
||||
if (len > 0 && !text.regionMatches(true, idx, _gmtPatternSuffix, 0, len)) {
|
||||
// no suffix match
|
||||
break;
|
||||
}
|
||||
@ -1910,17 +1716,19 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
if (parsed) {
|
||||
if (hasDigitOffset != null) {
|
||||
hasDigitOffset.value = true;
|
||||
} pos.setIndex(idx);
|
||||
}
|
||||
pos.setIndex(idx);
|
||||
return offset;
|
||||
}
|
||||
|
||||
// Try the default patterns
|
||||
int[] parsedLength = {0};
|
||||
offset = parseDefaultGMT(text, start, parsedLength);
|
||||
offset = parseOffsetDefaultLocalizedGMT(text, start, parsedLength);
|
||||
if (parsedLength[0] > 0) {
|
||||
if (hasDigitOffset != null) {
|
||||
hasDigitOffset.value = true;
|
||||
} pos.setIndex(start + parsedLength[0]);
|
||||
}
|
||||
pos.setIndex(start + parsedLength[0]);
|
||||
return offset;
|
||||
}
|
||||
|
||||
@ -1944,24 +1752,30 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses localized GMT string into offset.
|
||||
* Parses localized GMT offset fields into offset.
|
||||
*
|
||||
* @param text the input text
|
||||
* @param start the start index
|
||||
* @param minimumHourWidth the minimum hour width, 1 or 2.
|
||||
* @param offset the result offset set to offset[0]
|
||||
* @return parsed length
|
||||
* @param minimumHourWidth true if the parser allows hour field width to be 1
|
||||
* @param parsedLen the parsed length, or 0 on failure.
|
||||
* @return the parsed offset in milliseconds.
|
||||
*/
|
||||
private int parseGMTOffset(String text, int start, boolean minimumHourWidth, int[] offset) {
|
||||
int parsedLen = 0;
|
||||
int[] tmpParsedLen = new int[1];
|
||||
offset[0] = 0;
|
||||
private int parseOffsetFields(String text, int start, boolean minimumHourWidth, int[] parsedLen) {
|
||||
int outLen = 0;
|
||||
int[] tmpParsedLen = {0};
|
||||
int offset = 0;
|
||||
boolean sawVarHourAndAbuttingField = false;
|
||||
|
||||
if (parsedLen != null && parsedLen.length >= 1) {
|
||||
parsedLen[0] = 0;
|
||||
}
|
||||
|
||||
for (GMTOffsetPatternType gmtPatType : PARSE_GMT_OFFSET_TYPES) {
|
||||
int offsetH = 0, offsetM = 0, offsetS = 0;
|
||||
int idx = start;
|
||||
Object[] items = _gmtOffsetPatternItems[gmtPatType.ordinal()];
|
||||
assert items != null;
|
||||
|
||||
boolean failed = false;
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
if (items[i] instanceof String) {
|
||||
@ -1980,15 +1794,15 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
int minDigits = 1;
|
||||
int maxDigits = minimumHourWidth ? 1 : 2;
|
||||
if (!minimumHourWidth && !sawVarHourAndAbuttingField) {
|
||||
if (i + 1 < items.length && (items[i] instanceof GMTOffsetField)) {
|
||||
if (i + 1 < items.length && (items[i + 1] instanceof GMTOffsetField)) {
|
||||
sawVarHourAndAbuttingField = true;
|
||||
}
|
||||
}
|
||||
offsetH = parseOffsetDigits(text, idx, minDigits, maxDigits, 0, MAX_OFFSET_HOUR, tmpParsedLen);
|
||||
offsetH = parseOffsetFieldWithLocalizedDigits(text, idx, minDigits, maxDigits, 0, MAX_OFFSET_HOUR, tmpParsedLen);
|
||||
} else if (fieldType == 'm') {
|
||||
offsetM = parseOffsetDigits(text, idx, 2, 2, 0, MAX_OFFSET_MINUTE, tmpParsedLen);
|
||||
offsetM = parseOffsetFieldWithLocalizedDigits(text, idx, 2, 2, 0, MAX_OFFSET_MINUTE, tmpParsedLen);
|
||||
} else if (fieldType == 's') {
|
||||
offsetS = parseOffsetDigits(text, idx, 2, 2, 0, MAX_OFFSET_SECOND, tmpParsedLen);
|
||||
offsetS = parseOffsetFieldWithLocalizedDigits(text, idx, 2, 2, 0, MAX_OFFSET_SECOND, tmpParsedLen);
|
||||
}
|
||||
|
||||
if (tmpParsedLen[0] == 0) {
|
||||
@ -2000,13 +1814,13 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
}
|
||||
if (!failed) {
|
||||
int sign = gmtPatType.isPositive() ? 1 : -1;
|
||||
offset[0] = ((((offsetH * 60) + offsetM) * 60) + offsetS) * 1000 * sign;
|
||||
parsedLen = idx - start;
|
||||
offset = ((((offsetH * 60) + offsetM) * 60) + offsetS) * 1000 * sign;
|
||||
outLen = idx - start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (parsedLen == 0 && sawVarHourAndAbuttingField && !minimumHourWidth) {
|
||||
if (outLen == 0 && sawVarHourAndAbuttingField && !minimumHourWidth) {
|
||||
// When hour field is variable width and another non-literal pattern
|
||||
// field follows, the parse loop above might eat up the digit from
|
||||
// the abutting field. For example, with pattern "-Hmm" and input "-100",
|
||||
@ -2019,14 +1833,24 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
// the option is designed for supporting the case like "GMT+5". In this case,
|
||||
// we should get better result for parsing hour digits as much as possible.
|
||||
|
||||
return parseGMTOffset(text, start, true, offset);
|
||||
return parseOffsetFields(text, start, true, parsedLen);
|
||||
}
|
||||
|
||||
return parsedLen;
|
||||
if (parsedLen != null && parsedLen.length >= 1) {
|
||||
parsedLen[0] = outLen;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
private int parseDefaultGMT(String text, int start, int[] parsedLength) {
|
||||
int idx = start;;
|
||||
/**
|
||||
* Parses the input text using the default format patterns (e.g. "UTC{0}").
|
||||
* @param text the input text
|
||||
* @param start the start index
|
||||
* @param parsedLen the parsed length, or 0 on failure
|
||||
* @return the parsed offset in milliseconds.
|
||||
*/
|
||||
private int parseOffsetDefaultLocalizedGMT(String text, int start, int[] parsedLen) {
|
||||
int idx = start;
|
||||
int offset = 0;
|
||||
int parsed = 0;
|
||||
do {
|
||||
@ -2085,32 +1909,40 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
parsed = idx - start;
|
||||
} while (false);
|
||||
|
||||
parsedLength[0] = parsed;
|
||||
parsedLen[0] = parsed;
|
||||
return offset;
|
||||
}
|
||||
|
||||
private int parseDefaultOffsetFields(String text, int start, char separator, int[] parsedLength) {
|
||||
/**
|
||||
* Parses the input GMT offset fields with the default offset pattern.
|
||||
* @param text the input text
|
||||
* @param start the start index
|
||||
* @param separator the separator character, e.g. ':'
|
||||
* @param parsedLen the parsed length, or 0 on failure.
|
||||
* @return the parsed offset in milliseconds.
|
||||
*/
|
||||
private int parseDefaultOffsetFields(String text, int start, char separator, int[] parsedLen) {
|
||||
int max = text.length();
|
||||
int idx = start;
|
||||
int[] len = {0};
|
||||
int hour = 0, min = 0, sec = 0;
|
||||
|
||||
do {
|
||||
hour = parseOffsetDigits(text, idx, 1, 2, 0, MAX_OFFSET_HOUR, len);
|
||||
hour = parseOffsetFieldWithLocalizedDigits(text, idx, 1, 2, 0, MAX_OFFSET_HOUR, len);
|
||||
if (len[0] == 0) {
|
||||
break;
|
||||
}
|
||||
idx += len[0];
|
||||
|
||||
if (idx + 1 < max && text.charAt(idx) == separator) {
|
||||
min = parseOffsetDigits(text, idx + 1, 2, 2, 0, MAX_OFFSET_MINUTE, len);
|
||||
min = parseOffsetFieldWithLocalizedDigits(text, idx + 1, 2, 2, 0, MAX_OFFSET_MINUTE, len);
|
||||
if (len[0] == 0) {
|
||||
break;
|
||||
}
|
||||
idx += (1 + len[0]);
|
||||
|
||||
if (idx + 1 < max && text.charAt(idx) == separator) {
|
||||
sec = parseOffsetDigits(text, idx + 1, 2, 2, 0, MAX_OFFSET_SECOND, len);
|
||||
sec = parseOffsetFieldWithLocalizedDigits(text, idx + 1, 2, 2, 0, MAX_OFFSET_SECOND, len);
|
||||
if (len[0] == 0) {
|
||||
break;
|
||||
}
|
||||
@ -2120,15 +1952,22 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
} while (false);
|
||||
|
||||
if (idx == start) {
|
||||
parsedLength[0] = 0;
|
||||
parsedLen[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
parsedLength[0] = idx - start;
|
||||
parsedLen[0] = idx - start;
|
||||
return hour * MILLIS_PER_HOUR + min * MILLIS_PER_MINUTE + sec * MILLIS_PER_SECOND;
|
||||
}
|
||||
|
||||
private int parseAbuttingOffsetFields(String text, int start, int[] parsedLength) {
|
||||
/**
|
||||
* Parses abutting localized GMT offset fields (such as 0800) into offset.
|
||||
* @param text the input text
|
||||
* @param start the start index
|
||||
* @param parsedLen the parsed length, or 0 on failure
|
||||
* @return the parsed offset in milliseconds.
|
||||
*/
|
||||
private int parseAbuttingOffsetFields(String text, int start, int[] parsedLen) {
|
||||
final int MAXDIGITS = 6;
|
||||
int[] digits = new int[MAXDIGITS];
|
||||
int[] parsed = new int[MAXDIGITS]; // accumulative offsets
|
||||
@ -2138,7 +1977,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
int[] len = {0};
|
||||
int numDigits = 0;
|
||||
for (int i = 0; i < MAXDIGITS; i++) {
|
||||
digits[i] = parseSingleDigit(text, idx, len);
|
||||
digits[i] = parseSingleLocalizedDigit(text, idx, len);
|
||||
if (digits[i] < 0) {
|
||||
break;
|
||||
}
|
||||
@ -2148,7 +1987,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
}
|
||||
|
||||
if (numDigits == 0) {
|
||||
parsedLength[0] = 0;
|
||||
parsedLen[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2188,7 +2027,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
if (hour <= MAX_OFFSET_HOUR && min <= MAX_OFFSET_MINUTE && sec <= MAX_OFFSET_SECOND) {
|
||||
// found a valid combination
|
||||
offset = hour * MILLIS_PER_HOUR + min * MILLIS_PER_MINUTE + sec * MILLIS_PER_SECOND;
|
||||
parsedLength[0] = parsed[numDigits - 1];
|
||||
parsedLen[0] = parsed[numDigits - 1];
|
||||
break;
|
||||
}
|
||||
numDigits--;
|
||||
@ -2197,7 +2036,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an offset field number. This method will stop parsing when
|
||||
* Reads an offset field value. This method will stop parsing when
|
||||
* 1) number of digits reaches <code>maxDigits</code>
|
||||
* 2) just before already parsed number exceeds <code>maxVal</code>
|
||||
*
|
||||
@ -2207,20 +2046,20 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
* @param maxDigits the maximum number of digits
|
||||
* @param minVal the minimum value
|
||||
* @param maxVal the maximum value
|
||||
* @param parsedLength the actual parsed length is set to parsedLength[0], must not be null.
|
||||
* @param parsedLen the actual parsed length is set to parsedLen[0], must not be null.
|
||||
* @return the integer value parsed
|
||||
*/
|
||||
private int parseOffsetDigits(String text, int start, int minDigits, int maxDigits,
|
||||
int minVal, int maxVal, int[] parsedLength) {
|
||||
private int parseOffsetFieldWithLocalizedDigits(String text, int start, int minDigits, int maxDigits,
|
||||
int minVal, int maxVal, int[] parsedLen) {
|
||||
|
||||
parsedLength[0] = 0;
|
||||
parsedLen[0] = 0;
|
||||
|
||||
int decVal = 0;
|
||||
int numDigits = 0;
|
||||
int idx = start;
|
||||
int[] digitLen = {0};
|
||||
while (idx < text.length() && numDigits < maxDigits) {
|
||||
int digit = parseSingleDigit(text, idx, digitLen);
|
||||
int digit = parseSingleLocalizedDigit(text, idx, digitLen);
|
||||
if (digit < 0) {
|
||||
break;
|
||||
}
|
||||
@ -2238,18 +2077,27 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
decVal = -1;
|
||||
numDigits = 0;
|
||||
} else {
|
||||
parsedLength[0] = idx - start;
|
||||
parsedLen[0] = idx - start;
|
||||
}
|
||||
|
||||
|
||||
return decVal;
|
||||
}
|
||||
|
||||
private int parseSingleDigit(String text, int offset, int[] len) {
|
||||
/**
|
||||
* Reads a single decimal digit, either localized digits used by this object
|
||||
* or any Unicode numeric character.
|
||||
* @param text the text
|
||||
* @param start the start index
|
||||
* @param len the actual length read from the text
|
||||
* the start index is not a decimal number.
|
||||
* @return the integer value of the parsed digit, or -1 on failure.
|
||||
*/
|
||||
private int parseSingleLocalizedDigit(String text, int start, int[] len) {
|
||||
int digit = -1;
|
||||
len[0] = 0;
|
||||
if (offset < text.length()) {
|
||||
int cp = Character.codePointAt(text, offset);
|
||||
if (start < text.length()) {
|
||||
int cp = Character.codePointAt(text, start);
|
||||
|
||||
// First, try digits configured for this instance
|
||||
for (int i = 0; i < _gmtOffsetDigits.length; i++) {
|
||||
@ -2335,13 +2183,13 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
return 0;
|
||||
}
|
||||
ParsePosition posOffset = new ParsePosition(start + 1);
|
||||
int offset = parseAsciiDigitOffsetWithSeparators(text, posOffset, ':', OffsetFields.H, OffsetFields.HMS, false);
|
||||
if (posOffset.getErrorIndex() == -1 && !extendedOnly) {
|
||||
int offset = parseAsciiOffsetFields(text, posOffset, ':', OffsetFields.H, OffsetFields.HMS, false);
|
||||
if (posOffset.getErrorIndex() == -1 && !extendedOnly && (posOffset.getIndex() - start <= 3)) {
|
||||
// If the text is successfully parsed as extended format with the options above, it can be also parsed
|
||||
// as basic format. For example, "0230" can be parsed as offset 2:00 (only first digits are valid for
|
||||
// extended format), but it can be parsed as offset 2:30 with basic format. We use longer result.
|
||||
ParsePosition posBasic = new ParsePosition(start + 1);
|
||||
int tmpOffset = parseContiguousAsciiDigitOffset(text, posBasic, OffsetFields.H, OffsetFields.HMS, false);
|
||||
int tmpOffset = parseAbuttingAsciiOffsetFields(text, posBasic, OffsetFields.H, OffsetFields.HMS, false);
|
||||
if (posBasic.getErrorIndex() == -1 && posBasic.getIndex() > posOffset.getIndex()) {
|
||||
offset = tmpOffset;
|
||||
posOffset.setIndex(posBasic.getIndex());
|
||||
@ -2368,16 +2216,22 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
}
|
||||
|
||||
/**
|
||||
* Format offset using ASCII digits
|
||||
* Formats offset using ASCII digits
|
||||
* @param offset The offset
|
||||
* @param sep The field separator character or null if not required
|
||||
* @param minFields The minimum fields
|
||||
* @param maxFields The maximum fields
|
||||
* @return The offset string
|
||||
* @throws IllegalArgumentException if the specified offset is out of supported range
|
||||
* (-24 hours < offset < +24 hours).
|
||||
*/
|
||||
private static String formatOffsetWithASCIIDigits(int offset, Character sep, OffsetFields minFields, OffsetFields maxFields) {
|
||||
private static String formatOffsetWithAsciiDigits(int offset, Character sep, OffsetFields minFields, OffsetFields maxFields) {
|
||||
assert maxFields.ordinal() >= minFields.ordinal();
|
||||
|
||||
if (Math.abs(offset) >= MAX_OFFSET) {
|
||||
throw new IllegalArgumentException("Offset out of range :" + offset);
|
||||
}
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
char sign = '+';
|
||||
if (offset < 0) {
|
||||
@ -2393,9 +2247,9 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
offset = offset % MILLIS_PER_MINUTE;
|
||||
fields[2] = offset / MILLIS_PER_SECOND;
|
||||
|
||||
assert(fields[0] >= 0 && fields[0] < 100);
|
||||
assert(fields[1] >= 0 && fields[1] < 60);
|
||||
assert(fields[2] >= 0 && fields[2] < 60);
|
||||
assert(fields[0] >= 0 && fields[0] <= MAX_OFFSET_HOUR);
|
||||
assert(fields[1] >= 0 && fields[1] <= MAX_OFFSET_MINUTE);
|
||||
assert(fields[2] >= 0 && fields[2] <= MAX_OFFSET_SECOND);
|
||||
|
||||
int lastIdx = maxFields.ordinal();
|
||||
while (lastIdx > minFields.ordinal()) {
|
||||
@ -2418,7 +2272,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse offset represented by contiguous ASCII digits
|
||||
* Parses offset represented by contiguous ASCII digits
|
||||
* <p>
|
||||
* Note: This method expects the input position is already at the start of
|
||||
* ASCII digits and does not parse sign (+/-).
|
||||
@ -2427,14 +2281,14 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
* @param pos The parse position
|
||||
* @param minFields The minimum Fields to be parsed
|
||||
* @param maxFields The maximum Fields to be parsed
|
||||
* @param fixedHourWitdh true if hour field must be width of 2
|
||||
* @param fixedHourWidth true if hour field must be width of 2
|
||||
* @return Parsed offset, 0 or positive number.
|
||||
*/
|
||||
private int parseContiguousAsciiDigitOffset(String text, ParsePosition pos,
|
||||
OffsetFields minFields, OffsetFields maxFields, boolean fixedHourWitdh) {
|
||||
private static int parseAbuttingAsciiOffsetFields(String text, ParsePosition pos,
|
||||
OffsetFields minFields, OffsetFields maxFields, boolean fixedHourWidth) {
|
||||
int start = pos.getIndex();
|
||||
|
||||
int minDigits = 2 * (minFields.ordinal() + 1) - (fixedHourWitdh ? 0 : 1);
|
||||
int minDigits = 2 * (minFields.ordinal() + 1) - (fixedHourWidth ? 0 : 1);
|
||||
int maxDigits = 2 * (maxFields.ordinal() + 1);
|
||||
|
||||
int[] digits = new int[maxDigits];
|
||||
@ -2450,7 +2304,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (fixedHourWitdh && (numDigits % 2 != 0)) {
|
||||
if (fixedHourWidth && ((numDigits & 1) != 0)) {
|
||||
// Fixed digits, so the number of digits must be even number. Truncating.
|
||||
numDigits--;
|
||||
}
|
||||
@ -2497,7 +2351,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
}
|
||||
|
||||
// Truncating
|
||||
numDigits -= (fixedHourWitdh ? 2 : 1);
|
||||
numDigits -= (fixedHourWidth ? 2 : 1);
|
||||
hour = min = sec = 0;
|
||||
}
|
||||
|
||||
@ -2510,7 +2364,7 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse offset represented by ASCII digits and separators.
|
||||
* Parses offset represented by ASCII digits and separators.
|
||||
* <p>
|
||||
* Note: This method expects the input position is already at the start of
|
||||
* ASCII digits and does not parse sign (+/-).
|
||||
@ -2520,10 +2374,10 @@ public class TimeZoneFormat extends UFormat implements Freezable<TimeZoneFormat>
|
||||
* @param sep The separator character
|
||||
* @param minFields The minimum Fields to be parsed
|
||||
* @param maxFields The maximum Fields to be parsed
|
||||
* @param fixedHourWitdh true if hour field must be width of 2
|
||||
* @param fixedHourWidth true if hour field must be width of 2
|
||||
* @return Parsed offset, 0 or positive number.
|
||||
*/
|
||||
private int parseAsciiDigitOffsetWithSeparators(String text, ParsePosition pos,
|
||||
private static int parseAsciiOffsetFields(String text, ParsePosition pos,
|
||||
char sep, OffsetFields minFields, OffsetFields maxFields, boolean fixedHourWidth) {
|
||||
int start = pos.getIndex();
|
||||
int[] fieldVal = {0, 0, 0};
|
||||
|
Loading…
Reference in New Issue
Block a user