]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/util/TimeZone.java
icu4jsrc
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / util / TimeZone.java
1 /*\r
2  * @(#)TimeZone.java    1.51 00/01/19\r
3  *\r
4  * Copyright (C) 1996-2009, International Business Machines\r
5  * Corporation and others.  All Rights Reserved.\r
6  */\r
7 \r
8 package com.ibm.icu.util;\r
9 \r
10 import java.io.Serializable;\r
11 import java.util.Date;\r
12 import java.util.Locale;\r
13 import java.util.MissingResourceException;\r
14 \r
15 import com.ibm.icu.impl.Grego;\r
16 import com.ibm.icu.impl.ICUCache;\r
17 import com.ibm.icu.impl.ICUConfig;\r
18 import com.ibm.icu.impl.JavaTimeZone;\r
19 import com.ibm.icu.impl.SimpleCache;\r
20 import com.ibm.icu.impl.TimeZoneAdapter;\r
21 import com.ibm.icu.impl.ZoneMeta;\r
22 import com.ibm.icu.text.SimpleDateFormat;\r
23 \r
24 /**\r
25  * <code>TimeZone</code> represents a time zone offset, and also figures out daylight\r
26  * savings.\r
27  *\r
28  * <p>\r
29  * Typically, you get a <code>TimeZone</code> using <code>getDefault</code>\r
30  * which creates a <code>TimeZone</code> based on the time zone where the program\r
31  * is running. For example, for a program running in Japan, <code>getDefault</code>\r
32  * creates a <code>TimeZone</code> object based on Japanese Standard Time.\r
33  *\r
34  * <p>\r
35  * You can also get a <code>TimeZone</code> using <code>getTimeZone</code>\r
36  * along with a time zone ID. For instance, the time zone ID for the\r
37  * U.S. Pacific Time zone is "America/Los_Angeles". So, you can get a\r
38  * U.S. Pacific Time <code>TimeZone</code> object with:\r
39  * <blockquote>\r
40  * <pre>\r
41  * TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");\r
42  * </pre>\r
43  * </blockquote>\r
44  * You can use <code>getAvailableIDs</code> method to iterate through\r
45  * all the supported time zone IDs. You can then choose a\r
46  * supported ID to get a <code>TimeZone</code>.\r
47  * If the time zone you want is not represented by one of the\r
48  * supported IDs, then you can create a custom time zone ID with\r
49  * the following syntax:\r
50  *\r
51  * <blockquote>\r
52  * <pre>\r
53  * GMT[+|-]hh[[:]mm]\r
54  * </pre>\r
55  * </blockquote>\r
56  *\r
57  * For example, you might specify GMT+14:00 as a custom\r
58  * time zone ID.  The <code>TimeZone</code> that is returned\r
59  * when you specify a custom time zone ID does not include\r
60  * daylight savings time.\r
61  * <p>\r
62  * For compatibility with JDK 1.1.x, some other three-letter time zone IDs\r
63  * (such as "PST", "CTT", "AST") are also supported. However, <strong>their\r
64  * use is deprecated</strong> because the same abbreviation is often used\r
65  * for multiple time zones (for example, "CST" could be U.S. "Central Standard\r
66  * Time" and "China Standard Time"), and the Java platform can then only\r
67  * recognize one of them.\r
68  *\r
69  * <p><strong>Note:</strong> Starting from ICU4J 4.0, you can optionally choose\r
70  * JDK <code>TimeZone</code> as the time zone implementation.  The TimeZone factory\r
71  * method <code>getTimeZone</code> creates an instance of ICU's own <code>TimeZone</code>\r
72  * subclass by default.  If you want to use the JDK implementation always, you can\r
73  * set the default time zone implementation type by the new method\r
74  * <code>setDefaultTimeZoneType</code>.  Alternatively, you can change the initial\r
75  * default implementation type by setting a property below.\r
76  * \r
77  * <blockquote>\r
78  * <pre>\r
79  * #\r
80  * # The default TimeZone implementation type used by the ICU TimeZone\r
81  * # factory method. [ ICU | JDK ]\r
82  * #\r
83  * com.ibm.icu.util.TimeZone.DefaultTimeZoneType = ICU\r
84  * </pre>\r
85  * </blockquote>\r
86  *\r
87  * <p>This property is included in ICUConfig.properties in com.ibm.icu package.\r
88  * When <code>TimeZone</code> class is loaded, the initialization code checks\r
89  * if the property <code>com.ibm.icu.util.TimeZone.DefaultTimeZoneType=xxx</code>\r
90  * is defined by the system properties.  If not available, then it loads ICUConfig.properties\r
91  * to get the default time zone implementation type.  The property setting is\r
92  * only used for the initial default value and you can change the default type\r
93  * by <code>setDefaultTimeZoneType</code> at runtime.\r
94  *\r
95  * @see          Calendar\r
96  * @see          GregorianCalendar\r
97  * @see          SimpleTimeZone\r
98  * @author       Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu\r
99  * @stable ICU 2.0\r
100  */\r
101 abstract public class TimeZone implements Serializable, Cloneable {\r
102     // using serialver from jdk1.4.2_05\r
103     private static final long serialVersionUID = -744942128318337471L;\r
104 \r
105     /**\r
106      * Default constructor.  (For invocation by subclass constructors,\r
107      * typically implicit.)\r
108      * @stable ICU 2.8\r
109      */\r
110     public TimeZone() {\r
111     }\r
112 \r
113     /**\r
114      * A time zone implementation type indicating ICU's own TimeZone used by\r
115      * <code>getTimeZone</code>, <code>setDefaultTimeZoneType</code>\r
116      * and <code>getDefaultTimeZoneType</code>.\r
117      * @stable ICU 4.0\r
118      */\r
119     public static final int TIMEZONE_ICU = 0;\r
120     /**\r
121      * A time zone implementation type indicating JDK TimeZone used by\r
122      * <code>getTimeZone</code>, <code>setDefaultTimeZoneType</code>\r
123      * and <code>getDefaultTimeZoneType</code>.\r
124      * @stable ICU 4.0\r
125      */\r
126     public static final int TIMEZONE_JDK = 1;\r
127 \r
128     /**\r
129      * A style specifier for <code>getDisplayName()</code> indicating\r
130      * a short name, such as "PST."\r
131      * @see #LONG\r
132      * @stable ICU 2.0\r
133      */\r
134     public static final int SHORT = 0;\r
135 \r
136     /**\r
137      * A style specifier for <code>getDisplayName()</code> indicating\r
138      * a long name, such as "Pacific Standard Time."\r
139      * @see #SHORT\r
140      * @stable ICU 2.0\r
141      */\r
142     public static final int LONG  = 1;\r
143 \r
144     /**\r
145      * @internal\r
146      * @deprecated This API is ICU internal only.\r
147      */\r
148 /*\r
149     private static final int SHORT_GENERIC = 2;\r
150 */\r
151 \r
152     /**\r
153      * @internal\r
154      * @deprecated This API is ICU internal only.\r
155      */\r
156     private static final int LONG_GENERIC = 3;\r
157 \r
158     /**\r
159      * Cache to hold the SimpleDateFormat objects for a Locale.\r
160      */\r
161     private static ICUCache cachedLocaleData = new SimpleCache();\r
162 \r
163     /**\r
164      * Gets the time zone offset, for current date, modified in case of\r
165      * daylight savings. This is the offset to add *to* UTC to get local time.\r
166      * @param era the era of the given date.\r
167      * @param year the year in the given date.\r
168      * @param month the month in the given date.\r
169      * Month is 0-based. e.g., 0 for January.\r
170      * @param day the day-in-month of the given date.\r
171      * @param dayOfWeek the day-of-week of the given date.\r
172      * @param milliseconds the millis in day in <em>standard</em> local time.\r
173      * @return the offset to add *to* GMT to get local time.\r
174      * @stable ICU 2.0\r
175      */\r
176     abstract public int getOffset(int era, int year, int month, int day,\r
177                                   int dayOfWeek, int milliseconds);\r
178 \r
179 \r
180     /**\r
181      * Returns the offset of this time zone from UTC at the specified\r
182      * date. If Daylight Saving Time is in effect at the specified\r
183      * date, the offset value is adjusted with the amount of daylight\r
184      * saving.\r
185      *\r
186      * @param date the date represented in milliseconds since January 1, 1970 00:00:00 GMT\r
187      * @return the amount of time in milliseconds to add to UTC to get local time.\r
188      *\r
189      * @see Calendar#ZONE_OFFSET\r
190      * @see Calendar#DST_OFFSET\r
191      * @see #getOffset(long, boolean, int[])\r
192      * @stable ICU 2.8\r
193      */\r
194     public int getOffset(long date) {\r
195         int[] result = new int[2];\r
196         getOffset(date, false, result);\r
197         return result[0]+result[1];\r
198     }\r
199 \r
200     /**\r
201      * Returns the time zone raw and GMT offset for the given moment\r
202      * in time.  Upon return, local-millis = GMT-millis + rawOffset +\r
203      * dstOffset.  All computations are performed in the proleptic\r
204      * Gregorian calendar.  The default implementation in the TimeZone\r
205      * class delegates to the 8-argument getOffset().\r
206      *\r
207      * @param date moment in time for which to return offsets, in\r
208      * units of milliseconds from January 1, 1970 0:00 GMT, either GMT\r
209      * time or local wall time, depending on `local'.\r
210      * @param local if true, `date' is local wall time; otherwise it\r
211      * is in GMT time.\r
212      * @param offsets output parameter to receive the raw offset, that\r
213      * is, the offset not including DST adjustments, in offsets[0],\r
214      * and the DST offset, that is, the offset to be added to\r
215      * `rawOffset' to obtain the total offset between local and GMT\r
216      * time, in offsets[1]. If DST is not in effect, the DST offset is\r
217      * zero; otherwise it is a positive value, typically one hour.\r
218      *\r
219      * @stable ICU 2.8\r
220      */\r
221     public void getOffset(long date, boolean local, int[] offsets) {\r
222         offsets[0] = getRawOffset();\r
223         if (!local) {\r
224             date += offsets[0]; // now in local standard millis\r
225         }\r
226 \r
227         // When local == true, date might not be in local standard\r
228         // millis.  getOffset taking 6 parameters used here assume\r
229         // the given time in day is local standard time.\r
230         // At STD->DST transition, there is a range of time which\r
231         // does not exist.  When 'date' is in this time range\r
232         // (and local == true), this method interprets the specified\r
233         // local time as DST.  At DST->STD transition, there is a\r
234         // range of time which occurs twice.  In this case, this\r
235         // method interprets the specified local time as STD.\r
236         // To support the behavior above, we need to call getOffset\r
237         // (with 6 args) twice when local == true and DST is\r
238         // detected in the initial call.\r
239         int fields[] = new int[6];\r
240         for (int pass = 0; ; pass++) {\r
241             Grego.timeToFields(date, fields);\r
242             offsets[1] = getOffset(GregorianCalendar.AD,\r
243                                     fields[0], fields[1], fields[2],\r
244                                     fields[3], fields[5]) - offsets[0];\r
245 \r
246             if (pass != 0 || !local || offsets[1] == 0) {\r
247                 break;\r
248             }\r
249             // adjust to local standard millis\r
250             date -= offsets[1];\r
251         }\r
252     }\r
253 \r
254     /**\r
255      * Sets the base time zone offset to GMT.\r
256      * This is the offset to add *to* UTC to get local time.\r
257      * @param offsetMillis the given base time zone offset to GMT.\r
258      * @stable ICU 2.0\r
259      */\r
260     abstract public void setRawOffset(int offsetMillis);\r
261 \r
262     /**\r
263      * Gets unmodified offset, NOT modified in case of daylight savings.\r
264      * This is the offset to add *to* UTC to get local time.\r
265      * @return the unmodified offset to add *to* UTC to get local time.\r
266      * @stable ICU 2.0\r
267      */\r
268     abstract public int getRawOffset();\r
269 \r
270     /**\r
271      * Gets the ID of this time zone.\r
272      * @return the ID of this time zone.\r
273      * @stable ICU 2.0\r
274      */\r
275     public String getID() {\r
276         return ID;\r
277     }\r
278 \r
279     /**\r
280      * Sets the time zone ID. This does not change any other data in\r
281      * the time zone object.\r
282      * @param ID the new time zone ID.\r
283      * @stable ICU 2.0\r
284      */\r
285     public void setID(String ID) {\r
286         if (ID == null) {\r
287             throw new NullPointerException();\r
288         }\r
289         this.ID = ID;\r
290     }\r
291 \r
292     /**\r
293      * Returns a name of this time zone suitable for presentation to the user\r
294      * in the default locale.\r
295      * This method returns the long generic name.\r
296      * If the display name is not available for the locale,\r
297      * a fallback based on the country, city, or time zone id will be used.\r
298      * @return the human-readable name of this time zone in the default locale.\r
299      * @stable ICU 2.0\r
300      */\r
301     public final String getDisplayName() {\r
302         return _getDisplayName(false, LONG_GENERIC, ULocale.getDefault());\r
303     }\r
304 \r
305     /**\r
306      * Returns a name of this time zone suitable for presentation to the user\r
307      * in the specified locale.\r
308      * This method returns the long generic name.\r
309      * If the display name is not available for the locale,\r
310      * a fallback based on the country, city, or time zone id will be used.\r
311      * @param locale the locale in which to supply the display name.\r
312      * @return the human-readable name of this time zone in the given locale\r
313      * or in the default locale if the given locale is not recognized.\r
314      * @stable ICU 2.0\r
315      */\r
316     public final String getDisplayName(Locale locale) {\r
317         return _getDisplayName(false, LONG_GENERIC, ULocale.forLocale(locale));\r
318     }\r
319 \r
320     /**\r
321      * Returns a name of this time zone suitable for presentation to the user\r
322      * in the specified locale.\r
323      * This method returns the long name, not including daylight savings.\r
324      * If the display name is not available for the locale,\r
325      * a fallback based on the country, city, or time zone id will be used.\r
326      * @param locale the ulocale in which to supply the display name.\r
327      * @return the human-readable name of this time zone in the given locale\r
328      * or in the default ulocale if the given ulocale is not recognized.\r
329      * @stable ICU 3.2\r
330      */\r
331     public final String getDisplayName(ULocale locale) {\r
332         return _getDisplayName(false, LONG_GENERIC, locale);\r
333     }\r
334 \r
335     /**\r
336      * Returns a name of this time zone suitable for presentation to the user\r
337      * in the default locale.\r
338      * If the display name is not available for the locale,\r
339      * then this method returns a string in the format\r
340      * <code>GMT[+-]hh:mm</code>.\r
341      * @param daylight if true, return the daylight savings name.\r
342      * @param style either <code>LONG</code> or <code>SHORT</code>\r
343      * @return the human-readable name of this time zone in the default locale.\r
344      * @stable ICU 2.0\r
345      */\r
346     public final String getDisplayName(boolean daylight, int style) {\r
347         return getDisplayName(daylight, style, ULocale.getDefault());\r
348     }\r
349 \r
350     /**\r
351      * Returns a name of this time zone suitable for presentation to the user\r
352      * in the specified locale.\r
353      * If the display name is not available for the locale,\r
354      * then this method returns a string in the format\r
355      * <code>GMT[+-]hh:mm</code>.\r
356      * @param daylight if true, return the daylight savings name.\r
357      * @param style either <code>LONG</code> or <code>SHORT</code>\r
358      * @param locale the locale in which to supply the display name.\r
359      * @return the human-readable name of this time zone in the given locale\r
360      * or in the default locale if the given locale is not recognized.\r
361      * @exception IllegalArgumentException style is invalid.\r
362      * @stable ICU 2.0\r
363      */\r
364     public String getDisplayName(boolean daylight, int style, Locale locale) {\r
365         return getDisplayName(daylight, style, ULocale.forLocale(locale));\r
366     }\r
367 \r
368     /**\r
369      * Returns a name of this time zone suitable for presentation to the user\r
370      * in the specified locale.\r
371      * If the display name is not available for the locale,\r
372      * then this method returns a string in the format\r
373      * <code>GMT[+-]hh:mm</code>.\r
374      * @param daylight if true, return the daylight savings name.\r
375      * @param style either <code>LONG</code> or <code>SHORT</code>\r
376      * @param locale the locale in which to supply the display name.\r
377      * @return the human-readable name of this time zone in the given locale\r
378      * or in the default locale if the given locale is not recognized.\r
379      * @exception IllegalArgumentException style is invalid.\r
380      * @stable ICU 3.2\r
381      */\r
382     public String getDisplayName(boolean daylight, int style, ULocale locale) {\r
383         if (style != SHORT && style != LONG) {\r
384             throw new IllegalArgumentException("Illegal style: " + style);\r
385         }\r
386         return _getDisplayName(daylight, style, locale);\r
387     }\r
388 \r
389     /**\r
390      * The public version of this API only accepts LONG/SHORT, the\r
391      * internal version (which this calls) also accepts LONG_GENERIC/SHORT_GENERIC.\r
392      */\r
393     private synchronized String _getDisplayName(boolean daylight, int style, ULocale locale) {\r
394         if (locale == null) {\r
395             throw new NullPointerException("locale is null");\r
396         }\r
397 \r
398         /* NOTES:\r
399          * (1) We use SimpleDateFormat for simplicity; we could do this\r
400          * more efficiently but it would duplicate the SimpleDateFormat code\r
401          * here, which is undesirable.\r
402          * (2) Attempts to move the code from SimpleDateFormat to here also run\r
403          * around because this requires SimpleDateFormat to keep a Locale\r
404          * object around, which it currently doesn't; to synthesize such a\r
405          * locale upon resurrection; and to somehow handle the special case of\r
406          * construction from a DateFormatSymbols object.\r
407          */\r
408 \r
409         // We keep a cache, indexed by locale.  The cache contains a\r
410         // SimpleDateFormat object, which we create on demand.\r
411         SimpleDateFormat format = (SimpleDateFormat)cachedLocaleData.get(locale);\r
412         if (format == null) {\r
413             format = new SimpleDateFormat(null, locale);\r
414             cachedLocaleData.put(locale, format);\r
415         }\r
416 \r
417         String[] patterns = { "z", "zzzz", "v", "vvvv" };\r
418         format.applyPattern(patterns[style]);\r
419         format.setTimeZone(this);\r
420         Date d = new Date();\r
421         if (style >= 2) {\r
422             // Generic names may change time to time even for a single time zone.\r
423             // This method returns the one used for the zone now.\r
424             return format.format(d);\r
425         } else {\r
426             int[] offsets = new int[2];\r
427             getOffset(d.getTime(), false, offsets);\r
428             if ((daylight && offsets[1] != 0) || (!daylight && offsets[1] == 0)) {\r
429                 return format.format(d);\r
430             }\r
431 \r
432             // Create a new SimpleTimeZone as a stand-in for this zone; the stand-in\r
433             // will have no DST, or DST during July, but the same ID and offset,\r
434             // and hence the same display name.  We don't cache these because\r
435             // they're small and cheap to create.\r
436             SimpleTimeZone tz;\r
437             if (daylight && useDaylightTime()) {\r
438                 // The display name for daylight saving time was requested, but currently not in DST\r
439 \r
440                 // Set a fixed date (July 1) in this Gregorian year\r
441                 GregorianCalendar cal = new GregorianCalendar(this);\r
442                 cal.set(Calendar.MONTH, Calendar.JULY);\r
443                 cal.set(Calendar.DATE, 1);\r
444 \r
445                 // Get July 1 date\r
446                 d = cal.getTime();\r
447 \r
448                 // Check if it is in DST\r
449                 if (cal.get(Calendar.DST_OFFSET) == 0) {\r
450                     // We need to create a fake time zone\r
451                     tz = new SimpleTimeZone(offsets[0], getID(),\r
452                             Calendar.JUNE, 1, 0, 0,\r
453                             Calendar.AUGUST, 1, 0, 0,\r
454                             getDSTSavings());\r
455                     format.setTimeZone(tz);\r
456                 }\r
457             } else {\r
458                 // The display name for standard time was requested, but currently in DST\r
459                 // or display name for daylight saving time was requested, but this zone no longer\r
460                 // observes DST.\r
461                 tz = new SimpleTimeZone(offsets[0], getID());\r
462                 format.setTimeZone(tz);\r
463             }\r
464             return format.format(d);\r
465         }\r
466     }\r
467 \r
468     /**\r
469      * Returns the amount of time to be added to local standard time\r
470      * to get local wall clock time.\r
471      * <p>\r
472      * The default implementation always returns 3600000 milliseconds\r
473      * (i.e., one hour) if this time zone observes Daylight Saving\r
474      * Time. Otherwise, 0 (zero) is returned.\r
475      * <p>\r
476      * If an underlying TimeZone implementation subclass supports\r
477      * historical Daylight Saving Time changes, this method returns\r
478      * the known latest daylight saving value.\r
479      *\r
480      * @return the amount of saving time in milliseconds\r
481      * @stable ICU 2.8\r
482      */\r
483     public int getDSTSavings() {\r
484         if (useDaylightTime()) {\r
485             return 3600000;\r
486         }\r
487         return 0;\r
488     }\r
489 \r
490     /**\r
491      * Queries if this time zone uses daylight savings time.\r
492      * @return true if this time zone uses daylight savings time,\r
493      * false, otherwise.\r
494      * @stable ICU 2.0\r
495      */\r
496     abstract public boolean useDaylightTime();\r
497 \r
498     /**\r
499      * Queries if the given date is in daylight savings time in\r
500      * this time zone.\r
501      * @param date the given Date.\r
502      * @return true if the given date is in daylight savings time,\r
503      * false, otherwise.\r
504      * @stable ICU 2.0\r
505      */\r
506     abstract public boolean inDaylightTime(Date date);\r
507 \r
508     /**\r
509      * Gets the <code>TimeZone</code> for the given ID.\r
510      *\r
511      * @param ID the ID for a <code>TimeZone</code>, such as "America/Los_Angeles",\r
512      * or a custom ID such as "GMT-8:00". Note that the support of abbreviations,\r
513      * such as "PST", is for JDK 1.1.x compatibility only and full names should be used.\r
514      *\r
515      * @return the specified <code>TimeZone</code>, or the GMT zone if the given ID\r
516      * cannot be understood.\r
517      * @stable ICU 2.0\r
518      */\r
519     public static synchronized TimeZone getTimeZone(String ID) {\r
520         return getTimeZone(ID, TZ_IMPL);\r
521     }\r
522 \r
523     /**\r
524      * Gets the <code>TimeZone</code> for the given ID and the timezone type.\r
525      * @param ID the ID for a <code>TimeZone</code>, such as "America/Los_Angeles",\r
526      * or a custom ID such as "GMT-8:00". Note that the support of abbreviations,\r
527      * such as "PST", is for JDK 1.1.x compatibility only and full names should be used.\r
528      * @param type Time zone type, either <code>TIMEZONE_ICU</code> or <code>TIMEZONE_JDK</code>.\r
529      * @return the specified <code>TimeZone</code>, or the GMT zone if the given ID\r
530      * cannot be understood.\r
531      * @stable ICU 4.0\r
532      */\r
533     public static synchronized TimeZone getTimeZone(String ID, int type) {\r
534         TimeZone result;\r
535         if (type == TIMEZONE_JDK) {\r
536             result = new JavaTimeZone(ID);\r
537         } else {\r
538             /* We first try to lookup the zone ID in our system list.  If this\r
539              * fails, we try to parse it as a custom string GMT[+-]hh:mm.  If\r
540              * all else fails, we return GMT, which is probably not what the\r
541              * user wants, but at least is a functioning TimeZone object.\r
542              *\r
543              * We cannot return NULL, because that would break compatibility\r
544              * with the JDK.\r
545              */\r
546             if(ID==null){\r
547                 throw new NullPointerException();\r
548             }\r
549             result = ZoneMeta.getSystemTimeZone(ID);\r
550 \r
551             if (result == null) {\r
552                 result = ZoneMeta.getCustomTimeZone(ID);\r
553             }\r
554             if (result == null) {\r
555                 result = ZoneMeta.getGMT();\r
556             }\r
557         }\r
558         return result;\r
559     }\r
560 \r
561     /**\r
562      * Sets the default time zone type used by <code>getTimeZone</code>.\r
563      * @param type time zone type, either <code>TIMEZONE_ICU</code> or <code>TIMEZONE_JDK</code>.\r
564      * @stable ICU 4.0\r
565      */\r
566     public static synchronized void setDefaultTimeZoneType(int type) {\r
567         if (type != TIMEZONE_ICU && type != TIMEZONE_JDK) {\r
568             throw new IllegalArgumentException("Invalid timezone type");\r
569         }\r
570         TZ_IMPL = type;\r
571     }\r
572 \r
573     /**\r
574      * Returns the default time zone type currently used.\r
575      * @return The default time zone type, either <code>TIMEZONE_ICU</code> or <code>TIMEZONE_JDK</code>.\r
576      * @stable ICU 4.0\r
577      */\r
578     public static int getDefaultTimeZoneType() {\r
579         return TZ_IMPL;\r
580     }\r
581 \r
582     /**\r
583      * Return a new String array containing all system TimeZone IDs\r
584      * with the given raw offset from GMT.  These IDs may be passed to\r
585      * <code>get()</code> to construct the corresponding TimeZone\r
586      * object.\r
587      * @param rawOffset the offset in milliseconds from GMT\r
588      * @return an array of IDs for system TimeZones with the given\r
589      * raw offset.  If there are none, return a zero-length array.\r
590      * @stable ICU 2.0\r
591      */\r
592     public static String[] getAvailableIDs(int rawOffset) {\r
593         return ZoneMeta.getAvailableIDs(rawOffset);\r
594 \r
595     }\r
596 \r
597 \r
598     /**\r
599      * Return a new String array containing all system TimeZone IDs\r
600      * associated with the given country.  These IDs may be passed to\r
601      * <code>get()</code> to construct the corresponding TimeZone\r
602      * object.\r
603      * @param country a two-letter ISO 3166 country code, or <code>null</code>\r
604      * to return zones not associated with any country\r
605      * @return an array of IDs for system TimeZones in the given\r
606      * country.  If there are none, return a zero-length array.\r
607      * @stable ICU 2.0\r
608      */\r
609     public static String[] getAvailableIDs(String country) {\r
610         return ZoneMeta.getAvailableIDs(country);\r
611     }\r
612 \r
613     /**\r
614      * Return a new String array containing all system TimeZone IDs.\r
615      * These IDs (and only these IDs) may be passed to\r
616      * <code>get()</code> to construct the corresponding TimeZone\r
617      * object.\r
618      * @return an array of all system TimeZone IDs\r
619      * @stable ICU 2.0\r
620      */\r
621     public static String[] getAvailableIDs() {\r
622         return ZoneMeta.getAvailableIDs();\r
623     }\r
624     \r
625     /**\r
626      * Returns the number of IDs in the equivalency group that\r
627      * includes the given ID.  An equivalency group contains zones\r
628      * that have the same GMT offset and rules.\r
629      *\r
630      * <p>The returned count includes the given ID; it is always >= 1\r
631      * for valid IDs.  The given ID must be a system time zone.  If it\r
632      * is not, returns zero.\r
633      * @param id a system time zone ID\r
634      * @return the number of zones in the equivalency group containing\r
635      * 'id', or zero if 'id' is not a valid system ID\r
636      * @see #getEquivalentID\r
637      * @stable ICU 2.0\r
638      */\r
639     public static int countEquivalentIDs(String id) {\r
640         return ZoneMeta.countEquivalentIDs(id);\r
641     }\r
642 \r
643     /**\r
644      * Returns an ID in the equivalency group that\r
645      * includes the given ID.  An equivalency group contains zones\r
646      * that have the same GMT offset and rules.\r
647      *\r
648      * <p>The given index must be in the range 0..n-1, where n is the\r
649      * value returned by <code>countEquivalentIDs(id)</code>.  For\r
650      * some value of 'index', the returned value will be equal to the\r
651      * given id.  If the given id is not a valid system time zone, or\r
652      * if 'index' is out of range, then returns an empty string.\r
653      * @param id a system time zone ID\r
654      * @param index a value from 0 to n-1, where n is the value\r
655      * returned by <code>countEquivalentIDs(id)</code>\r
656      * @return the ID of the index-th zone in the equivalency group\r
657      * containing 'id', or an empty string if 'id' is not a valid\r
658      * system ID or 'index' is out of range\r
659      * @see #countEquivalentIDs\r
660      * @stable ICU 2.0\r
661      */\r
662     public static String getEquivalentID(String id, int index) {\r
663         return ZoneMeta.getEquivalentID(id, index);\r
664     }\r
665 \r
666     /**\r
667      * Gets the default <code>TimeZone</code> for this host.\r
668      * The source of the default <code>TimeZone</code> \r
669      * may vary with implementation.\r
670      * @return a default <code>TimeZone</code>.\r
671      * @stable ICU 2.0\r
672      */\r
673     public static synchronized TimeZone getDefault() {\r
674         if (defaultZone == null) {\r
675             if (TZ_IMPL == TIMEZONE_JDK) {\r
676                 defaultZone = new JavaTimeZone();\r
677             } else {\r
678                 java.util.TimeZone temp = java.util.TimeZone.getDefault();\r
679                 defaultZone = getTimeZone(temp.getID());\r
680             }\r
681         }\r
682         return (TimeZone) defaultZone.clone();\r
683     }\r
684 \r
685     /**\r
686      * Sets the <code>TimeZone</code> that is\r
687      * returned by the <code>getDefault</code> method.  If <code>zone</code>\r
688      * is null, reset the default to the value it had originally when the\r
689      * VM first started.\r
690      * @param tz the new default time zone\r
691      * @stable ICU 2.0\r
692      */\r
693     public static synchronized void setDefault(TimeZone tz) {\r
694         defaultZone = tz;\r
695         java.util.TimeZone jdkZone = null;\r
696         if (defaultZone instanceof JavaTimeZone) {\r
697             jdkZone = ((JavaTimeZone)defaultZone).unwrap();\r
698         } else {\r
699             // Keep java.util.TimeZone default in sync so java.util.Date\r
700             // can interoperate with com.ibm.icu.util classes.\r
701 \r
702             if (tz != null) {\r
703                 if (tz instanceof com.ibm.icu.impl.OlsonTimeZone) {\r
704                     // Because of the lack of APIs supporting historic\r
705                     // zone offset/dst saving in JDK TimeZone,\r
706                     // wrapping ICU TimeZone with JDK TimeZone will\r
707                     // cause historic offset calculation in Calendar/Date.\r
708                     // JDK calendar implementation calls getRawOffset() and\r
709                     // getDSTSavings() when the instance of JDK TimeZone\r
710                     // is not an instance of JDK internal TimeZone subclass\r
711                     // (sun.util.calendar.ZoneInfo).  Ticket#6459\r
712                     String icuID = tz.getID();\r
713                     jdkZone = java.util.TimeZone.getTimeZone(icuID);\r
714                     if (!icuID.equals(jdkZone.getID())) {\r
715                         // JDK does not know the ID..\r
716                         jdkZone = null;\r
717                     }\r
718                 }\r
719                 if (jdkZone == null) {\r
720                     jdkZone = TimeZoneAdapter.wrap(tz);\r
721                 }\r
722             }\r
723         }\r
724         java.util.TimeZone.setDefault(jdkZone);\r
725     }\r
726 \r
727     /**\r
728      * Returns true if this zone has the same rule and offset as another zone.\r
729      * That is, if this zone differs only in ID, if at all.  Returns false\r
730      * if the other zone is null.\r
731      * @param other the <code>TimeZone</code> object to be compared with\r
732      * @return true if the other zone is not null and is the same as this one,\r
733      * with the possible exception of the ID\r
734      * @stable ICU 2.0\r
735      */\r
736     public boolean hasSameRules(TimeZone other) {\r
737         return other != null &&\r
738             getRawOffset() == other.getRawOffset() &&\r
739             useDaylightTime() == other.useDaylightTime();\r
740     }\r
741 \r
742     /**\r
743      * Overrides Cloneable\r
744      * @stable ICU 2.0\r
745      */\r
746     public Object clone() {\r
747         try {\r
748             TimeZone other = (TimeZone) super.clone();\r
749             other.ID = ID;\r
750             return other;\r
751         } catch (CloneNotSupportedException e) {\r
752             throw new IllegalStateException();\r
753         }\r
754     }\r
755 \r
756     /**\r
757      * Return true if obj is a TimeZone with the same class and ID as this.\r
758      * @return true if obj is a TimeZone with the same class and ID as this\r
759      * @param obj the object to compare against\r
760      * @stable ICU 3.6\r
761      */\r
762     public boolean equals(Object obj){\r
763         if (this == obj) return true;\r
764         if (obj == null || getClass() != obj.getClass()) return false;\r
765         return (ID.equals(((TimeZone)obj).ID));\r
766     }\r
767 \r
768     /**\r
769      * Return the hash code.\r
770      * @return the hash code\r
771      * @stable ICU 3.6\r
772      */\r
773     public int hashCode(){\r
774         return ID.hashCode();\r
775     }\r
776 \r
777     /**\r
778      * Returns the time zone data version currently used by ICU.\r
779      * \r
780      * @return the version string, such as "2007f"\r
781      * @throws MissingResourceException if ICU time zone resource bundle\r
782      * is missing or the version information is not available.\r
783      * \r
784      * @stable ICU 3.8\r
785      */\r
786     public static synchronized String getTZDataVersion() {\r
787         if (TZDATA_VERSION == null) {\r
788             UResourceBundle tzbundle = UResourceBundle.getBundleInstance(\r
789                     "com/ibm/icu/impl/data/icudt" + VersionInfo.ICU_DATA_VERSION, "zoneinfo");\r
790             TZDATA_VERSION = tzbundle.getString("TZVersion");\r
791         }\r
792         return TZDATA_VERSION;\r
793     }\r
794 \r
795     /**\r
796      * Returns the canonical system time zone ID or the normalized\r
797      * custom time zone ID for the given time zone ID.\r
798      * @param id The input time zone ID to be canonicalized.\r
799      * @return The canonical system time zone ID or the custom time zone ID\r
800      * in normalized format for the given time zone ID.  When the given time zone ID\r
801      * is neither a known system time zone ID nor a valid custom time zone ID,\r
802      * null is returned.\r
803      * @stable ICU 4.0\r
804      */\r
805     public static String getCanonicalID(String id) {\r
806         return getCanonicalID(id, null);\r
807     }\r
808 \r
809     /**\r
810      * Returns the canonical system time zone ID or the normalized\r
811      * custom time zone ID for the given time zone ID.\r
812      * @param id The input time zone ID to be canonicalized.\r
813      * @param isSystemID When non-null boolean array is specified and\r
814      * the given ID is a known system time zone ID, true is set to <code>isSystemID[0]</code>\r
815      * @return The canonical system time zone ID or the custom time zone ID\r
816      * in normalized format for the given time zone ID.  When the given time zone ID\r
817      * is neither a known system time zone ID nor a valid custom time zone ID,\r
818      * null is returned.\r
819      * @stable ICU 4.0\r
820      */\r
821     public static String getCanonicalID(String id, boolean[] isSystemID) {\r
822         String canonicalID = null;\r
823         boolean systemTzid = false;\r
824         if (id != null && id.length() != 0) {\r
825             canonicalID = ZoneMeta.getCanonicalSystemID(id);\r
826             if (canonicalID != null) {\r
827                 systemTzid = true;\r
828             } else {\r
829                 canonicalID = ZoneMeta.getCustomID(id);\r
830             }\r
831         }\r
832         if (isSystemID != null) {\r
833             isSystemID[0] = systemTzid;\r
834         }\r
835         return canonicalID;\r
836     }\r
837 \r
838     // =======================privates===============================\r
839 \r
840     /**\r
841      * The string identifier of this <code>TimeZone</code>.  This is a\r
842      * programmatic identifier used internally to look up <code>TimeZone</code>\r
843      * objects from the system table and also to map them to their localized\r
844      * display names.  <code>ID</code> values are unique in the system\r
845      * table but may not be for dynamically created zones.\r
846      * @serial\r
847      */\r
848     private String           ID;\r
849 \r
850     /**\r
851      * The default time zone, or null if not set.\r
852      */\r
853     private static TimeZone  defaultZone = null;\r
854 \r
855     /**\r
856      * The tzdata version\r
857      */\r
858     private static String TZDATA_VERSION = null;\r
859 \r
860     /**\r
861      * TimeZone implementation type\r
862      */\r
863     private static int TZ_IMPL = TIMEZONE_ICU;\r
864 \r
865     /**\r
866      * TimeZone implementation type initialization\r
867      */\r
868     private static final String TZIMPL_CONFIG_KEY = "com.ibm.icu.util.TimeZone.DefaultTimeZoneType";\r
869     private static final String TZIMPL_CONFIG_ICU = "ICU";\r
870     private static final String TZIMPL_CONFIG_JDK = "JDK";\r
871 \r
872     static {\r
873         String type = ICUConfig.get(TZIMPL_CONFIG_KEY, TZIMPL_CONFIG_ICU);\r
874         if (type.equalsIgnoreCase(TZIMPL_CONFIG_JDK)) {\r
875             TZ_IMPL = TIMEZONE_JDK;\r
876         }\r
877     }\r
878 }\r
879 \r
880 //eof\r