Home | History | Annotate | Download | only in text
      1 /* GENERATED SOURCE. DO NOT MODIFY. */
      2 //  2016 and later: Unicode, Inc. and others.
      3 // License & terms of use: http://www.unicode.org/copyright.html#License
      4 /*
      5  *******************************************************************************
      6  * Copyright (C) 2011-2016, International Business Machines Corporation and
      7  * others. All Rights Reserved.
      8  *******************************************************************************
      9  */
     10 package android.icu.text;
     11 
     12 import java.io.Serializable;
     13 import java.util.Collection;
     14 import java.util.Collections;
     15 import java.util.EnumSet;
     16 import java.util.Locale;
     17 import java.util.Set;
     18 
     19 import android.icu.impl.ICUConfig;
     20 import android.icu.impl.SoftCache;
     21 import android.icu.impl.TZDBTimeZoneNames;
     22 import android.icu.impl.TimeZoneNamesImpl;
     23 import android.icu.util.TimeZone;
     24 import android.icu.util.ULocale;
     25 
     26 /**
     27  * <code>TimeZoneNames</code> is an abstract class representing the time zone display name data model defined
     28  * by <a href="http://www.unicode.org/reports/tr35/">UTS#35 Unicode Locale Data Markup Language (LDML)</a>.
     29  * The model defines meta zone, which is used for storing a set of display names. A meta zone can be shared
     30  * by multiple time zones. Also a time zone may have multiple meta zone historic mappings.
     31  * <p>
     32  * For example, people in the United States refer the zone used by the east part of North America as "Eastern Time".
     33  * The tz database contains multiple time zones "America/New_York", "America/Detroit", "America/Montreal" and some
     34  * others that belong to "Eastern Time". However, assigning different display names to these time zones does not make
     35  * much sense for most of people.
     36  * <p>
     37  * In <a href="http://cldr.unicode.org/">CLDR</a> (which uses LDML for representing locale data), the display name
     38  * "Eastern Time" is stored as long generic display name of a meta zone identified by the ID "America_Eastern".
     39  * Then, there is another table maintaining the historic mapping to meta zones for each time zone. The time zones in
     40  * the above example ("America/New_York", "America/Detroit"...) are mapped to the meta zone "America_Eastern".
     41  * <p>
     42  * Sometimes, a time zone is mapped to a different time zone in the past. For example, "America/Indiana/Knox"
     43  * had been moving "Eastern Time" and "Central Time" back and forth. Therefore, it is necessary that time zone
     44  * to meta zones mapping data are stored by date range.
     45  *
     46  * <p><b>Note:</b>
     47  * <p>
     48  * {@link TimeZoneFormat} assumes an instance of <code>TimeZoneNames</code> is immutable. If you want to provide
     49  * your own <code>TimeZoneNames</code> implementation and use it with {@link TimeZoneFormat}, you must follow
     50  * the contract.
     51  * <p>
     52  * The methods in this class assume that time zone IDs are already canonicalized. For example, you may not get proper
     53  * result returned by a method with time zone ID "America/Indiana/Indianapolis", because it's not a canonical time zone
     54  * ID (the canonical time zone ID for the time zone is "America/Indianapolis". See
     55  * {@link TimeZone#getCanonicalID(String)} about ICU canonical time zone IDs.
     56  *
     57  * <p>
     58  * In CLDR, most of time zone display names except location names are provided through meta zones. But a time zone may
     59  * have a specific name that is not shared with other time zones.
     60  *
     61  * For example, time zone "Europe/London" has English long name for standard time "Greenwich Mean Time", which is also
     62  * shared with other time zones. However, the long name for daylight saving time is "British Summer Time", which is only
     63  * used for "Europe/London".
     64  *
     65  * <p>
     66  * {@link #getTimeZoneDisplayName(String, NameType)} is designed for accessing a name only used by a single time zone.
     67  * But is not necessarily mean that a subclass implementation use the same model with CLDR. A subclass implementation
     68  * may provide time zone names only through {@link #getTimeZoneDisplayName(String, NameType)}, or only through
     69  * {@link #getMetaZoneDisplayName(String, NameType)}, or both.
     70  *
     71  * <p>
     72  * The default <code>TimeZoneNames</code> implementation returned by {@link #getInstance(ULocale)} uses the locale data
     73  * imported from CLDR. In CLDR, set of meta zone IDs and mappings between zone IDs and meta zone IDs are shared by all
     74  * locales. Therefore, the behavior of {@link #getAvailableMetaZoneIDs()}, {@link #getAvailableMetaZoneIDs(String)},
     75  * {@link #getMetaZoneID(String, long)}, and {@link #getReferenceZoneID(String, String)} won't be changed no matter
     76  * what locale is used for getting an instance of <code>TimeZoneNames</code>.
     77  */
     78 public abstract class TimeZoneNames implements Serializable {
     79 
     80     private static final long serialVersionUID = -9180227029248969153L;
     81 
     82     /**
     83      * Time zone display name types
     84      */
     85     public enum NameType {
     86         /**
     87          * Long display name, such as "Eastern Time".
     88          */
     89         LONG_GENERIC,
     90         /**
     91          * Long display name for standard time, such as "Eastern Standard Time".
     92          */
     93         LONG_STANDARD,
     94         /**
     95          * Long display name for daylight saving time, such as "Eastern Daylight Time".
     96          */
     97         LONG_DAYLIGHT,
     98         /**
     99          * Short display name, such as "ET".
    100          */
    101         SHORT_GENERIC,
    102         /**
    103          * Short display name for standard time, such as "EST".
    104          */
    105         SHORT_STANDARD,
    106         /**
    107          * Short display name for daylight saving time, such as "EDT".
    108          */
    109         SHORT_DAYLIGHT,
    110         /**
    111          * Exemplar location name, such as "Los Angeles".
    112          */
    113         EXEMPLAR_LOCATION,
    114     }
    115 
    116     private static Cache TZNAMES_CACHE = new Cache();
    117 
    118     private static final Factory TZNAMES_FACTORY;
    119     private static final String FACTORY_NAME_PROP = "android.icu.text.TimeZoneNames.Factory.impl";
    120     private static final String DEFAULT_FACTORY_CLASS = "android.icu.impl.TimeZoneNamesFactoryImpl";
    121 
    122     static {
    123         Factory factory = null;
    124         String classname = ICUConfig.get(FACTORY_NAME_PROP, DEFAULT_FACTORY_CLASS);
    125         while (true) {
    126             try {
    127                 factory = (Factory) Class.forName(classname).newInstance();
    128                 break;
    129             } catch (ClassNotFoundException cnfe) {
    130                 // fall through
    131             } catch (IllegalAccessException iae) {
    132                 // fall through
    133             } catch (InstantiationException ie) {
    134                 // fall through
    135             }
    136             if (classname.equals(DEFAULT_FACTORY_CLASS)) {
    137                 break;
    138             }
    139             classname = DEFAULT_FACTORY_CLASS;
    140         }
    141 
    142         if (factory == null) {
    143             factory = new DefaultTimeZoneNames.FactoryImpl();
    144         }
    145         TZNAMES_FACTORY = factory;
    146     }
    147 
    148     /**
    149      * Returns an instance of <code>TimeZoneNames</code> for the specified locale.
    150      *
    151      * @param locale
    152      *            The locale.
    153      * @return An instance of <code>TimeZoneNames</code>
    154      */
    155     public static TimeZoneNames getInstance(ULocale locale) {
    156         String key = locale.getBaseName();
    157         return TZNAMES_CACHE.getInstance(key, locale);
    158     }
    159 
    160     /**
    161      * Returns an instance of <code>TimeZoneNames</code> for the specified
    162      * {@link java.util.Locale}.
    163      *
    164      * @param locale
    165      *            The {@link java.util.Locale}.
    166      * @return An instance of <code>TimeZoneDisplayNames</code>
    167      */
    168     public static TimeZoneNames getInstance(Locale locale) {
    169         return getInstance(ULocale.forLocale(locale));
    170     }
    171 
    172     /**
    173      * Returns an instance of <code>TimeZoneNames</code> containing only short specific
    174      * zone names ({@link NameType#SHORT_STANDARD} and {@link NameType#SHORT_DAYLIGHT}),
    175      * compatible with the IANA tz database's zone abbreviations (not localized).
    176      * <br>
    177      * Note: The input locale is used for resolving ambiguous names (e.g. "IST" is parsed
    178      * as Israel Standard Time for Israel, while it is parsed as India Standard Time for
    179      * all other regions). The zone names returned by this instance are not localized.
    180      */
    181     public static TimeZoneNames getTZDBInstance(ULocale locale) {
    182         return new TZDBTimeZoneNames(locale);
    183     }
    184 
    185     /**
    186      * Returns an immutable set of all available meta zone IDs.
    187      * @return An immutable set of all available meta zone IDs.
    188      */
    189     public abstract Set<String> getAvailableMetaZoneIDs();
    190 
    191     /**
    192      * Returns an immutable set of all available meta zone IDs used by the given time zone.
    193      *
    194      * @param tzID
    195      *            The canonical time zone ID.
    196      * @return An immutable set of all available meta zone IDs used by the given time zone.
    197      */
    198     public abstract Set<String> getAvailableMetaZoneIDs(String tzID);
    199 
    200     /**
    201      * Returns the meta zone ID for the given canonical time zone ID at the given date.
    202      *
    203      * @param tzID
    204      *            The canonical time zone ID.
    205      * @param date
    206      *            The date.
    207      * @return The meta zone ID for the given time zone ID at the given date. If the time zone does not have a
    208      *         corresponding meta zone at the given date or the implementation does not support meta zones, null is
    209      *         returned.
    210      */
    211     public abstract String getMetaZoneID(String tzID, long date);
    212 
    213     /**
    214      * Returns the reference zone ID for the given meta zone ID for the region.
    215      *
    216      * Note: Each meta zone must have a reference zone associated with a special region "001" (world).
    217      * Some meta zones may have region specific reference zone IDs other than the special region
    218      * "001". When a meta zone does not have any region specific reference zone IDs, this method
    219      * return the reference zone ID for the special region "001" (world).
    220      *
    221      * @param mzID
    222      *            The meta zone ID.
    223      * @param region
    224      *            The region.
    225      * @return The reference zone ID ("golden zone" in the LDML specification) for the given time zone ID for the
    226      *         region. If the meta zone is unknown or the implementation does not support meta zones, null is returned.
    227      */
    228     public abstract String getReferenceZoneID(String mzID, String region);
    229 
    230     /**
    231      * Returns the display name of the meta zone.
    232      *
    233      * @param mzID
    234      *            The meta zone ID.
    235      * @param type
    236      *            The display name type. See {@link TimeZoneNames.NameType}.
    237      * @return The display name of the meta zone. When this object does not have a localized display name for the given
    238      *         meta zone with the specified type or the implementation does not provide any display names associated
    239      *         with meta zones, null is returned.
    240      */
    241     public abstract String getMetaZoneDisplayName(String mzID, NameType type);
    242 
    243     /**
    244      * Returns the display name of the time zone at the given date.
    245      *
    246      * <p>
    247      * <b>Note:</b> This method calls the subclass's {@link #getTimeZoneDisplayName(String, NameType)} first. When the
    248      * result is null, this method calls {@link #getMetaZoneID(String, long)} to get the meta zone ID mapped from the
    249      * time zone, then calls {@link #getMetaZoneDisplayName(String, NameType)}.
    250      *
    251      * @param tzID
    252      *            The canonical time zone ID.
    253      * @param type
    254      *            The display name type. See {@link TimeZoneNames.NameType}.
    255      * @param date
    256      *            The date
    257      * @return The display name for the time zone at the given date. When this object does not have a localized display
    258      *         name for the time zone with the specified type and date, null is returned.
    259      */
    260     public final String getDisplayName(String tzID, NameType type, long date) {
    261         String name = getTimeZoneDisplayName(tzID, type);
    262         if (name == null) {
    263             String mzID = getMetaZoneID(tzID, date);
    264             name = getMetaZoneDisplayName(mzID, type);
    265         }
    266         return name;
    267     }
    268 
    269     /**
    270      * Returns the display name of the time zone. Unlike {@link #getDisplayName(String, NameType, long)},
    271      * this method does not get a name from a meta zone used by the time zone.
    272      *
    273      * @param tzID
    274      *            The canonical time zone ID.
    275      * @param type
    276      *            The display name type. See {@link TimeZoneNames.NameType}.
    277      * @return The display name for the time zone. When this object does not have a localized display name for the given
    278      *         time zone with the specified type, null is returned.
    279      */
    280     public abstract String getTimeZoneDisplayName(String tzID, NameType type);
    281 
    282     /**
    283      * Returns the exemplar location name for the given time zone. When this object does not have a localized location
    284      * name, the default implementation may still returns a programmatically generated name with the logic described
    285      * below.
    286      * <ol>
    287      * <li>Check if the ID contains "/". If not, return null.
    288      * <li>Check if the ID does not start with "Etc/" or "SystemV/". If it does, return null.
    289      * <li>Extract a substring after the last occurrence of "/".
    290      * <li>Replace "_" with " ".
    291      * </ol>
    292      * For example, "New York" is returned for the time zone ID "America/New_York" when this object does not have the
    293      * localized location name.
    294      *
    295      * @param tzID
    296      *            The canonical time zone ID
    297      * @return The exemplar location name for the given time zone, or null when a localized location name is not
    298      *         available and the fallback logic described above cannot extract location from the ID.
    299      */
    300     public String getExemplarLocationName(String tzID) {
    301         return TimeZoneNamesImpl.getDefaultExemplarLocationName(tzID);
    302     }
    303 
    304     /**
    305      * Finds time zone name prefix matches for the input text at the
    306      * given offset and returns a collection of the matches.
    307      *
    308      * @param text the text.
    309      * @param start the starting offset within the text.
    310      * @param types the set of name types, or <code>null</code> for all name types.
    311      * @return A collection of matches.
    312      * @see NameType
    313      * @see MatchInfo
    314      * @hide draft / provisional / internal are hidden on Android
    315      */
    316     public Collection<MatchInfo> find(CharSequence text, int start, EnumSet<NameType> types) {
    317         throw new UnsupportedOperationException("The method is not implemented in TimeZoneNames base class.");
    318     }
    319 
    320     /**
    321      * A <code>MatchInfo</code> represents a time zone name match used by
    322      * {@link TimeZoneNames#find(CharSequence, int, EnumSet)}.
    323      * @hide draft / provisional / internal are hidden on Android
    324      */
    325     public static class MatchInfo {
    326         private NameType _nameType;
    327         private String _tzID;
    328         private String _mzID;
    329         private int _matchLength;
    330 
    331         /**
    332          * Constructing a <code>MatchInfo</code>.
    333          *
    334          * @param nameType the name type enum.
    335          * @param tzID the time zone ID, or null
    336          * @param mzID the meta zone ID, or null
    337          * @param matchLength the match length.
    338          * @throws IllegalArgumentException when 1) <code>nameType</code> is <code>null</code>,
    339          * or 2) both <code>tzID</code> and <code>mzID</code> are <code>null</code>,
    340          * or 3) <code>matchLength</code> is 0 or smaller.
    341          * @see NameType
    342          * @hide draft / provisional / internal are hidden on Android
    343          */
    344         public MatchInfo(NameType nameType, String tzID, String mzID, int matchLength) {
    345             if (nameType == null) {
    346                 throw new IllegalArgumentException("nameType is null");
    347             }
    348             if (tzID == null && mzID == null) {
    349                 throw new IllegalArgumentException("Either tzID or mzID must be available");
    350             }
    351             if (matchLength <= 0) {
    352                 throw new IllegalArgumentException("matchLength must be positive value");
    353             }
    354             _nameType = nameType;
    355             _tzID = tzID;
    356             _mzID = mzID;
    357             _matchLength = matchLength;
    358         }
    359 
    360         /**
    361          * Returns the time zone ID, or <code>null</code> if not available.
    362          *
    363          * <p><b>Note</b>: A <code>MatchInfo</code> must have either a time zone ID
    364          * or a meta zone ID.
    365          *
    366          * @return the time zone ID, or <code>null</code>.
    367          * @see #mzID()
    368          * @hide draft / provisional / internal are hidden on Android
    369          */
    370         public String tzID() {
    371             return _tzID;
    372         }
    373 
    374         /**
    375          * Returns the meta zone ID, or <code>null</code> if not available.
    376          *
    377          * <p><b>Note</b>: A <code>MatchInfo</code> must have either a time zone ID
    378          * or a meta zone ID.
    379          *
    380          * @return the meta zone ID, or <code>null</code>.
    381          * @see #tzID()
    382          * @hide draft / provisional / internal are hidden on Android
    383          */
    384         public String mzID() {
    385             return _mzID;
    386         }
    387 
    388         /**
    389          * Returns the time zone name type.
    390          * @return the time zone name type enum.
    391          * @see NameType
    392          * @hide draft / provisional / internal are hidden on Android
    393          */
    394         public NameType nameType() {
    395             return _nameType;
    396         }
    397 
    398         /**
    399          * Returns the match length.
    400          * @return the match length.
    401          * @hide draft / provisional / internal are hidden on Android
    402          */
    403         public int matchLength() {
    404             return _matchLength;
    405         }
    406     }
    407 
    408     /**
    409      * @deprecated This API is ICU internal only.
    410      * @hide original deprecated declaration
    411      * @hide draft / provisional / internal are hidden on Android
    412      */
    413     @Deprecated
    414     public void loadAllDisplayNames() {}
    415 
    416     /**
    417      * @deprecated This API is ICU internal only.
    418      * @hide original deprecated declaration
    419      * @hide draft / provisional / internal are hidden on Android
    420      */
    421     @Deprecated
    422     public void getDisplayNames(String tzID, NameType[] types, long date,
    423             String[] dest, int destOffset) {
    424         if (tzID == null || tzID.length() == 0) {
    425             return;
    426         }
    427         String mzID = null;
    428         for (int i = 0; i < types.length; ++i) {
    429             NameType type = types[i];
    430             String name = getTimeZoneDisplayName(tzID, type);
    431             if (name == null) {
    432                 if (mzID == null) {
    433                     mzID = getMetaZoneID(tzID, date);
    434                 }
    435                 name = getMetaZoneDisplayName(mzID, type);
    436             }
    437             dest[destOffset + i] = name;
    438         }
    439     }
    440 
    441     /**
    442      * Sole constructor for invocation by subclass constructors.
    443      *
    444      * @hide draft / provisional / internal are hidden on Android
    445      */
    446     protected TimeZoneNames() {
    447     }
    448 
    449     /**
    450      * The super class of <code>TimeZoneNames</code> service factory classes.
    451      *
    452      * @deprecated This API is ICU internal only.
    453      * @hide original deprecated declaration
    454      * @hide draft / provisional / internal are hidden on Android
    455      */
    456     @Deprecated
    457     public static abstract class Factory {
    458         /**
    459          * The factory method of <code>TimeZoneNames</code>.
    460          *
    461          * @param locale
    462          *            The display locale
    463          * @return An instance of <code>TimeZoneNames</code>.
    464          * @deprecated This API is ICU internal only.
    465          * @hide original deprecated declaration
    466          * @hide draft / provisional / internal are hidden on Android
    467          */
    468         @Deprecated
    469         public abstract TimeZoneNames getTimeZoneNames(ULocale locale);
    470 
    471         /**
    472          * Sole constructor
    473          * @deprecated This API is ICU internal only.
    474          * @hide original deprecated declaration
    475          * @hide draft / provisional / internal are hidden on Android
    476          */
    477         @Deprecated
    478         protected Factory() {
    479         }
    480     }
    481 
    482     /**
    483      * TimeZoneNames cache used by {@link TimeZoneNames#getInstance(ULocale)}
    484      */
    485     private static class Cache extends SoftCache<String, TimeZoneNames, ULocale> {
    486 
    487         /*
    488          * (non-Javadoc)
    489          *
    490          * @see android.icu.impl.CacheBase#createInstance(java.lang.Object, java.lang.Object)
    491          */
    492         @Override
    493         protected TimeZoneNames createInstance(String key, ULocale data) {
    494             return TZNAMES_FACTORY.getTimeZoneNames(data);
    495         }
    496 
    497     }
    498 
    499     ///CLOVER:OFF
    500     /**
    501      * The default implementation of <code>TimeZoneNames</code> used by {@link TimeZoneNames#getInstance(ULocale)} when
    502      * the ICU4J tznamedata component is not available.
    503      */
    504     private static class DefaultTimeZoneNames extends TimeZoneNames {
    505 
    506         private static final long serialVersionUID = -995672072494349071L;
    507 
    508         public static final DefaultTimeZoneNames INSTANCE = new DefaultTimeZoneNames();
    509 
    510         /* (non-Javadoc)
    511          * @see android.icu.text.TimeZoneNames#getAvailableMetaZoneIDs()
    512          */
    513         @Override
    514         public Set<String> getAvailableMetaZoneIDs() {
    515             return Collections.emptySet();
    516         }
    517 
    518         /* (non-Javadoc)
    519          * @see android.icu.text.TimeZoneNames#getAvailableMetaZoneIDs(java.lang.String)
    520          */
    521         @Override
    522         public Set<String> getAvailableMetaZoneIDs(String tzID) {
    523             return Collections.emptySet();
    524         }
    525 
    526         /*
    527          * (non-Javadoc)
    528          *
    529          * @see android.icu.text.TimeZoneNames#getMetaZoneID (java.lang.String, long)
    530          */
    531         @Override
    532         public String getMetaZoneID(String tzID, long date) {
    533             return null;
    534         }
    535 
    536         /*
    537          * (non-Javadoc)
    538          *
    539          * @see android.icu.text.TimeZoneNames#getReferenceZoneID(java.lang.String, java.lang.String)
    540          */
    541         @Override
    542         public String getReferenceZoneID(String mzID, String region) {
    543             return null;
    544         }
    545 
    546         /*
    547          *  (non-Javadoc)
    548          * @see android.icu.text.TimeZoneNames#getMetaZoneDisplayName(java.lang.String, android.icu.text.TimeZoneNames.NameType)
    549          */
    550         @Override
    551         public String getMetaZoneDisplayName(String mzID, NameType type) {
    552             return null;
    553         }
    554 
    555         /*
    556          * (non-Javadoc)
    557          * @see android.icu.text.TimeZoneNames#getTimeZoneDisplayName(java.lang.String, android.icu.text.TimeZoneNames.NameType)
    558          */
    559         @Override
    560         public String getTimeZoneDisplayName(String tzID, NameType type) {
    561             return null;
    562         }
    563 
    564         /* (non-Javadoc)
    565          * @see android.icu.text.TimeZoneNames#find(java.lang.CharSequence, int, android.icu.text.TimeZoneNames.NameType[])
    566          */
    567         @Override
    568         public Collection<MatchInfo> find(CharSequence text, int start, EnumSet<NameType> nameTypes) {
    569             return Collections.emptyList();
    570         }
    571 
    572         /**
    573          * The default <code>TimeZoneNames</code> factory called from {@link TimeZoneNames#getInstance(ULocale)} when
    574          * the ICU4J tznamedata component is not available.
    575          */
    576         public static class FactoryImpl extends Factory {
    577 
    578             /*
    579              * (non-Javadoc)
    580              *
    581              * @see android.icu.text.TimeZoneNames.Factory#getTimeZoneNames (android.icu.util.ULocale)
    582              */
    583             @Override
    584             public TimeZoneNames getTimeZoneNames(ULocale locale) {
    585                 return DefaultTimeZoneNames.INSTANCE;
    586             }
    587         }
    588     }
    589     ///CLOVER:ON
    590 }
    591