icu4j/main/classes/core/.settings/org.eclipse.core.resources.prefs -text
icu4j/main/classes/core/.settings/org.eclipse.jdt.core.prefs -text
icu4j/main/classes/core/manifest.stub -text
+icu4j/main/classes/core/src/com/ibm/icu/impl/TZDBTimeZoneNames.java -text
icu4j/main/classes/currdata/.externalToolBuilders/copy-data-currdata.launch -text
icu4j/main/classes/currdata/.settings/org.eclipse.core.resources.prefs -text
icu4j/main/classes/currdata/.settings/org.eclipse.jdt.core.prefs -text
--- /dev/null
+/*
+ *******************************************************************************
+ * Copyright (C) 2014, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ *******************************************************************************
+ */
+package com.ibm.icu.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.MissingResourceException;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.ibm.icu.impl.TextTrieMap.ResultHandler;
+import com.ibm.icu.text.TimeZoneNames;
+import com.ibm.icu.util.ULocale;
+import com.ibm.icu.util.UResourceBundle;
+
+/**
+ * Yet another TimeZoneNames implementation based on the tz database.
+ * This implementation contains only tz abbreviations (short standard
+ * and daylight names) for each metazone.
+ *
+ * The data file $ICU4C_ROOT/source/data/zone/tzdbNames.txt contains
+ * the metazone - abbreviations mapping data (manually edited).
+ *
+ * Note: The abbreviations in the tz database are not necessarily
+ * unique. For example, parsing abbreviation "IST" is ambiguous
+ * (can be parsed as India Standard Time or Israel Standard Time).
+ * The data file (tzdbNames.txt) contains regional mapping, and
+ * the locale in the constructor is used as a hint for resolving
+ * these ambiguous names.
+ */
+public class TZDBTimeZoneNames extends TimeZoneNames {
+ private static final long serialVersionUID = 1L;
+
+ private static final ConcurrentHashMap<String, TZDBNames> TZDB_NAMES_MAP =
+ new ConcurrentHashMap<String, TZDBNames>();
+
+ private static volatile TextTrieMap<TZDBNameInfo> TZDB_NAMES_TRIE = null;
+
+ private static final ICUResourceBundle ZONESTRINGS;
+ static {
+ UResourceBundle bundle = ICUResourceBundle
+ .getBundleInstance(ICUResourceBundle.ICU_ZONE_BASE_NAME, "tzdbNames");
+ ZONESTRINGS = (ICUResourceBundle)bundle.get("zoneStrings");
+ }
+
+ private ULocale _locale;
+ private transient volatile String _region;
+
+ public TZDBTimeZoneNames(ULocale loc) {
+ _locale = loc;
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.text.TimeZoneNames#getAvailableMetaZoneIDs()
+ */
+ @Override
+ public Set<String> getAvailableMetaZoneIDs() {
+ return TimeZoneNamesImpl._getAvailableMetaZoneIDs();
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.text.TimeZoneNames#getAvailableMetaZoneIDs(java.lang.String)
+ */
+ @Override
+ public Set<String> getAvailableMetaZoneIDs(String tzID) {
+ return TimeZoneNamesImpl._getAvailableMetaZoneIDs(tzID);
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.text.TimeZoneNames#getMetaZoneID(java.lang.String, long)
+ */
+ @Override
+ public String getMetaZoneID(String tzID, long date) {
+ return TimeZoneNamesImpl._getMetaZoneID(tzID, date);
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.text.TimeZoneNames#getReferenceZoneID(java.lang.String, java.lang.String)
+ */
+ @Override
+ public String getReferenceZoneID(String mzID, String region) {
+ return TimeZoneNamesImpl._getReferenceZoneID(mzID, region);
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.text.TimeZoneNames#getMetaZoneDisplayName(java.lang.String,
+ * com.ibm.icu.text.TimeZoneNames.NameType)
+ */
+ @Override
+ public String getMetaZoneDisplayName(String mzID, NameType type) {
+ if (mzID == null || mzID.length() == 0 ||
+ (type != NameType.SHORT_STANDARD && type != NameType.SHORT_DAYLIGHT)) {
+ return null;
+ }
+ return getMetaZoneNames(mzID).getName(type);
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.text.TimeZoneNames#getTimeZoneDisplayName(java.lang.String,
+ * com.ibm.icu.text.TimeZoneNames.NameType)
+ */
+ @Override
+ public String getTimeZoneDisplayName(String tzID, NameType type) {
+ // No abbreviations associated a zone directly for now.
+ return null;
+ }
+
+// /* (non-Javadoc)
+// * @see com.ibm.icu.text.TimeZoneNames#getExemplarLocationName(java.lang.String)
+// */
+// public String getExemplarLocationName(String tzID) {
+// return super.getExemplarLocationName(tzID);
+// }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.text.TimeZoneNames#find(java.lang.CharSequence, int, java.util.EnumSet)
+ */
+ @Override
+ public Collection<MatchInfo> find(CharSequence text, int start, EnumSet<NameType> nameTypes) {
+ if (text == null || text.length() == 0 || start < 0 || start >= text.length()) {
+ throw new IllegalArgumentException("bad input text or range");
+ }
+
+ prepareFind();
+ TZDBNameSearchHandler handler = new TZDBNameSearchHandler(nameTypes, getTargetRegion());
+ TZDB_NAMES_TRIE.find(text, start, handler);
+ return handler.getMatches();
+ }
+
+ private static class TZDBNames {
+ public static final TZDBNames EMPTY_TZDBNAMES = new TZDBNames(null, null);
+
+ private String[] _names;
+ private String[] _parseRegions;
+ private static final String[] KEYS = {"ss", "sd"};
+
+ private TZDBNames(String[] names, String[] parseRegions) {
+ _names = names;
+ _parseRegions = parseRegions;
+ }
+
+ static TZDBNames getInstance(ICUResourceBundle zoneStrings, String key) {
+ if (zoneStrings == null || key == null || key.length() == 0) {
+ return EMPTY_TZDBNAMES;
+ }
+
+ ICUResourceBundle table = null;
+ try {
+ table = (ICUResourceBundle)zoneStrings.get(key);
+ } catch (MissingResourceException e) {
+ return EMPTY_TZDBNAMES;
+ }
+
+ boolean isEmpty = true;
+ String[] names = new String[KEYS.length];
+ for (int i = 0; i < names.length; i++) {
+ try {
+ names[i] = table.getString(KEYS[i]);
+ isEmpty = false;
+ } catch (MissingResourceException e) {
+ names[i] = null;
+ }
+ }
+
+ if (isEmpty) {
+ return EMPTY_TZDBNAMES;
+ }
+
+ String[] parseRegions = null;
+ try {
+ ICUResourceBundle regionsRes = (ICUResourceBundle)table.get("parseRegions");
+ if (regionsRes.getType() == UResourceBundle.STRING) {
+ parseRegions = new String[1];
+ parseRegions[0] = regionsRes.getString();
+ } else if (regionsRes.getType() == UResourceBundle.ARRAY) {
+ parseRegions = regionsRes.getStringArray();
+ }
+ } catch (MissingResourceException e) {
+ // fall through
+ }
+
+ return new TZDBNames(names, parseRegions);
+ }
+
+ String getName(NameType type) {
+ if (_names == null) {
+ return null;
+ }
+ String name = null;
+ switch (type) {
+ case SHORT_STANDARD:
+ name = _names[0];
+ break;
+ case SHORT_DAYLIGHT:
+ name = _names[1];
+ break;
+ }
+
+ return name;
+ }
+
+ String[] getParseRegions() {
+ return _parseRegions;
+ }
+ }
+
+ private static class TZDBNameInfo {
+ String mzID;
+ NameType type;
+ boolean ambiguousType;
+ String[] parseRegions;
+ }
+
+ private static class TZDBNameSearchHandler implements ResultHandler<TZDBNameInfo> {
+ private EnumSet<NameType> _nameTypes;
+ private Collection<MatchInfo> _matches;
+ private String _region;
+
+ TZDBNameSearchHandler(EnumSet<NameType> nameTypes, String region) {
+ _nameTypes = nameTypes;
+ assert region != null;
+ _region = region;
+ }
+
+ /* (non-Javadoc)
+ * @see com.ibm.icu.impl.TextTrieMap.ResultHandler#handlePrefixMatch(int,
+ * java.util.Iterator)
+ */
+ public boolean handlePrefixMatch(int matchLength, Iterator<TZDBNameInfo> values) {
+ TZDBNameInfo match = null;
+ TZDBNameInfo defaultRegionMatch = null;
+
+ while (values.hasNext()) {
+ TZDBNameInfo ninfo = values.next();
+
+ if (_nameTypes != null && !_nameTypes.contains(ninfo.type)) {
+ continue;
+ }
+
+ // Some tz database abbreviations are ambiguous. For example,
+ // CST means either Central Standard Time or China Standard Time.
+ // Unlike CLDR time zone display names, this implementation
+ // does not use unique names. And TimeZoneFormat does not expect
+ // multiple results returned for the same time zone type.
+ // For this reason, this implementation resolve one among same
+ // zone type with a same name at this level.
+ if (ninfo.parseRegions == null) {
+ // parseRegions == null means this is the default metazone
+ // mapping for the abbreviation.
+ if (defaultRegionMatch == null) {
+ match = defaultRegionMatch = ninfo;
+ }
+ } else {
+ boolean matchRegion = false;
+ // non-default metazone mapping for an abbreviation
+ // comes with applicable regions. For example, the default
+ // metazone mapping for "CST" is America_Central,
+ // but if region is one of CN/MO/TW, "CST" is parsed
+ // as metazone China (China Standard Time).
+ for (String region : ninfo.parseRegions) {
+ if (_region.equals(region)) {
+ match = ninfo;
+ matchRegion = true;
+ break;
+ }
+ }
+ if (matchRegion) {
+ break;
+ }
+ if (match == null) {
+ match = ninfo;
+ }
+ }
+ }
+
+ if (match != null) {
+ NameType ntype = match.type;
+ // Note: Workaround for duplicated standard/daylight names
+ // The tz database contains a few zones sharing a
+ // same name for both standard time and daylight saving
+ // time. For example, Australia/Sydney observes DST,
+ // but "EST" is used for both standard and daylight.
+ // When both SHORT_STANDARD and SHORT_DAYLIGHT are included
+ // in the find operation, we cannot tell which one was
+ // actually matched.
+ // TimeZoneFormat#parse returns a matched name type (standard
+ // or daylight) and DateFormat implementation uses the info to
+ // to adjust actual time. To avoid false type information,
+ // this implementation replaces the name type with SHORT_GENERIC.
+ if (match.ambiguousType
+ && (ntype == NameType.SHORT_STANDARD || ntype == NameType.SHORT_DAYLIGHT)
+ && _nameTypes.contains(NameType.SHORT_STANDARD)
+ && _nameTypes.contains(NameType.SHORT_DAYLIGHT)) {
+ ntype = NameType.SHORT_GENERIC;
+ }
+ MatchInfo minfo = new MatchInfo(ntype, null, match.mzID, matchLength);
+ if (_matches == null) {
+ _matches = new LinkedList<MatchInfo>();
+ }
+ _matches.add(minfo);
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the match results
+ * @return the match results
+ */
+ public Collection<MatchInfo> getMatches() {
+ if (_matches == null) {
+ return Collections.emptyList();
+ }
+ return _matches;
+ }
+ }
+
+ private static TZDBNames getMetaZoneNames(String mzID) {
+ TZDBNames names = TZDB_NAMES_MAP.get(mzID);
+ if (names == null) {
+ names = TZDBNames.getInstance(ZONESTRINGS, "meta:" + mzID);
+ mzID = mzID.intern();
+ TZDBNames tmpNames = TZDB_NAMES_MAP.putIfAbsent(mzID, names);
+ names = (tmpNames == null) ? names : tmpNames;
+ }
+ return names;
+ }
+
+ private static void prepareFind() {
+ if (TZDB_NAMES_TRIE == null) {
+ synchronized(TZDBTimeZoneNames.class) {
+ if (TZDB_NAMES_TRIE == null) {
+ // loading all names into trie
+ TZDB_NAMES_TRIE = new TextTrieMap<TZDBNameInfo>(true);
+ Set<String> mzIDs = TimeZoneNamesImpl._getAvailableMetaZoneIDs();
+ for (String mzID : mzIDs) {
+ TZDBNames names = getMetaZoneNames(mzID);
+ String std = names.getName(NameType.SHORT_STANDARD);
+ String dst = names.getName(NameType.SHORT_DAYLIGHT);
+ if (std == null && dst == null) {
+ continue;
+ }
+ String[] parseRegions = names.getParseRegions();
+ mzID = mzID.intern();
+
+ // The tz database contains a few zones sharing a
+ // same name for both standard time and daylight saving
+ // time. For example, Australia/Sydney observes DST,
+ // but "EST" is used for both standard and daylight.
+ // we need to store the information for later processing.
+ boolean ambiguousType = (std != null && dst != null && std.equals(dst));
+
+ if (std != null) {
+ TZDBNameInfo stdInf = new TZDBNameInfo();
+ stdInf.mzID = mzID;
+ stdInf.type = NameType.SHORT_STANDARD;
+ stdInf.ambiguousType = ambiguousType;
+ stdInf.parseRegions = parseRegions;
+ TZDB_NAMES_TRIE.put(std, stdInf);
+ }
+ if (dst != null) {
+ TZDBNameInfo dstInf = new TZDBNameInfo();
+ dstInf.mzID = mzID;
+ dstInf.type = NameType.SHORT_DAYLIGHT;
+ dstInf.ambiguousType = ambiguousType;
+ dstInf.parseRegions = parseRegions;
+ TZDB_NAMES_TRIE.put(dst, dstInf);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private String getTargetRegion() {
+ if (_region == null) {
+ String region = _locale.getCountry();
+ if (region.length() == 0) {
+ ULocale tmp = ULocale.addLikelySubtags(_locale);
+ region = tmp.getCountry();
+ if (region.length() == 0) {
+ region = "001";
+ }
+ }
+ _region = region;
+ }
+ return _region;
+ }
+}
/*
*******************************************************************************
- * Copyright (C) 2011-2013, International Business Machines Corporation and *
+ * Copyright (C) 2011-2014, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
private static final String ZONE_STRINGS_BUNDLE = "zoneStrings";
private static final String MZ_PREFIX = "meta:";
- private static Set<String> METAZONE_IDS;
+ private static volatile Set<String> METAZONE_IDS;
private static final TZ2MZsCache TZ_TO_MZS_CACHE = new TZ2MZsCache();
private static final MZ2TZsCache MZ_TO_TZS_CACHE = new MZ2TZsCache();
* @see com.ibm.icu.text.TimeZoneNames#getAvailableMetaZoneIDs()
*/
@Override
- public synchronized Set<String> getAvailableMetaZoneIDs() {
+ public Set<String> getAvailableMetaZoneIDs() {
+ return _getAvailableMetaZoneIDs();
+ }
+
+ static Set<String> _getAvailableMetaZoneIDs() {
if (METAZONE_IDS == null) {
- UResourceBundle bundle = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "metaZones");
- UResourceBundle mapTimezones = bundle.get("mapTimezones");
- Set<String> keys = mapTimezones.keySet();
- METAZONE_IDS = Collections.unmodifiableSet(keys);
+ synchronized (TimeZoneNamesImpl.class) {
+ if (METAZONE_IDS == null) {
+ UResourceBundle bundle = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "metaZones");
+ UResourceBundle mapTimezones = bundle.get("mapTimezones");
+ Set<String> keys = mapTimezones.keySet();
+ METAZONE_IDS = Collections.unmodifiableSet(keys);
+ }
+ }
}
return METAZONE_IDS;
}
*/
@Override
public Set<String> getAvailableMetaZoneIDs(String tzID) {
+ return _getAvailableMetaZoneIDs(tzID);
+ }
+
+ static Set<String> _getAvailableMetaZoneIDs(String tzID) {
if (tzID == null || tzID.length() == 0) {
return Collections.emptySet();
}
*/
@Override
public String getMetaZoneID(String tzID, long date) {
+ return _getMetaZoneID(tzID, date);
+ }
+
+ static String _getMetaZoneID(String tzID, long date) {
if (tzID == null || tzID.length() == 0) {
return null;
}
*/
@Override
public String getReferenceZoneID(String mzID, String region) {
+ return _getReferenceZoneID(mzID, region);
+ }
+
+ static String _getReferenceZoneID(String mzID, String region) {
if (mzID == null || mzID.length() == 0) {
return null;
}
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SoftCache;
+import com.ibm.icu.impl.TZDBTimeZoneNames;
import com.ibm.icu.impl.TextTrieMap;
import com.ibm.icu.impl.TimeZoneGenericNames;
import com.ibm.icu.impl.TimeZoneGenericNames.GenericMatchInfo;
* by other styles.
* @stable ICU 49
*/
- ALL_STYLES;
- }
+ ALL_STYLES,
+ /**
+ * When parsing a time zone display name in {@link Style#SPECIFIC_SHORT},
+ * look for the IANA tz database compatible zone abbreviations in addition
+ * to the localized names coming from the {@link TimeZoneNames} currently
+ * used by the {@link TimeZoneFormat}.
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
+ */
+ TZ_DATABASE_ABBREVIATIONS;
+ }
/*
* fields to be serialized
private String[] _gmtOffsetDigits;
private String _gmtZeroFormat;
private boolean _parseAllStyles;
+ private boolean _parseTZDBNames;
/*
* Transient fields
private transient boolean _frozen;
+ private transient volatile TimeZoneNames _tzdbNames;
/*
* Static final fields
return _gnames;
}
+ /**
+ * Private method returning the instance of TZDBTimeZoneNames.
+ * The instance if used only for parsing when {@link ParseOption#TZ_DATABASE_ABBREVIATIONS}
+ * is enabled.
+ * @return an instance of TZDBTimeZoneNames.
+ */
+ private TimeZoneNames getTZDBTimeZoneNames() {
+ if (_tzdbNames == null) {
+ synchronized(this) {
+ if (_tzdbNames == null) {
+ _tzdbNames = new TZDBTimeZoneNames(_locale);
+ }
+ }
+ }
+ return _tzdbNames;
+ }
+
/**
* Sets the time zone display name data to this instance.
*
* @stable ICU 49
*/
public TimeZoneFormat setDefaultParseOptions(EnumSet<ParseOption> options) {
- // Currently, only ALL_STYLES is supported
_parseAllStyles = options.contains(ParseOption.ALL_STYLES);
+ _parseTZDBNames = options.contains(ParseOption.TZ_DATABASE_ABBREVIATIONS);
return this;
}
* @stable ICU 49
*/
public EnumSet<ParseOption> getDefaultParseOptions() {
- if (_parseAllStyles) {
+ if (_parseAllStyles && _parseTZDBNames) {
+ return EnumSet.of(ParseOption.ALL_STYLES, ParseOption.TZ_DATABASE_ABBREVIATIONS);
+ } else if (_parseAllStyles) {
return EnumSet.of(ParseOption.ALL_STYLES);
+ } else if (_parseTZDBNames) {
+ return EnumSet.of(ParseOption.TZ_DATABASE_ABBREVIATIONS);
}
return EnumSet.noneOf(ParseOption.class);
}
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:
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:
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) {
import com.ibm.icu.impl.ICUConfig;
import com.ibm.icu.impl.SoftCache;
+import com.ibm.icu.impl.TZDBTimeZoneNames;
import com.ibm.icu.impl.TimeZoneNamesImpl;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.ULocale;
}
/**
- * Returns an instance of <code>TimeZoneDisplayNames</code> for the specified locale.
+ * Returns an instance of <code>TimeZoneNames</code> for the specified locale.
*
* @param locale
* The locale.
- * @return An instance of <code>TimeZoneDisplayNames</code>
+ * @return An instance of <code>TimeZoneNames</code>
* @stable ICU 49
*/
public static TimeZoneNames getInstance(ULocale locale) {
}
/**
- * Returns an instance of <code>TimeZoneDisplayNames</code> for the specified JDK locale.
+ * Returns an instance of <code>TimeZoneNames</code> for the specified JDK locale.
*
* @param locale
* The JDK locale.
return getInstance(ULocale.forLocale(locale));
}
+ /**
+ * Returns an instance of <code>TimeZoneNames</code> containing only short specific
+ * zone names ({@link NameType#SHORT_STANDARD} and {@link NameType#SHORT_DAYLIGHT}),
+ * compatible with the IANA tz database's zone abbreviations (not localized).
+ * <br>
+ * Note: The input locale is used for resolving ambiguous names (e.g. "IST" is parsed
+ * as Israel Standard Time for Israel, while it is parsed as India Standard Time for
+ * all other regions). The zone names returned by this instance are not localized.
+ *
+ * @draft ICU 54
+ * @provisional This API might change or be removed in a future release.
+ */
+ public static TimeZoneNames getTZDBInstance(ULocale locale) {
+ return new TZDBTimeZoneNames(locale);
+ }
+
/**
* Returns an immutable set of all available meta zone IDs.
* @return An immutable set of all available meta zone IDs.
version https://git-lfs.github.com/spec/v1
-oid sha256:df42e127c7c6127bce3a0a44577d33d8457fc073f5fa131f6916c039b374932c
-size 10503267
+oid sha256:3d46efbf5fced8f73fd8e352902259aa0ba4c89fdf9fcbee24862044a09c56b8
+size 10505785
version https://git-lfs.github.com/spec/v1
-oid sha256:33523d17a26aa17b47fafbd6242592cd070436cd988b32d67230612a31432ca8
+oid sha256:d3137adf135a24c2bb8f5fcbbbdea86e07a79f3eb8f4dab3734e88afa7a2dc7a
size 91046
import com.ibm.icu.text.TimeZoneFormat.ParseOption;
import com.ibm.icu.text.TimeZoneFormat.Style;
import com.ibm.icu.text.TimeZoneFormat.TimeType;
+import com.ibm.icu.text.TimeZoneNames;
import com.ibm.icu.util.BasicTimeZone;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.Output;
public void TestParse() {
final Object[][] DATA = {
- // text inpos locale style parseAll? expected outpos time type
- {"Z", 0, "en_US", Style.ISO_EXTENDED_FULL, false, "Etc/GMT", 1, TimeType.UNKNOWN},
- {"Z", 0, "en_US", Style.SPECIFIC_LONG, false, "Etc/GMT", 1, TimeType.UNKNOWN},
- {"Zambia time", 0, "en_US", Style.ISO_EXTENDED_FULL, true, "Etc/GMT", 1, TimeType.UNKNOWN},
- {"Zambia time", 0, "en_US", Style.GENERIC_LOCATION, false, "Africa/Lusaka", 11, TimeType.UNKNOWN},
- {"Zambia time", 0, "en_US", Style.ISO_BASIC_LOCAL_FULL, true, "Africa/Lusaka", 11, TimeType.UNKNOWN},
- {"+00:00", 0, "en_US", Style.ISO_EXTENDED_FULL, false, "Etc/GMT", 6, TimeType.UNKNOWN},
- {"-01:30:45", 0, "en_US", Style.ISO_EXTENDED_FULL, false, "GMT-01:30:45", 9, TimeType.UNKNOWN},
- {"-7", 0, "en_US", Style.ISO_BASIC_LOCAL_FULL, false, "GMT-07:00", 2, TimeType.UNKNOWN},
- {"-2222", 0, "en_US", Style.ISO_BASIC_LOCAL_FULL, false, "GMT-22:22", 5, TimeType.UNKNOWN},
- {"-3333", 0, "en_US", Style.ISO_BASIC_LOCAL_FULL, false, "GMT-03:33", 4, TimeType.UNKNOWN},
- {"XXX+01:30YYY", 3, "en_US", Style.LOCALIZED_GMT, false, "GMT+01:30", 9, TimeType.UNKNOWN},
- {"GMT0", 0, "en_US", Style.SPECIFIC_SHORT, false, "Etc/GMT", 3, TimeType.UNKNOWN},
- {"EST", 0, "en_US", Style.SPECIFIC_SHORT, false, "America/New_York", 3, TimeType.STANDARD},
- {"ESTx", 0, "en_US", Style.SPECIFIC_SHORT, false, "America/New_York", 3, TimeType.STANDARD},
- {"EDTx", 0, "en_US", Style.SPECIFIC_SHORT, false, "America/New_York", 3, TimeType.DAYLIGHT},
- {"EST", 0, "en_US", Style.SPECIFIC_LONG, false, null, 0, TimeType.UNKNOWN},
- {"EST", 0, "en_US", Style.SPECIFIC_LONG, true, "America/New_York", 3, TimeType.STANDARD},
- {"EST", 0, "en_CA", Style.SPECIFIC_SHORT, false, "America/Toronto", 3, TimeType.STANDARD},
+ // text inpos locale style
+ // parseOptions expected outpos time type
+ {"Z", 0, "en_US", Style.ISO_EXTENDED_FULL,
+ null, "Etc/GMT", 1, TimeType.UNKNOWN},
+
+ {"Z", 0, "en_US", Style.SPECIFIC_LONG,
+ null, "Etc/GMT", 1, TimeType.UNKNOWN},
+
+ {"Zambia time", 0, "en_US", Style.ISO_EXTENDED_FULL,
+ EnumSet.of(ParseOption.ALL_STYLES), "Etc/GMT", 1, TimeType.UNKNOWN},
+
+ {"Zambia time", 0, "en_US", Style.GENERIC_LOCATION,
+ null, "Africa/Lusaka", 11, TimeType.UNKNOWN},
+
+ {"Zambia time", 0, "en_US", Style.ISO_BASIC_LOCAL_FULL,
+ EnumSet.of(ParseOption.ALL_STYLES), "Africa/Lusaka", 11, TimeType.UNKNOWN},
+
+ {"+00:00", 0, "en_US", Style.ISO_EXTENDED_FULL,
+ null, "Etc/GMT", 6, TimeType.UNKNOWN},
+
+ {"-01:30:45", 0, "en_US", Style.ISO_EXTENDED_FULL,
+ null, "GMT-01:30:45", 9, TimeType.UNKNOWN},
+
+ {"-7", 0, "en_US", Style.ISO_BASIC_LOCAL_FULL,
+ null, "GMT-07:00", 2, TimeType.UNKNOWN},
+
+ {"-2222", 0, "en_US", Style.ISO_BASIC_LOCAL_FULL,
+ null, "GMT-22:22", 5, TimeType.UNKNOWN},
+
+ {"-3333", 0, "en_US", Style.ISO_BASIC_LOCAL_FULL,
+ null, "GMT-03:33", 4, TimeType.UNKNOWN},
+
+ {"XXX+01:30YYY", 3, "en_US", Style.LOCALIZED_GMT,
+ null, "GMT+01:30", 9, TimeType.UNKNOWN},
+
+ {"GMT0", 0, "en_US", Style.SPECIFIC_SHORT,
+ null, "Etc/GMT", 3, TimeType.UNKNOWN},
+
+ {"EST", 0, "en_US", Style.SPECIFIC_SHORT,
+ null, "America/New_York", 3, TimeType.STANDARD},
+
+ {"ESTx", 0, "en_US", Style.SPECIFIC_SHORT,
+ null, "America/New_York", 3, TimeType.STANDARD},
+
+ {"EDTx", 0, "en_US", Style.SPECIFIC_SHORT,
+ null, "America/New_York", 3, TimeType.DAYLIGHT},
+
+ {"EST", 0, "en_US", Style.SPECIFIC_LONG,
+ null, null, 0, TimeType.UNKNOWN},
+
+ {"EST", 0, "en_US", Style.SPECIFIC_LONG,
+ EnumSet.of(ParseOption.ALL_STYLES), "America/New_York", 3, TimeType.STANDARD},
+
+ {"EST", 0, "en_CA", Style.SPECIFIC_SHORT,
+ null, "America/Toronto", 3, TimeType.STANDARD},
+
+ {"CST", 0, "en_US", Style.SPECIFIC_SHORT,
+ null, "America/Chicago", 3, TimeType.STANDARD},
+
+ {"CST", 0, "en_GB", Style.SPECIFIC_SHORT,
+ null, null, 0, TimeType.UNKNOWN},
+
+ {"CST", 0, "en_GB", Style.SPECIFIC_SHORT,
+ EnumSet.of(ParseOption.TZ_DATABASE_ABBREVIATIONS), "America/Chicago", 3, TimeType.STANDARD},
+
+ {"--CST--", 2, "en_GB", Style.SPECIFIC_SHORT,
+ EnumSet.of(ParseOption.TZ_DATABASE_ABBREVIATIONS), "America/Chicago", 5, TimeType.STANDARD},
+
+ {"CST", 0, "zh_CN", Style.SPECIFIC_SHORT,
+ EnumSet.of(ParseOption.TZ_DATABASE_ABBREVIATIONS), "Asia/Shanghai", 3, TimeType.STANDARD},
+
+ {"EST", 0, "en_AU", Style.SPECIFIC_SHORT,
+ EnumSet.of(ParseOption.TZ_DATABASE_ABBREVIATIONS), "Australia/Sydney", 3, TimeType.UNKNOWN},
+
+ {"AST", 0, "ar_SA", Style.SPECIFIC_SHORT,
+ EnumSet.of(ParseOption.TZ_DATABASE_ABBREVIATIONS), "Asia/Riyadh", 3, TimeType.STANDARD},
+
+ {"AQTST", 0, "en", Style.SPECIFIC_LONG,
+ null, null, 0, TimeType.UNKNOWN},
+
+ {"AQTST", 0, "en", Style.SPECIFIC_LONG,
+ EnumSet.of(ParseOption.ALL_STYLES), null, 0, TimeType.UNKNOWN},
+
+ {"AQTST", 0, "en", Style.SPECIFIC_LONG,
+ EnumSet.of(ParseOption.ALL_STYLES, ParseOption.TZ_DATABASE_ABBREVIATIONS), "Asia/Aqtobe", 5, TimeType.DAYLIGHT},
};
for (Object[] test : DATA) {
int inPos = (Integer)test[1];
ULocale loc = new ULocale((String)test[2]);
Style style = (Style)test[3];
- EnumSet<ParseOption> options = (Boolean)test[4] ? EnumSet.of(ParseOption.ALL_STYLES) : null;
+ EnumSet<ParseOption> options = (EnumSet<ParseOption>)test[4];
String expID = (String)test[5];
int expPos = (Integer)test[6];
TimeType expType = (TimeType)test[7];
}
}
}
+
+ public void TestFormatTZDBNames() {
+ final Date dateJan = new Date(1358208000000L); // 2013-01-15T00:00:00Z
+ final Date dateJul = new Date(1373846400000L); // 2013-07-15T00:00:00Z
+
+ final Object[][] TESTDATA = {
+ {
+ "en",
+ "America/Chicago",
+ dateJan,
+ Style.SPECIFIC_SHORT,
+ "CST",
+ TimeType.STANDARD
+ },
+ {
+ "en",
+ "Asia/Shanghai",
+ dateJan,
+ Style.SPECIFIC_SHORT,
+ "CST",
+ TimeType.STANDARD
+ },
+ {
+ "zh_Hans",
+ "Asia/Shanghai",
+ dateJan,
+ Style.SPECIFIC_SHORT,
+ "CST",
+ TimeType.STANDARD
+ },
+ {
+ "en",
+ "America/Los_Angeles",
+ dateJul,
+ Style.SPECIFIC_LONG,
+ "GMT-07:00", // No long display names
+ TimeType.DAYLIGHT
+ },
+ {
+ "ja",
+ "America/Los_Angeles",
+ dateJul,
+ Style.SPECIFIC_SHORT,
+ "PDT",
+ TimeType.DAYLIGHT
+ },
+ {
+ "en",
+ "Australia/Sydney",
+ dateJan,
+ Style.SPECIFIC_SHORT,
+ "EST",
+ TimeType.DAYLIGHT
+ },
+ {
+ "en",
+ "Australia/Sydney",
+ dateJul,
+ Style.SPECIFIC_SHORT,
+ "EST",
+ TimeType.STANDARD
+ },
+ };
+
+ for (Object[] testCase : TESTDATA) {
+ ULocale loc = new ULocale((String)testCase[0]);
+ TimeZoneFormat tzfmt = TimeZoneFormat.getInstance(loc).cloneAsThawed();
+ TimeZoneNames tzdbNames = TimeZoneNames.getTZDBInstance(loc);
+ tzfmt.setTimeZoneNames(tzdbNames);
+
+ TimeZone tz = TimeZone.getTimeZone((String)testCase[1]);
+ Output<TimeType> timeType = new Output<TimeType>();
+ String out = tzfmt.format((Style)testCase[3], tz, ((Date)testCase[2]).getTime(), timeType);
+
+ if (!out.equals((String)testCase[4]) || timeType.value != testCase[5]) {
+ errln("Format result for [locale=" + testCase[0] + ",tzid=" + testCase[1] + ",date=" + testCase[2]
+ + ",style=" + testCase[3] + "]: expected [output=" + testCase[4] + ",type=" + testCase[5]
+ + "]; actual [output=" + out + ",type=" + timeType.value + "]");
+ }
+ }
+ }
}
\ No newline at end of file
/*
*******************************************************************************
- * Copyright (c) 2004-2013, International Business Machines
+ * Copyright (c) 2004-2014, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*
import java.util.Locale;
import com.ibm.icu.impl.DateNumberFormat;
+import com.ibm.icu.impl.TZDBTimeZoneNames;
import com.ibm.icu.impl.TimeZoneGenericNames;
import com.ibm.icu.impl.TimeZoneGenericNames.GenericNameType;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.text.TimeZoneFormat;
import com.ibm.icu.text.TimeZoneFormat.Style;
import com.ibm.icu.text.TimeZoneNames;
+import com.ibm.icu.text.TimeZoneNames.NameType;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.DateInterval;
import com.ibm.icu.util.GregorianCalendar;
}
}
+ public static class TZDBTimeZoneNamesHandler implements SerializableTest.Handler {
+ public Object[] getTestObjects() {
+ return new Object[] {
+ TimeZoneNames.getTZDBInstance(ULocale.ENGLISH),
+ TimeZoneNames.getTZDBInstance(ULocale.JAPAN)
+ };
+ }
+ public boolean hasSameBehavior(Object a, Object b) {
+ TZDBTimeZoneNames tzdbna = (TZDBTimeZoneNames)a;
+ TZDBTimeZoneNames tzdbnb = (TZDBTimeZoneNames)b;
+
+ final String[] TZIDS = {
+ "America/Los_Angeles",
+ "America/Argentina/Buenos_Aires",
+ "Asia/Shanghai",
+ "Etc/GMT"
+ };
+
+ final long[] DATES = {
+ 1277942400000L, // 2010-07-01 00:00:00 GMT
+ 1293840000000L, // 2011-01-01 00:00:00 GMT
+ };
+
+ final NameType[] nTypes = {
+ NameType.SHORT_STANDARD,
+ NameType.SHORT_DAYLIGHT
+ };
+
+ for (String tzid : TZIDS) {
+ for (NameType nt : nTypes) {
+ for (long date : DATES) {
+ String nameA = tzdbna.getDisplayName(tzid, nt, date);
+ String nameB = tzdbnb.getDisplayName(tzid, nt, date);
+ if (!Utility.objectEquals(nameA, nameB)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
public static class TimeZoneFormatHandler implements SerializableTest.Handler {
static final String CUSTOM_GMT_PATTERN = "Offset {0} from UTC";
map.put("com.ibm.icu.impl.TimeZoneNamesImpl", new FormatTests.TimeZoneNamesHandler());
map.put("com.ibm.icu.text.TimeZoneFormat", new FormatTests.TimeZoneFormatHandler());
map.put("com.ibm.icu.impl.TimeZoneGenericNames", new FormatTests.TimeZoneGenericNamesHandler());
+ map.put("com.ibm.icu.impl.TZDBTimeZoneNames", new FormatTests.TZDBTimeZoneNamesHandler());
map.put("com.ibm.icu.util.Calendar", new CalendarTests.CalendarHandler());
map.put("com.ibm.icu.util.BuddhistCalendar", new CalendarTests.BuddhistCalendarHandler());