use of android.icu.text.TimeZoneNames.MatchInfo in project j2objc by google.
the class TimeZoneFormat method parseExemplarLocation.
/**
* Parse an exemplar location string.
* @param text the text contains an exemplar location string at the position.
* @param pos the position.
* @return The zone ID for the parsed exemplar location.
*/
private String parseExemplarLocation(String text, ParsePosition pos) {
int startIdx = pos.getIndex();
int parsedPos = -1;
String tzID = null;
EnumSet<NameType> nameTypes = EnumSet.of(NameType.EXEMPLAR_LOCATION);
Collection<MatchInfo> exemplarMatches = _tznames.find(text, startIdx, nameTypes);
if (exemplarMatches != null) {
MatchInfo exemplarMatch = null;
for (MatchInfo match : exemplarMatches) {
if (startIdx + match.matchLength() > parsedPos) {
exemplarMatch = match;
parsedPos = startIdx + match.matchLength();
}
}
if (exemplarMatch != null) {
tzID = getTimeZoneID(exemplarMatch.tzID(), exemplarMatch.mzID());
pos.setIndex(parsedPos);
}
}
if (tzID == null) {
pos.setErrorIndex(startIdx);
}
return tzID;
}
use of android.icu.text.TimeZoneNames.MatchInfo in project j2objc by google.
the class TimeZoneFormat method parse.
/**
* Returns a <code>TimeZone</code> by parsing the time zone string according to
* the parse position, the style and the parse options.
*
* @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.
* @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 #format(Style, TimeZone, long, Output)
*/
public TimeZone parse(Style style, String text, ParsePosition pos, EnumSet<ParseOption> options, Output<TimeType> timeType) {
if (timeType == null) {
timeType = new Output<TimeType>(TimeType.UNKNOWN);
} else {
timeType.value = TimeType.UNKNOWN;
}
int startIdx = pos.getIndex();
int maxPos = text.length();
int offset;
// Styles using localized GMT format as fallback
boolean fallbackLocalizedGMT = (style == Style.SPECIFIC_LONG || style == Style.GENERIC_LONG || style == Style.GENERIC_LOCATION);
boolean fallbackShortLocalizedGMT = (style == Style.SPECIFIC_SHORT || style == Style.GENERIC_SHORT);
// bit flags representing already evaluated styles
int evaluated = 0;
ParsePosition tmpPos = new ParsePosition(startIdx);
// stores successfully parsed offset for later use
int parsedOffset = UNKNOWN_OFFSET;
// stores successfully parsed offset position for later use
int parsedPos = -1;
// Try localized GMT format first if necessary
if (fallbackLocalizedGMT || fallbackShortLocalizedGMT) {
Output<Boolean> hasDigitOffset = new Output<Boolean>(false);
offset = parseOffsetLocalizedGMT(text, tmpPos, fallbackShortLocalizedGMT, hasDigitOffset);
if (tmpPos.getErrorIndex() == -1) {
// 2) The input text was not completely processed
if (tmpPos.getIndex() == maxPos || hasDigitOffset.value) {
pos.setIndex(tmpPos.getIndex());
return getTimeZoneForOffset(offset);
}
parsedOffset = offset;
parsedPos = tmpPos.getIndex();
}
// Note: For now, no distinction between long/short localized GMT format in the parser.
// This might be changed in future.
// evaluated |= (fallbackLocalizedGMT ? Style.LOCALIZED_GMT.flag : Style.LOCALIZED_GMT_SHORT.flag);
evaluated |= (Style.LOCALIZED_GMT.flag | Style.LOCALIZED_GMT_SHORT.flag);
}
boolean parseTZDBAbbrev = (options == null) ? getDefaultParseOptions().contains(ParseOption.TZ_DATABASE_ABBREVIATIONS) : options.contains(ParseOption.TZ_DATABASE_ABBREVIATIONS);
// Try the specified style
switch(style) {
case LOCALIZED_GMT:
{
tmpPos.setIndex(startIdx);
tmpPos.setErrorIndex(-1);
offset = parseOffsetLocalizedGMT(text, tmpPos);
if (tmpPos.getErrorIndex() == -1) {
pos.setIndex(tmpPos.getIndex());
return getTimeZoneForOffset(offset);
}
// Note: For now, no distinction between long/short localized GMT format in the parser.
// This might be changed in future.
evaluated |= Style.LOCALIZED_GMT_SHORT.flag;
break;
}
case LOCALIZED_GMT_SHORT:
{
tmpPos.setIndex(startIdx);
tmpPos.setErrorIndex(-1);
offset = parseOffsetShortLocalizedGMT(text, tmpPos);
if (tmpPos.getErrorIndex() == -1) {
pos.setIndex(tmpPos.getIndex());
return getTimeZoneForOffset(offset);
}
// Note: For now, no distinction between long/short localized GMT format in the parser.
// This might be changed in future.
evaluated |= Style.LOCALIZED_GMT.flag;
break;
}
case ISO_BASIC_SHORT:
case ISO_BASIC_FIXED:
case ISO_BASIC_FULL:
case ISO_EXTENDED_FIXED:
case ISO_EXTENDED_FULL:
{
tmpPos.setIndex(startIdx);
tmpPos.setErrorIndex(-1);
offset = parseOffsetISO8601(text, tmpPos);
if (tmpPos.getErrorIndex() == -1) {
pos.setIndex(tmpPos.getIndex());
return getTimeZoneForOffset(offset);
}
break;
}
case ISO_BASIC_LOCAL_SHORT:
case ISO_BASIC_LOCAL_FIXED:
case ISO_BASIC_LOCAL_FULL:
case ISO_EXTENDED_LOCAL_FIXED:
case ISO_EXTENDED_LOCAL_FULL:
{
tmpPos.setIndex(startIdx);
tmpPos.setErrorIndex(-1);
// Exclude the case of UTC Indicator "Z" here
Output<Boolean> hasDigitOffset = new Output<Boolean>(false);
offset = parseOffsetISO8601(text, tmpPos, false, hasDigitOffset);
if (tmpPos.getErrorIndex() == -1 && hasDigitOffset.value) {
pos.setIndex(tmpPos.getIndex());
return getTimeZoneForOffset(offset);
}
break;
}
case SPECIFIC_LONG:
case SPECIFIC_SHORT:
{
// Specific styles
EnumSet<NameType> nameTypes = null;
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);
}
Collection<MatchInfo> specificMatches = _tznames.find(text, startIdx, nameTypes);
if (specificMatches != null) {
MatchInfo specificMatch = null;
for (MatchInfo match : specificMatches) {
if (startIdx + match.matchLength() > parsedPos) {
specificMatch = match;
parsedPos = startIdx + match.matchLength();
}
}
if (specificMatch != null) {
timeType.value = getTimeType(specificMatch.nameType());
pos.setIndex(parsedPos);
return TimeZone.getTimeZone(getTimeZoneID(specificMatch.tzID(), specificMatch.mzID()));
}
}
if (parseTZDBAbbrev && style == Style.SPECIFIC_SHORT) {
assert nameTypes.contains(NameType.SHORT_STANDARD);
assert nameTypes.contains(NameType.SHORT_DAYLIGHT);
Collection<MatchInfo> tzdbNameMatches = getTZDBTimeZoneNames().find(text, startIdx, nameTypes);
if (tzdbNameMatches != null) {
MatchInfo tzdbNameMatch = null;
for (MatchInfo match : tzdbNameMatches) {
if (startIdx + match.matchLength() > parsedPos) {
tzdbNameMatch = match;
parsedPos = startIdx + match.matchLength();
}
}
if (tzdbNameMatch != null) {
timeType.value = getTimeType(tzdbNameMatch.nameType());
pos.setIndex(parsedPos);
return TimeZone.getTimeZone(getTimeZoneID(tzdbNameMatch.tzID(), tzdbNameMatch.mzID()));
}
}
}
break;
}
case GENERIC_LONG:
case GENERIC_SHORT:
case GENERIC_LOCATION:
{
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;
default:
// style cannot be other than above cases
assert false;
break;
}
GenericMatchInfo bestGeneric = getTimeZoneGenericNames().findBestMatch(text, startIdx, genericNameTypes);
if (bestGeneric != null && (startIdx + bestGeneric.matchLength() > parsedPos)) {
timeType.value = bestGeneric.timeType();
pos.setIndex(startIdx + bestGeneric.matchLength());
return TimeZone.getTimeZone(bestGeneric.tzID());
}
break;
}
case ZONE_ID:
{
tmpPos.setIndex(startIdx);
tmpPos.setErrorIndex(-1);
String id = parseZoneID(text, tmpPos);
if (tmpPos.getErrorIndex() == -1) {
pos.setIndex(tmpPos.getIndex());
return TimeZone.getTimeZone(id);
}
break;
}
case ZONE_ID_SHORT:
{
tmpPos.setIndex(startIdx);
tmpPos.setErrorIndex(-1);
String id = parseShortZoneID(text, tmpPos);
if (tmpPos.getErrorIndex() == -1) {
pos.setIndex(tmpPos.getIndex());
return TimeZone.getTimeZone(id);
}
break;
}
case EXEMPLAR_LOCATION:
{
tmpPos.setIndex(startIdx);
tmpPos.setErrorIndex(-1);
String id = parseExemplarLocation(text, tmpPos);
if (tmpPos.getErrorIndex() == -1) {
pos.setIndex(tmpPos.getIndex());
return TimeZone.getTimeZone(id);
}
break;
}
}
evaluated |= style.flag;
if (parsedPos > startIdx) {
// GMT format.
assert parsedOffset != UNKNOWN_OFFSET;
pos.setIndex(parsedPos);
return getTimeZoneForOffset(parsedOffset);
}
// Failed to parse the input text as the time zone format in the specified style.
// Check the longest match among other styles below.
// stores successfully parsed zone ID for later use
String parsedID = null;
// stores successfully parsed time type for later use
TimeType parsedTimeType = TimeType.UNKNOWN;
assert parsedPos < 0;
assert parsedOffset == UNKNOWN_OFFSET;
// ISO 8601
if (parsedPos < maxPos && ((evaluated & ISO_Z_STYLE_FLAG) == 0 || (evaluated & ISO_LOCAL_STYLE_FLAG) == 0)) {
tmpPos.setIndex(startIdx);
tmpPos.setErrorIndex(-1);
Output<Boolean> hasDigitOffset = new Output<Boolean>(false);
offset = parseOffsetISO8601(text, tmpPos, false, hasDigitOffset);
if (tmpPos.getErrorIndex() == -1) {
if (tmpPos.getIndex() == maxPos || hasDigitOffset.value) {
pos.setIndex(tmpPos.getIndex());
return getTimeZoneForOffset(offset);
}
// may collide with other names. In this case, we need to evaluate other names.
if (parsedPos < tmpPos.getIndex()) {
parsedOffset = offset;
parsedID = null;
parsedTimeType = TimeType.UNKNOWN;
parsedPos = tmpPos.getIndex();
// only when "Z" is used
assert parsedPos == startIdx + 1;
}
}
}
// Localized GMT format
if (parsedPos < maxPos && (evaluated & Style.LOCALIZED_GMT.flag) == 0) {
tmpPos.setIndex(startIdx);
tmpPos.setErrorIndex(-1);
Output<Boolean> hasDigitOffset = new Output<Boolean>(false);
offset = parseOffsetLocalizedGMT(text, tmpPos, false, hasDigitOffset);
if (tmpPos.getErrorIndex() == -1) {
if (tmpPos.getIndex() == maxPos || hasDigitOffset.value) {
pos.setIndex(tmpPos.getIndex());
return getTimeZoneForOffset(offset);
}
// Evaluate other names - see the comment earlier in this method.
if (parsedPos < tmpPos.getIndex()) {
parsedOffset = offset;
parsedID = null;
parsedTimeType = TimeType.UNKNOWN;
parsedPos = tmpPos.getIndex();
}
}
}
if (parsedPos < maxPos && (evaluated & Style.LOCALIZED_GMT_SHORT.flag) == 0) {
tmpPos.setIndex(startIdx);
tmpPos.setErrorIndex(-1);
Output<Boolean> hasDigitOffset = new Output<Boolean>(false);
offset = parseOffsetLocalizedGMT(text, tmpPos, true, hasDigitOffset);
if (tmpPos.getErrorIndex() == -1) {
if (tmpPos.getIndex() == maxPos || hasDigitOffset.value) {
pos.setIndex(tmpPos.getIndex());
return getTimeZoneForOffset(offset);
}
// Evaluate other names - see the comment earlier in this method.
if (parsedPos < tmpPos.getIndex()) {
parsedOffset = offset;
parsedID = null;
parsedTimeType = TimeType.UNKNOWN;
parsedPos = tmpPos.getIndex();
}
}
}
// When ParseOption.ALL_STYLES is available, we also try to look all possible display names and IDs.
// 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.
// Note: Adding all possible names into the trie used by the implementation is quite heavy operation,
// which we want to avoid normally (note that we cache the trie, so this is applicable to the
// first time only as long as the cache does not expire).
boolean parseAllStyles = (options == null) ? getDefaultParseOptions().contains(ParseOption.ALL_STYLES) : options.contains(ParseOption.ALL_STYLES);
if (parseAllStyles) {
// Try all specific names and exemplar location names
if (parsedPos < maxPos) {
Collection<MatchInfo> specificMatches = _tznames.find(text, startIdx, ALL_SIMPLE_NAME_TYPES);
MatchInfo specificMatch = null;
int matchPos = -1;
if (specificMatches != null) {
for (MatchInfo match : specificMatches) {
if (startIdx + match.matchLength() > matchPos) {
specificMatch = match;
matchPos = startIdx + match.matchLength();
}
}
}
if (parsedPos < matchPos) {
parsedPos = matchPos;
parsedID = getTimeZoneID(specificMatch.tzID(), specificMatch.mzID());
parsedTimeType = getTimeType(specificMatch.nameType());
parsedOffset = UNKNOWN_OFFSET;
}
}
if (parseTZDBAbbrev && parsedPos < maxPos && (evaluated & Style.SPECIFIC_SHORT.flag) == 0) {
Collection<MatchInfo> tzdbNameMatches = getTZDBTimeZoneNames().find(text, startIdx, ALL_SIMPLE_NAME_TYPES);
MatchInfo tzdbNameMatch = null;
int matchPos = -1;
if (tzdbNameMatches != null) {
for (MatchInfo match : tzdbNameMatches) {
if (startIdx + match.matchLength() > matchPos) {
tzdbNameMatch = match;
matchPos = startIdx + match.matchLength();
}
}
if (parsedPos < matchPos) {
parsedPos = matchPos;
parsedID = getTimeZoneID(tzdbNameMatch.tzID(), tzdbNameMatch.mzID());
parsedTimeType = getTimeType(tzdbNameMatch.nameType());
parsedOffset = UNKNOWN_OFFSET;
}
}
}
// Try generic names
if (parsedPos < maxPos) {
GenericMatchInfo genericMatch = getTimeZoneGenericNames().findBestMatch(text, startIdx, ALL_GENERIC_NAME_TYPES);
if (genericMatch != null && parsedPos < startIdx + genericMatch.matchLength()) {
parsedPos = startIdx + genericMatch.matchLength();
parsedID = genericMatch.tzID();
parsedTimeType = genericMatch.timeType();
parsedOffset = UNKNOWN_OFFSET;
}
}
// Try time zone ID
if (parsedPos < maxPos && (evaluated & Style.ZONE_ID.flag) == 0) {
tmpPos.setIndex(startIdx);
tmpPos.setErrorIndex(-1);
String id = parseZoneID(text, tmpPos);
if (tmpPos.getErrorIndex() == -1 && parsedPos < tmpPos.getIndex()) {
parsedPos = tmpPos.getIndex();
parsedID = id;
parsedTimeType = TimeType.UNKNOWN;
parsedOffset = UNKNOWN_OFFSET;
}
}
// Try short time zone ID
if (parsedPos < maxPos && (evaluated & Style.ZONE_ID_SHORT.flag) == 0) {
tmpPos.setIndex(startIdx);
tmpPos.setErrorIndex(-1);
String id = parseShortZoneID(text, tmpPos);
if (tmpPos.getErrorIndex() == -1 && parsedPos < tmpPos.getIndex()) {
parsedPos = tmpPos.getIndex();
parsedID = id;
parsedTimeType = TimeType.UNKNOWN;
parsedOffset = UNKNOWN_OFFSET;
}
}
}
if (parsedPos > startIdx) {
// Parsed successfully
TimeZone parsedTZ = null;
if (parsedID != null) {
parsedTZ = TimeZone.getTimeZone(parsedID);
} else {
assert parsedOffset != UNKNOWN_OFFSET;
parsedTZ = getTimeZoneForOffset(parsedOffset);
}
timeType.value = parsedTimeType;
pos.setIndex(parsedPos);
return parsedTZ;
}
pos.setErrorIndex(startIdx);
return null;
}
use of android.icu.text.TimeZoneNames.MatchInfo in project j2objc by google.
the class TimeZoneGenericNames method find.
/**
* Returns a collection of time zone display name matches for the specified types in the
* given text at the given offset.
* @param text the text
* @param start the start offset in the text
* @param genericTypes the set of name types.
* @return A collection of match info.
*/
public Collection<GenericMatchInfo> find(String text, int start, EnumSet<GenericNameType> genericTypes) {
if (text == null || text.length() == 0 || start < 0 || start >= text.length()) {
throw new IllegalArgumentException("bad input text or range");
}
// Find matches in the local trie
Collection<GenericMatchInfo> results = findLocal(text, start, genericTypes);
// Also find matches in the TimeZoneNames
Collection<MatchInfo> tznamesMatches = findTimeZoneNames(text, start, genericTypes);
if (tznamesMatches != null) {
// transform matches and append them to local matches
for (MatchInfo match : tznamesMatches) {
if (results == null) {
results = new LinkedList<GenericMatchInfo>();
}
results.add(createGenericMatchInfo(match));
}
}
return results;
}
use of android.icu.text.TimeZoneNames.MatchInfo in project j2objc by google.
the class TimeZoneGenericNames method findBestMatch.
/**
* Returns the best match of time zone display name for the specified types in the
* given text at the given offset.
* @param text the text
* @param start the start offset in the text
* @param genericTypes the set of name types.
* @return the best matching name info.
*/
public GenericMatchInfo findBestMatch(String text, int start, EnumSet<GenericNameType> genericTypes) {
if (text == null || text.length() == 0 || start < 0 || start >= text.length()) {
throw new IllegalArgumentException("bad input text or range");
}
GenericMatchInfo bestMatch = null;
// Find matches in the TimeZoneNames first
Collection<MatchInfo> tznamesMatches = findTimeZoneNames(text, start, genericTypes);
if (tznamesMatches != null) {
MatchInfo longestMatch = null;
for (MatchInfo match : tznamesMatches) {
if (longestMatch == null || match.matchLength() > longestMatch.matchLength()) {
longestMatch = match;
}
}
if (longestMatch != null) {
bestMatch = createGenericMatchInfo(longestMatch);
if (bestMatch.matchLength() == (text.length() - start)) {
// below back to the original one above. -Yoshito (2011-09-14)
if (bestMatch.timeType != TimeType.STANDARD) {
return bestMatch;
}
}
}
}
// Find matches in the local trie
Collection<GenericMatchInfo> localMatches = findLocal(text, start, genericTypes);
if (localMatches != null) {
for (GenericMatchInfo match : localMatches) {
// if (bestMatch == null || match.matchLength() > bestMatch.matchLength()) {
if (bestMatch == null || match.matchLength() >= bestMatch.matchLength()) {
bestMatch = match;
}
}
}
return bestMatch;
}
Aggregations