2 *******************************************************************************
3 * Copyright (C) 2011, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
7 package com.ibm.icu.text;
9 import java.io.Serializable;
10 import java.util.Collection;
11 import java.util.Collections;
12 import java.util.EnumSet;
14 import java.util.regex.Pattern;
16 import com.ibm.icu.impl.ICUConfig;
17 import com.ibm.icu.impl.SoftCache;
18 import com.ibm.icu.util.TimeZone;
19 import com.ibm.icu.util.ULocale;
22 * <code>TimeZoneNames</code> is an abstract class representing the time zone display name data model defined
23 * by <a href="http://www.unicode.org/reports/tr35/">UTS#35 Unicode Locale Data Markup Language (LDML)</a>.
24 * The model defines meta zone, which is used for storing a set of display names. A meta zone can be shared
25 * by multiple time zones. Also a time zone may have multiple meta zone historic mappings.
27 * For example, people in the United States refer the zone used by the east part of North America as "Eastern Time".
28 * The tz database contains multiple time zones "America/New_York", "America/Detroit", "America/Montreal" and some
29 * others that belong to "Eastern Time". However, assigning different display names to these time zones does not make
30 * much sense for most of people.
32 * In <a href="http://cldr.unicode.org/">CLDR</a> (which uses LDML for representing locale data), the display name
33 * "Eastern Time" is stored as long generic display name of a meta zone identified by the ID "America_Eastern".
34 * Then, there is another table maintaining the historic mapping to meta zones for each time zone. The time zones in
35 * the above example ("America/New_York", "America/Detroit"...) are mapped to the meta zone "America_Eastern".
37 * Sometimes, a time zone is mapped to a different time zone in the past. For example, "America/Indiana/Knox"
38 * had been moving "Eastern Time" and "Central Time" back and forth. Therefore, it is necessary that time zone
39 * to meta zones mapping data are stored by date range.
43 * {@link TimeZoneFormat} assumes an instance of <code>TimeZoneNames</code> is immutable. If you want to provide
44 * your own <code>TimeZoneNames</code> implementation and use it with {@link TimeZoneFormat}, you must follow
47 * The methods in this class assume that time zone IDs are already canonicalized. For example, you may not get proper
48 * result returned by a method with time zone ID "America/Indiana/Indianapolis", because it's not a canonical time zone
49 * ID (the canonical time zone ID for the time zone is "America/Indianapolis". See
50 * {@link TimeZone#getCanonicalID(String)} about ICU canonical time zone IDs.
53 * In CLDR, most of time zone display names except location names are provided through meta zones. But a time zone may
54 * have a specific name that is not shared with other time zones.
56 * For example, time zone "Europe/London" has English long name for standard time "Greenwich Mean Time", which is also
57 * shared with other time zones. However, the long name for daylight saving time is "British Summer Time", which is only
58 * used for "Europe/London".
61 * {@link #getTimeZoneDisplayName(String, NameType)} is designed for accessing a name only used by a single time zone.
62 * But is not necessarily mean that a subclass implementation use the same model with CLDR. A subclass implementation
63 * may provide time zone names only through {@link #getTimeZoneDisplayName(String, NameType)}, or only through
64 * {@link #getMetaZoneDisplayName(String, NameType)}, or both.
66 * @internal ICU 4.8 technology preview
67 * @deprecated This API might change or be removed in a future release.
69 public abstract class TimeZoneNames implements Serializable {
71 private static final long serialVersionUID = -9180227029248969153L;
74 * Time zone display name types
76 * @internal ICU 4.8 technology preview
77 * @deprecated This API might change or be removed in a future release.
79 public enum NameType {
81 * Long display name, such as "Eastern Time".
83 * @internal ICU 4.8 technology preview
84 * @deprecated This API might change or be removed in a future release.
88 * Long display name for standard time, such as "Eastern Standard Time".
90 * @internal ICU 4.8 technology preview
91 * @deprecated This API might change or be removed in a future release.
95 * Long display name for daylight saving time, such as "Eastern Daylight Time".
97 * @internal ICU 4.8 technology preview
98 * @deprecated This API might change or be removed in a future release.
102 * Short display name, such as "ET".
104 * @internal ICU 4.8 technology preview
105 * @deprecated This API might change or be removed in a future release.
109 * Short display name for standard time, such as "EST".
111 * @internal ICU 4.8 technology preview
112 * @deprecated This API might change or be removed in a future release.
116 * Short display name for daylight saving time, such as "EDT".
118 * @internal ICU 4.8 technology preview
119 * @deprecated This API might change or be removed in a future release.
123 * Short display name for standard time, such as "EST".
124 * <p><b>Note:</b> The short abbreviation might not be well understood by people not familiar with the zone.
125 * Unlike {@link #SHORT_STANDARD}, this type excludes short standard names not commonly used by the region.
127 * @internal ICU 4.8 technology preview
128 * @deprecated This API might change or be removed in a future release.
130 SHORT_STANDARD_COMMONLY_USED,
132 * Short display name for daylight saving time, such as "EDT".
133 * <p><b>Note:</b> The short abbreviation might not be well understood by people not familiar with the zone.
134 * Unlike {@link #SHORT_DAYLIGHT}, this type excludes short daylight names not commonly used by the region.
136 * @internal ICU 4.8 technology preview
137 * @deprecated This API might change or be removed in a future release.
139 SHORT_DAYLIGHT_COMMONLY_USED
142 private static Cache TZNAMES_CACHE = new Cache();
144 private static final Factory TZNAMES_FACTORY;
145 private static final String FACTORY_NAME_PROP = "com.ibm.icu.text.TimeZoneNames.Factory.impl";
146 private static final String DEFAULT_FACTORY_CLASS = "com.ibm.icu.impl.TimeZoneNamesFactoryImpl";
147 private static final Pattern LOC_EXCLUSION_PATTERN = Pattern.compile("Etc/.*|SystemV/.*|.*/Riyadh8[7-9]");
150 Factory factory = null;
151 String classname = ICUConfig.get(FACTORY_NAME_PROP, DEFAULT_FACTORY_CLASS);
154 factory = (Factory) Class.forName(classname).newInstance();
156 } catch (ClassNotFoundException cnfe) {
158 } catch (IllegalAccessException iae) {
160 } catch (InstantiationException ie) {
163 if (classname.equals(DEFAULT_FACTORY_CLASS)) {
166 classname = DEFAULT_FACTORY_CLASS;
169 if (factory == null) {
170 factory = new DefaultTimeZoneNames.FactoryImpl();
172 TZNAMES_FACTORY = factory;
176 * Returns an instance of <code>TimeZoneDisplayNames</code> for the specified locale.
180 * @return An instance of <code>TimeZoneDisplayNames</code>
181 * @internal ICU 4.8 technology preview
182 * @deprecated This API might change or be removed in a future release.
184 public static TimeZoneNames getInstance(ULocale locale) {
185 String key = locale.getBaseName();
186 return TZNAMES_CACHE.getInstance(key, locale);
190 * Returns an immutable set of all available meta zone IDs.
191 * @return An immutable set of all available meta zone IDs.
192 * @internal ICU 4.8 technology preview
193 * @deprecated This API might change or be removed in a future release.
195 public abstract Set<String> getAvailableMetaZoneIDs();
198 * Returns an immutable set of all available meta zone IDs used by the given time zone.
201 * The canonical time zone ID.
202 * @return An immutable set of all available meta zone IDs used by the given time zone.
203 * @internal ICU 4.8 technology preview
204 * @deprecated This API might change or be removed in a future release.
206 public abstract Set<String> getAvailableMetaZoneIDs(String tzID);
209 * Returns the meta zone ID for the given canonical time zone ID at the given date.
212 * The canonical time zone ID.
215 * @return The meta zone ID for the given time zone ID at the given date. If the time zone does not have a
216 * corresponding meta zone at the given date or the implementation does not support meta zones, null is
218 * @internal ICU 4.8 technology preview
219 * @deprecated This API might change or be removed in a future release.
221 public abstract String getMetaZoneID(String tzID, long date);
224 * Returns the reference zone ID for the given meta zone ID for the region.
230 * @return The reference zone ID ("golden zone" in the LDML specification) for the given time zone ID for the
231 * region. If the meta zone is unknown or the implementation does not support meta zones, null is returned.
232 * @internal ICU 4.8 technology preview
233 * @deprecated This API might change or be removed in a future release.
235 public abstract String getReferenceZoneID(String mzID, String region);
238 * Returns the display name of the meta zone.
243 * The display name type. See {@link TimeZoneNames.NameType}.
244 * @return The display name of the meta zone. When this object does not have a localized display name for the given
245 * meta zone with the specified type or the implementation does not provide any display names associated
246 * with meta zones, null is returned.
247 * @internal ICU 4.8 technology preview
248 * @deprecated This API might change or be removed in a future release.
250 public abstract String getMetaZoneDisplayName(String mzID, NameType type);
253 * Returns the display name of the time zone at the given date.
256 * <b>Note:</b> This method calls the subclass's {@link #getTimeZoneDisplayName(String, NameType)} first. When the
257 * result is null, this method calls {@link #getMetaZoneID(String, long)} to get the meta zone ID mapped from the
258 * time zone, then calls {@link #getMetaZoneDisplayName(String, NameType)}.
261 * The canonical time zone ID.
263 * The display name type. See {@link TimeZoneNames.NameType}.
266 * @return The display name for the time zone at the given date. When this object does not have a localized display
267 * name for the time zone with the specified type and date, null is returned.
268 * @internal ICU 4.8 technology preview
269 * @deprecated This API might change or be removed in a future release.
271 public final String getDisplayName(String tzID, NameType type, long date) {
272 String name = getTimeZoneDisplayName(tzID, type);
274 String mzID = getMetaZoneID(tzID, date);
275 name = getMetaZoneDisplayName(mzID, type);
281 * Returns the display name of the time zone. Unlike {@link #getDisplayName(String, NameType, long)},
282 * this method does not get a name from a meta zone used by the time zone.
285 * The canonical time zone ID.
287 * The display name type. See {@link TimeZoneNames.NameType}.
288 * @return The display name for the time zone. When this object does not have a localized display name for the given
289 * time zone with the specified type, null is returned.
290 * @internal ICU 4.8 technology preview
291 * @deprecated This API might change or be removed in a future release.
293 public abstract String getTimeZoneDisplayName(String tzID, NameType type);
296 * Returns the exemplar location name for the given time zone. When this object does not have a localized location
297 * name, the default implementation may still returns a programmatically generated name with the logic described
300 * <li>Check if the ID contains "/". If not, return null.
301 * <li>Check if the ID does not start with "Etc/" or "SystemV/". If it does, return null.
302 * <li>Extract a substring after the last occurrence of "/".
303 * <li>Replace "_" with " ".
305 * For example, "New York" is returned for the time zone ID "America/New_York" when this object does not have the
306 * localized location name.
309 * The canonical time zone ID
310 * @return The exemplar location name for the given time zone, or null when a localized location name is not
311 * available and the fallback logic described above cannot extract location from the ID.
312 * @internal ICU 4.8 technology preview
313 * @deprecated This API might change or be removed in a future release.
315 public String getExemplarLocationName(String tzID) {
316 if (tzID == null || tzID.length() == 0 || LOC_EXCLUSION_PATTERN.matcher(tzID).matches()) {
320 String location = null;
321 int sep = tzID.lastIndexOf('/');
322 if (sep > 0 && sep + 1 < tzID.length()) {
323 location = tzID.substring(sep + 1).replace('_', ' ');
330 * Finds time zone name prefix matches for the input text at the
331 * given offset and returns a collection of the matches.
333 * @param text the text.
334 * @param start the starting offset within the text.
335 * @param types the set of name types, or <code>null</code> for all name types.
336 * @return A collection of matches.
339 * @internal ICU 4.8 technology preview
340 * @deprecated This API might change or be removed in a future release.
342 public Collection<MatchInfo> find(String text, int start, EnumSet<NameType> types) {
343 throw new UnsupportedOperationException("The method is not implemented in TimeZoneNames base class.");
347 * A <code>MatchInfo</code> represents a time zone name match used by
348 * {@link TimeZoneNames#find(String, int, EnumSet)}.
349 * @internal ICU 4.8 technology preview
350 * @deprecated This API might change or be removed in a future release.
352 public static class MatchInfo {
353 private NameType _nameType;
354 private String _tzID;
355 private String _mzID;
356 private int _matchLength;
359 * Constructing a <code>MatchInfo</code>.
361 * @param nameType the name type enum.
362 * @param tzID the time zone ID, or null
363 * @param mzID the meta zone ID, or null
364 * @param matchLength the match length.
365 * @throws IllegalArgumentException when 1) <code>nameType</code> is <code>null</code>,
366 * or 2) both <code>tzID</code> and <code>mzID</code> are <code>null</code>,
367 * or 3) <code>matchLength</code> is 0 or smaller.
369 * @internal ICU 4.8 technology preview
370 * @deprecated This API might change or be removed in a future release.
372 public MatchInfo(NameType nameType, String tzID, String mzID, int matchLength) {
373 if (nameType == null) {
374 throw new IllegalArgumentException("nameType is null");
376 if (tzID == null && mzID == null) {
377 throw new IllegalArgumentException("Either tzID or mzID must be available");
379 if (matchLength <= 0) {
380 throw new IllegalArgumentException("matchLength must be positive value");
382 _nameType = nameType;
385 _matchLength = matchLength;
389 * Returns the time zone ID, or <code>null</code> if not available.
391 * <p><b>Note</b>: A <code>MatchInfo</code> must have either a time zone ID
394 * @return the time zone ID, or <code>null</code>.
396 * @internal ICU 4.8 technology preview
397 * @deprecated This API might change or be removed in a future release.
399 public String tzID() {
404 * Returns the meta zone ID, or <code>null</code> if not available.
406 * <p><b>Note</b>: A <code>MatchInfo</code> must have either a time zone ID
409 * @return the meta zone ID, or <code>null</code>.
411 * @internal ICU 4.8 technology preview
412 * @deprecated This API might change or be removed in a future release.
414 public String mzID() {
419 * Returns the time zone name type.
420 * @return the time zone name type enum.
422 * @internal ICU 4.8 technology preview
423 * @deprecated This API might change or be removed in a future release.
425 public NameType nameType() {
430 * Returns the match length.
431 * @return the match length.
432 * @internal ICU 4.8 technology preview
433 * @deprecated This API might change or be removed in a future release.
435 public int matchLength() {
441 * Sole constructor for invocation by subclass constructors.
443 * @internal ICU 4.8 technology preview
444 * @deprecated This API might change or be removed in a future release.
446 protected TimeZoneNames() {
450 * The super class of <code>TimeZoneNames</code> service factory classes.
454 public static abstract class Factory {
456 * The factory method of <code>TimeZoneNames</code>.
460 * @return An instance of <code>TimeZoneNames</code>.
463 public abstract TimeZoneNames getTimeZoneNames(ULocale locale);
467 * TimeZoneNames cache used by {@link TimeZoneNames#getInstance(ULocale)}
469 private static class Cache extends SoftCache<String, TimeZoneNames, ULocale> {
474 * @see com.ibm.icu.impl.CacheBase#createInstance(java.lang.Object, java.lang.Object)
477 protected TimeZoneNames createInstance(String key, ULocale data) {
478 return TZNAMES_FACTORY.getTimeZoneNames(data);
484 * The default implementation of <code>TimeZoneNames</code> used by {@link TimeZoneNames#getInstance(ULocale)} when
485 * the ICU4J tznamedata component is not available.
487 private static class DefaultTimeZoneNames extends TimeZoneNames {
489 private static final long serialVersionUID = -995672072494349071L;
491 public static final DefaultTimeZoneNames INSTANCE = new DefaultTimeZoneNames();
494 * @see com.ibm.icu.text.TimeZoneNames#getAvailableMetaZoneIDs()
497 public Set<String> getAvailableMetaZoneIDs() {
498 return Collections.emptySet();
502 * @see com.ibm.icu.text.TimeZoneNames#getAvailableMetaZoneIDs(java.lang.String)
505 public Set<String> getAvailableMetaZoneIDs(String tzID) {
506 return Collections.emptySet();
512 * @see com.ibm.icu.text.TimeZoneNames#getMetaZoneID (java.lang.String, long)
515 public String getMetaZoneID(String tzID, long date) {
522 * @see com.ibm.icu.text.TimeZoneNames#getReferenceZoneID(java.lang.String, java.lang.String)
525 public String getReferenceZoneID(String mzID, String region) {
531 * @see com.ibm.icu.text.TimeZoneNames#getMetaZoneDisplayName(java.lang.String, com.ibm.icu.text.TimeZoneNames.NameType)
534 public String getMetaZoneDisplayName(String mzID, NameType type) {
540 * @see com.ibm.icu.text.TimeZoneNames#getTimeZoneDisplayName(java.lang.String, com.ibm.icu.text.TimeZoneNames.NameType)
543 public String getTimeZoneDisplayName(String tzID, NameType type) {
548 * @see com.ibm.icu.text.TimeZoneNames#find(java.lang.String, int, com.ibm.icu.text.TimeZoneNames.NameType[])
551 public Collection<MatchInfo> find(String text, int start, EnumSet<NameType> nameTypes) {
552 return Collections.emptyList();
556 * The default <code>TimeZoneNames</code> factory called from {@link TimeZoneNames#getInstance(ULocale)} when
557 * the ICU4J tznamedata component is not available.
559 public static class FactoryImpl extends Factory {
564 * @see com.ibm.icu.text.TimeZoneNames.Factory#getTimeZoneNames (com.ibm.icu.util.ULocale)
567 public TimeZoneNames getTimeZoneNames(ULocale locale) {
568 return DefaultTimeZoneNames.INSTANCE;