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