001 /* java.util.TimeZone
002 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
003 Free Software Foundation, Inc.
004
005 This file is part of GNU Classpath.
006
007 GNU Classpath is free software; you can redistribute it and/or modify
008 it under the terms of the GNU General Public License as published by
009 the Free Software Foundation; either version 2, or (at your option)
010 any later version.
011
012 GNU Classpath is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of
014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 General Public License for more details.
016
017 You should have received a copy of the GNU General Public License
018 along with GNU Classpath; see the file COPYING. If not, write to the
019 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
020 02110-1301 USA.
021
022 Linking this library statically or dynamically with other modules is
023 making a combined work based on this library. Thus, the terms and
024 conditions of the GNU General Public License cover the whole
025 combination.
026
027 As a special exception, the copyright holders of this library give you
028 permission to link this library with independent modules to produce an
029 executable, regardless of the license terms of these independent
030 modules, and to copy and distribute the resulting executable under
031 terms of your choice, provided that you also meet, for each linked
032 independent module, the terms and conditions of the license of that
033 module. An independent module is a module which is not derived from
034 or based on this library. If you modify this library, you may extend
035 this exception to your version of the library, but you are not
036 obligated to do so. If you do not wish to do so, delete this
037 exception statement from your version. */
038
039
040 package java.util;
041
042 import gnu.classpath.SystemProperties;
043 import gnu.java.util.ZoneInfo;
044 import java.io.File;
045 import java.security.AccessController;
046 import java.security.PrivilegedAction;
047 import java.text.DateFormatSymbols;
048
049 /**
050 * This class represents a time zone offset and handles daylight savings.
051 *
052 * You can get the default time zone with <code>getDefault</code>.
053 * This represents the time zone where program is running.
054 *
055 * Another way to create a time zone is <code>getTimeZone</code>, where
056 * you can give an identifier as parameter. For instance, the identifier
057 * of the Central European Time zone is "CET".
058 *
059 * With the <code>getAvailableIDs</code> method, you can get all the
060 * supported time zone identifiers.
061 *
062 * @see Calendar
063 * @see SimpleTimeZone
064 * @author Jochen Hoenicke
065 */
066 public abstract class TimeZone implements java.io.Serializable, Cloneable
067 {
068
069 /**
070 * Constant used to indicate that a short timezone abbreviation should
071 * be returned, such as "EST"
072 */
073 public static final int SHORT = 0;
074
075 /**
076 * Constant used to indicate that a long timezone name should be
077 * returned, such as "Eastern Standard Time".
078 */
079 public static final int LONG = 1;
080
081 /**
082 * The time zone identifier, e.g. PST.
083 */
084 private String ID;
085
086 /**
087 * The default time zone, as returned by getDefault.
088 */
089 private static TimeZone defaultZone0;
090
091 /**
092 * Tries to get the default TimeZone for this system if not already
093 * set. It will call <code>getDefaultTimeZone(String)</code> with
094 * the result of <code>System.getProperty("user.timezone")</code>.
095 * If that fails it calls <code>VMTimeZone.getDefaultTimeZoneId()</code>.
096 * If that also fails GMT is returned.
097 */
098 private static synchronized TimeZone defaultZone()
099 {
100 /* Look up default timezone */
101 if (defaultZone0 == null)
102 {
103 defaultZone0 = (TimeZone) AccessController.doPrivileged
104 (new PrivilegedAction()
105 {
106 public Object run()
107 {
108 TimeZone zone = null;
109
110 // Prefer System property user.timezone.
111 String tzid = System.getProperty("user.timezone");
112 if (tzid != null && !tzid.equals(""))
113 zone = getDefaultTimeZone(tzid);
114
115 // Try platfom specific way.
116 if (zone == null)
117 zone = VMTimeZone.getDefaultTimeZoneId();
118
119 // Fall back on GMT.
120 if (zone == null)
121 zone = getTimeZone ("GMT");
122
123 return zone;
124 }
125 });
126 }
127
128 return defaultZone0;
129 }
130
131 private static final long serialVersionUID = 3581463369166924961L;
132
133 /**
134 * Flag whether zoneinfo data should be used,
135 * otherwise builtin timezone data will be provided.
136 */
137 private static String zoneinfo_dir;
138
139 /**
140 * Cached copy of getAvailableIDs().
141 */
142 private static String[] availableIDs = null;
143
144 /**
145 * JDK 1.1.x compatibility aliases.
146 */
147 private static HashMap aliases0;
148
149 /**
150 * HashMap for timezones by ID.
151 */
152 private static HashMap timezones0;
153 /* initialize this static field lazily to overhead if
154 * it is not needed:
155 */
156 // Package-private to avoid a trampoline.
157 static HashMap timezones()
158 {
159 if (timezones0 == null)
160 {
161 HashMap timezones = new HashMap();
162 timezones0 = timezones;
163
164 zoneinfo_dir = SystemProperties.getProperty("gnu.java.util.zoneinfo.dir");
165 if (zoneinfo_dir != null && !new File(zoneinfo_dir).isDirectory())
166 zoneinfo_dir = null;
167
168 if (zoneinfo_dir != null)
169 {
170 aliases0 = new HashMap();
171
172 // These deprecated aliases for JDK 1.1.x compatibility
173 // should take precedence over data files read from
174 // /usr/share/zoneinfo.
175 aliases0.put("ACT", "Australia/Darwin");
176 aliases0.put("AET", "Australia/Sydney");
177 aliases0.put("AGT", "America/Argentina/Buenos_Aires");
178 aliases0.put("ART", "Africa/Cairo");
179 aliases0.put("AST", "America/Juneau");
180 aliases0.put("BST", "Asia/Colombo");
181 aliases0.put("CAT", "Africa/Gaborone");
182 aliases0.put("CNT", "America/St_Johns");
183 aliases0.put("CST", "CST6CDT");
184 aliases0.put("CTT", "Asia/Brunei");
185 aliases0.put("EAT", "Indian/Comoro");
186 aliases0.put("ECT", "CET");
187 aliases0.put("EST", "EST5EDT");
188 aliases0.put("EST5", "EST5EDT");
189 aliases0.put("IET", "EST5EDT");
190 aliases0.put("IST", "Asia/Calcutta");
191 aliases0.put("JST", "Asia/Seoul");
192 aliases0.put("MIT", "Pacific/Niue");
193 aliases0.put("MST", "MST7MDT");
194 aliases0.put("MST7", "MST7MDT");
195 aliases0.put("NET", "Indian/Mauritius");
196 aliases0.put("NST", "Pacific/Auckland");
197 aliases0.put("PLT", "Indian/Kerguelen");
198 aliases0.put("PNT", "MST7MDT");
199 aliases0.put("PRT", "America/Anguilla");
200 aliases0.put("PST", "PST8PDT");
201 aliases0.put("SST", "Pacific/Ponape");
202 aliases0.put("VST", "Asia/Bangkok");
203 return timezones;
204 }
205
206 TimeZone tz;
207 // Automatically generated by scripts/timezones.pl
208 // XXX - Should we read this data from a file?
209 tz = new SimpleTimeZone(-11000 * 3600, "MIT");
210 timezones0.put("MIT", tz);
211 timezones0.put("Pacific/Apia", tz);
212 timezones0.put("Pacific/Midway", tz);
213 timezones0.put("Pacific/Niue", tz);
214 timezones0.put("Pacific/Pago_Pago", tz);
215 tz = new SimpleTimeZone
216 (-10000 * 3600, "America/Adak",
217 Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
218 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
219 timezones0.put("America/Adak", tz);
220 tz = new SimpleTimeZone(-10000 * 3600, "HST");
221 timezones0.put("HST", tz);
222 timezones0.put("Pacific/Fakaofo", tz);
223 timezones0.put("Pacific/Honolulu", tz);
224 timezones0.put("Pacific/Johnston", tz);
225 timezones0.put("Pacific/Rarotonga", tz);
226 timezones0.put("Pacific/Tahiti", tz);
227 tz = new SimpleTimeZone(-9500 * 3600, "Pacific/Marquesas");
228 timezones0.put("Pacific/Marquesas", tz);
229 tz = new SimpleTimeZone
230 (-9000 * 3600, "AST",
231 Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
232 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
233 timezones0.put("AST", tz);
234 timezones0.put("America/Anchorage", tz);
235 timezones0.put("America/Juneau", tz);
236 timezones0.put("America/Nome", tz);
237 timezones0.put("America/Yakutat", tz);
238 tz = new SimpleTimeZone(-9000 * 3600, "Pacific/Gambier");
239 timezones0.put("Pacific/Gambier", tz);
240 tz = new SimpleTimeZone
241 (-8000 * 3600, "America/Tijuana",
242 Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
243 Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
244 timezones0.put("America/Tijuana", tz);
245 tz = new SimpleTimeZone
246 (-8000 * 3600, "PST",
247 Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
248 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
249 timezones0.put("PST", tz);
250 timezones0.put("PST8PDT", tz);
251 timezones0.put("America/Dawson", tz);
252 timezones0.put("America/Los_Angeles", tz);
253 timezones0.put("America/Vancouver", tz);
254 timezones0.put("America/Whitehorse", tz);
255 timezones0.put("US/Pacific-New", tz);
256 tz = new SimpleTimeZone(-8000 * 3600, "Pacific/Pitcairn");
257 timezones0.put("Pacific/Pitcairn", tz);
258 tz = new SimpleTimeZone
259 (-7000 * 3600, "America/Chihuahua",
260 Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
261 Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
262 timezones0.put("America/Chihuahua", tz);
263 timezones0.put("America/Mazatlan", tz);
264 tz = new SimpleTimeZone(-7000 * 3600, "MST7");
265 timezones0.put("MST7", tz);
266 timezones0.put("PNT", tz);
267 timezones0.put("America/Dawson_Creek", tz);
268 timezones0.put("America/Hermosillo", tz);
269 timezones0.put("America/Phoenix", tz);
270 tz = new SimpleTimeZone
271 (-7000 * 3600, "MST",
272 Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
273 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
274 timezones0.put("MST", tz);
275 timezones0.put("MST7MDT", tz);
276 timezones0.put("America/Boise", tz);
277 timezones0.put("America/Cambridge_Bay", tz);
278 timezones0.put("America/Denver", tz);
279 timezones0.put("America/Edmonton", tz);
280 timezones0.put("America/Inuvik", tz);
281 timezones0.put("America/Shiprock", tz);
282 timezones0.put("America/Yellowknife", tz);
283 tz = new SimpleTimeZone
284 (-6000 * 3600, "America/Cancun",
285 Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
286 Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
287 timezones0.put("America/Cancun", tz);
288 timezones0.put("America/Merida", tz);
289 timezones0.put("America/Mexico_City", tz);
290 timezones0.put("America/Monterrey", tz);
291 tz = new SimpleTimeZone(-6000 * 3600, "America/Belize");
292 timezones0.put("America/Belize", tz);
293 timezones0.put("America/Costa_Rica", tz);
294 timezones0.put("America/El_Salvador", tz);
295 timezones0.put("America/Guatemala", tz);
296 timezones0.put("America/Managua", tz);
297 timezones0.put("America/Regina", tz);
298 timezones0.put("America/Swift_Current", tz);
299 timezones0.put("America/Tegucigalpa", tz);
300 timezones0.put("Pacific/Galapagos", tz);
301 tz = new SimpleTimeZone
302 (-6000 * 3600, "CST",
303 Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
304 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
305 timezones0.put("CST", tz);
306 timezones0.put("CST6CDT", tz);
307 timezones0.put("America/Chicago", tz);
308 timezones0.put("America/Indiana/Knox", tz);
309 timezones0.put("America/Indiana/Petersburg", tz);
310 timezones0.put("America/Indiana/Vincennes", tz);
311 timezones0.put("America/Menominee", tz);
312 timezones0.put("America/North_Dakota/Center", tz);
313 timezones0.put("America/North_Dakota/New_Salem", tz);
314 timezones0.put("America/Rainy_River", tz);
315 timezones0.put("America/Rankin_Inlet", tz);
316 timezones0.put("America/Winnipeg", tz);
317 tz = new SimpleTimeZone
318 (-6000 * 3600, "Pacific/Easter",
319 Calendar.OCTOBER, 2, Calendar.SATURDAY, 22000 * 3600,
320 Calendar.MARCH, 2, Calendar.SATURDAY, 22000 * 3600);
321 timezones0.put("Pacific/Easter", tz);
322 tz = new SimpleTimeZone(-5000 * 3600, "EST5");
323 timezones0.put("EST5", tz);
324 timezones0.put("IET", tz);
325 timezones0.put("America/Atikokan", tz);
326 timezones0.put("America/Bogota", tz);
327 timezones0.put("America/Cayman", tz);
328 timezones0.put("America/Eirunepe", tz);
329 timezones0.put("America/Guayaquil", tz);
330 timezones0.put("America/Jamaica", tz);
331 timezones0.put("America/Lima", tz);
332 timezones0.put("America/Panama", tz);
333 timezones0.put("America/Rio_Branco", tz);
334 tz = new SimpleTimeZone
335 (-5000 * 3600, "America/Havana",
336 Calendar.APRIL, 1, Calendar.SUNDAY, 0 * 3600,
337 Calendar.OCTOBER, -1, Calendar.SUNDAY, 1000 * 3600);
338 timezones0.put("America/Havana", tz);
339 tz = new SimpleTimeZone
340 (-5000 * 3600, "America/Grand_Turk",
341 Calendar.APRIL, 1, Calendar.SUNDAY, 0 * 3600,
342 Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600);
343 timezones0.put("America/Grand_Turk", tz);
344 timezones0.put("America/Port-au-Prince", tz);
345 tz = new SimpleTimeZone
346 (-5000 * 3600, "EST",
347 Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
348 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
349 timezones0.put("EST", tz);
350 timezones0.put("EST5EDT", tz);
351 timezones0.put("America/Detroit", tz);
352 timezones0.put("America/Indiana/Indianapolis", tz);
353 timezones0.put("America/Indiana/Marengo", tz);
354 timezones0.put("America/Indiana/Vevay", tz);
355 timezones0.put("America/Iqaluit", tz);
356 timezones0.put("America/Kentucky/Louisville", tz);
357 timezones0.put("America/Kentucky/Monticello", tz);
358 timezones0.put("America/Montreal", tz);
359 timezones0.put("America/Nassau", tz);
360 timezones0.put("America/New_York", tz);
361 timezones0.put("America/Nipigon", tz);
362 timezones0.put("America/Pangnirtung", tz);
363 timezones0.put("America/Thunder_Bay", tz);
364 timezones0.put("America/Toronto", tz);
365 tz = new SimpleTimeZone
366 (-4000 * 3600, "America/Asuncion",
367 Calendar.OCTOBER, 3, Calendar.SUNDAY, 0 * 3600,
368 Calendar.MARCH, 2, Calendar.SUNDAY, 0 * 3600);
369 timezones0.put("America/Asuncion", tz);
370 tz = new SimpleTimeZone(-4000 * 3600, "PRT");
371 timezones0.put("PRT", tz);
372 timezones0.put("America/Anguilla", tz);
373 timezones0.put("America/Antigua", tz);
374 timezones0.put("America/Aruba", tz);
375 timezones0.put("America/Barbados", tz);
376 timezones0.put("America/Blanc-Sablon", tz);
377 timezones0.put("America/Boa_Vista", tz);
378 timezones0.put("America/Caracas", tz);
379 timezones0.put("America/Curacao", tz);
380 timezones0.put("America/Dominica", tz);
381 timezones0.put("America/Grenada", tz);
382 timezones0.put("America/Guadeloupe", tz);
383 timezones0.put("America/Guyana", tz);
384 timezones0.put("America/La_Paz", tz);
385 timezones0.put("America/Manaus", tz);
386 timezones0.put("America/Martinique", tz);
387 timezones0.put("America/Montserrat", tz);
388 timezones0.put("America/Port_of_Spain", tz);
389 timezones0.put("America/Porto_Velho", tz);
390 timezones0.put("America/Puerto_Rico", tz);
391 timezones0.put("America/Santo_Domingo", tz);
392 timezones0.put("America/St_Kitts", tz);
393 timezones0.put("America/St_Lucia", tz);
394 timezones0.put("America/St_Thomas", tz);
395 timezones0.put("America/St_Vincent", tz);
396 timezones0.put("America/Tortola", tz);
397 tz = new SimpleTimeZone
398 (-4000 * 3600, "America/Campo_Grande",
399 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0 * 3600,
400 Calendar.FEBRUARY, -1, Calendar.SUNDAY, 0 * 3600);
401 timezones0.put("America/Campo_Grande", tz);
402 timezones0.put("America/Cuiaba", tz);
403 tz = new SimpleTimeZone
404 (-4000 * 3600, "America/Goose_Bay",
405 Calendar.MARCH, 2, Calendar.SUNDAY, 60000,
406 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 60000);
407 timezones0.put("America/Goose_Bay", tz);
408 tz = new SimpleTimeZone
409 (-4000 * 3600, "America/Glace_Bay",
410 Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
411 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
412 timezones0.put("America/Glace_Bay", tz);
413 timezones0.put("America/Halifax", tz);
414 timezones0.put("America/Moncton", tz);
415 timezones0.put("America/Thule", tz);
416 timezones0.put("Atlantic/Bermuda", tz);
417 tz = new SimpleTimeZone
418 (-4000 * 3600, "America/Santiago",
419 Calendar.OCTOBER, 9, -Calendar.SUNDAY, 0 * 3600,
420 Calendar.MARCH, 9, -Calendar.SUNDAY, 0 * 3600);
421 timezones0.put("America/Santiago", tz);
422 timezones0.put("Antarctica/Palmer", tz);
423 tz = new SimpleTimeZone
424 (-4000 * 3600, "Atlantic/Stanley",
425 Calendar.SEPTEMBER, 1, Calendar.SUNDAY, 2000 * 3600,
426 Calendar.APRIL, 3, Calendar.SUNDAY, 2000 * 3600);
427 timezones0.put("Atlantic/Stanley", tz);
428 tz = new SimpleTimeZone
429 (-3500 * 3600, "CNT",
430 Calendar.MARCH, 2, Calendar.SUNDAY, 60000,
431 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 60000);
432 timezones0.put("CNT", tz);
433 timezones0.put("America/St_Johns", tz);
434 tz = new SimpleTimeZone
435 (-3000 * 3600, "America/Godthab",
436 Calendar.MARCH, 30, -Calendar.SATURDAY, 22000 * 3600,
437 Calendar.OCTOBER, 30, -Calendar.SATURDAY, 23000 * 3600);
438 timezones0.put("America/Godthab", tz);
439 tz = new SimpleTimeZone
440 (-3000 * 3600, "America/Miquelon",
441 Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
442 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
443 timezones0.put("America/Miquelon", tz);
444 tz = new SimpleTimeZone
445 (-3000 * 3600, "America/Montevideo",
446 Calendar.OCTOBER, 1, Calendar.SUNDAY, 2000 * 3600,
447 Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600);
448 timezones0.put("America/Montevideo", tz);
449 tz = new SimpleTimeZone
450 (-3000 * 3600, "America/Sao_Paulo",
451 Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0 * 3600,
452 Calendar.FEBRUARY, -1, Calendar.SUNDAY, 0 * 3600);
453 timezones0.put("America/Sao_Paulo", tz);
454 tz = new SimpleTimeZone(-3000 * 3600, "AGT");
455 timezones0.put("AGT", tz);
456 timezones0.put("America/Araguaina", tz);
457 timezones0.put("America/Argentina/Buenos_Aires", tz);
458 timezones0.put("America/Argentina/Catamarca", tz);
459 timezones0.put("America/Argentina/Cordoba", tz);
460 timezones0.put("America/Argentina/Jujuy", tz);
461 timezones0.put("America/Argentina/La_Rioja", tz);
462 timezones0.put("America/Argentina/Mendoza", tz);
463 timezones0.put("America/Argentina/Rio_Gallegos", tz);
464 timezones0.put("America/Argentina/San_Juan", tz);
465 timezones0.put("America/Argentina/Tucuman", tz);
466 timezones0.put("America/Argentina/Ushuaia", tz);
467 timezones0.put("America/Bahia", tz);
468 timezones0.put("America/Belem", tz);
469 timezones0.put("America/Cayenne", tz);
470 timezones0.put("America/Fortaleza", tz);
471 timezones0.put("America/Maceio", tz);
472 timezones0.put("America/Paramaribo", tz);
473 timezones0.put("America/Recife", tz);
474 timezones0.put("Antarctica/Rothera", tz);
475 tz = new SimpleTimeZone(-2000 * 3600, "America/Noronha");
476 timezones0.put("America/Noronha", tz);
477 timezones0.put("Atlantic/South_Georgia", tz);
478 tz = new SimpleTimeZone
479 (-1000 * 3600, "America/Scoresbysund",
480 Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600,
481 Calendar.OCTOBER, -1, Calendar.SUNDAY, 1000 * 3600);
482 timezones0.put("America/Scoresbysund", tz);
483 timezones0.put("Atlantic/Azores", tz);
484 tz = new SimpleTimeZone(-1000 * 3600, "Atlantic/Cape_Verde");
485 timezones0.put("Atlantic/Cape_Verde", tz);
486 tz = new SimpleTimeZone(0 * 3600, "GMT");
487 timezones0.put("GMT", tz);
488 timezones0.put("UTC", tz);
489 timezones0.put("Africa/Abidjan", tz);
490 timezones0.put("Africa/Accra", tz);
491 timezones0.put("Africa/Bamako", tz);
492 timezones0.put("Africa/Banjul", tz);
493 timezones0.put("Africa/Bissau", tz);
494 timezones0.put("Africa/Casablanca", tz);
495 timezones0.put("Africa/Conakry", tz);
496 timezones0.put("Africa/Dakar", tz);
497 timezones0.put("Africa/El_Aaiun", tz);
498 timezones0.put("Africa/Freetown", tz);
499 timezones0.put("Africa/Lome", tz);
500 timezones0.put("Africa/Monrovia", tz);
501 timezones0.put("Africa/Nouakchott", tz);
502 timezones0.put("Africa/Ouagadougou", tz);
503 timezones0.put("Africa/Sao_Tome", tz);
504 timezones0.put("America/Danmarkshavn", tz);
505 timezones0.put("Atlantic/Reykjavik", tz);
506 timezones0.put("Atlantic/St_Helena", tz);
507 tz = new SimpleTimeZone
508 (0 * 3600, "WET",
509 Calendar.MARCH, -1, Calendar.SUNDAY, 1000 * 3600,
510 Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
511 timezones0.put("WET", tz);
512 timezones0.put("Atlantic/Canary", tz);
513 timezones0.put("Atlantic/Faroe", tz);
514 timezones0.put("Atlantic/Madeira", tz);
515 timezones0.put("Europe/Dublin", tz);
516 timezones0.put("Europe/Guernsey", tz);
517 timezones0.put("Europe/Isle_of_Man", tz);
518 timezones0.put("Europe/Jersey", tz);
519 timezones0.put("Europe/Lisbon", tz);
520 timezones0.put("Europe/London", tz);
521 tz = new SimpleTimeZone(1000 * 3600, "Africa/Algiers");
522 timezones0.put("Africa/Algiers", tz);
523 timezones0.put("Africa/Bangui", tz);
524 timezones0.put("Africa/Brazzaville", tz);
525 timezones0.put("Africa/Douala", tz);
526 timezones0.put("Africa/Kinshasa", tz);
527 timezones0.put("Africa/Lagos", tz);
528 timezones0.put("Africa/Libreville", tz);
529 timezones0.put("Africa/Luanda", tz);
530 timezones0.put("Africa/Malabo", tz);
531 timezones0.put("Africa/Ndjamena", tz);
532 timezones0.put("Africa/Niamey", tz);
533 timezones0.put("Africa/Porto-Novo", tz);
534 tz = new SimpleTimeZone
535 (1000 * 3600, "Africa/Windhoek",
536 Calendar.SEPTEMBER, 1, Calendar.SUNDAY, 2000 * 3600,
537 Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600);
538 timezones0.put("Africa/Windhoek", tz);
539 tz = new SimpleTimeZone
540 (1000 * 3600, "CET",
541 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
542 Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
543 timezones0.put("CET", tz);
544 timezones0.put("ECT", tz);
545 timezones0.put("MET", tz);
546 timezones0.put("Africa/Ceuta", tz);
547 timezones0.put("Africa/Tunis", tz);
548 timezones0.put("Arctic/Longyearbyen", tz);
549 timezones0.put("Atlantic/Jan_Mayen", tz);
550 timezones0.put("Europe/Amsterdam", tz);
551 timezones0.put("Europe/Andorra", tz);
552 timezones0.put("Europe/Belgrade", tz);
553 timezones0.put("Europe/Berlin", tz);
554 timezones0.put("Europe/Bratislava", tz);
555 timezones0.put("Europe/Brussels", tz);
556 timezones0.put("Europe/Budapest", tz);
557 timezones0.put("Europe/Copenhagen", tz);
558 timezones0.put("Europe/Gibraltar", tz);
559 timezones0.put("Europe/Ljubljana", tz);
560 timezones0.put("Europe/Luxembourg", tz);
561 timezones0.put("Europe/Madrid", tz);
562 timezones0.put("Europe/Malta", tz);
563 timezones0.put("Europe/Monaco", tz);
564 timezones0.put("Europe/Oslo", tz);
565 timezones0.put("Europe/Paris", tz);
566 timezones0.put("Europe/Podgorica", tz);
567 timezones0.put("Europe/Prague", tz);
568 timezones0.put("Europe/Rome", tz);
569 timezones0.put("Europe/San_Marino", tz);
570 timezones0.put("Europe/Sarajevo", tz);
571 timezones0.put("Europe/Skopje", tz);
572 timezones0.put("Europe/Stockholm", tz);
573 timezones0.put("Europe/Tirane", tz);
574 timezones0.put("Europe/Vaduz", tz);
575 timezones0.put("Europe/Vatican", tz);
576 timezones0.put("Europe/Vienna", tz);
577 timezones0.put("Europe/Warsaw", tz);
578 timezones0.put("Europe/Zagreb", tz);
579 timezones0.put("Europe/Zurich", tz);
580 tz = new SimpleTimeZone
581 (2000 * 3600, "ART",
582 Calendar.APRIL, -1, Calendar.FRIDAY, 0 * 3600,
583 Calendar.SEPTEMBER, -1, Calendar.THURSDAY, 24000 * 3600);
584 timezones0.put("ART", tz);
585 timezones0.put("Africa/Cairo", tz);
586 tz = new SimpleTimeZone(2000 * 3600, "CAT");
587 timezones0.put("CAT", tz);
588 timezones0.put("Africa/Blantyre", tz);
589 timezones0.put("Africa/Bujumbura", tz);
590 timezones0.put("Africa/Gaborone", tz);
591 timezones0.put("Africa/Harare", tz);
592 timezones0.put("Africa/Johannesburg", tz);
593 timezones0.put("Africa/Kigali", tz);
594 timezones0.put("Africa/Lubumbashi", tz);
595 timezones0.put("Africa/Lusaka", tz);
596 timezones0.put("Africa/Maputo", tz);
597 timezones0.put("Africa/Maseru", tz);
598 timezones0.put("Africa/Mbabane", tz);
599 timezones0.put("Africa/Tripoli", tz);
600 timezones0.put("Asia/Jerusalem", tz);
601 tz = new SimpleTimeZone
602 (2000 * 3600, "Asia/Amman",
603 Calendar.MARCH, -1, Calendar.THURSDAY, 0 * 3600,
604 Calendar.OCTOBER, -1, Calendar.FRIDAY, 1000 * 3600);
605 timezones0.put("Asia/Amman", tz);
606 tz = new SimpleTimeZone
607 (2000 * 3600, "Asia/Beirut",
608 Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600,
609 Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600);
610 timezones0.put("Asia/Beirut", tz);
611 tz = new SimpleTimeZone
612 (2000 * 3600, "Asia/Damascus",
613 Calendar.APRIL, 1, 0, 0 * 3600,
614 Calendar.OCTOBER, 1, 0, 0 * 3600);
615 timezones0.put("Asia/Damascus", tz);
616 tz = new SimpleTimeZone
617 (2000 * 3600, "Asia/Gaza",
618 Calendar.APRIL, 1, 0, 0 * 3600,
619 Calendar.OCTOBER, 3, Calendar.FRIDAY, 0 * 3600);
620 timezones0.put("Asia/Gaza", tz);
621 tz = new SimpleTimeZone
622 (2000 * 3600, "EET",
623 Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600,
624 Calendar.OCTOBER, -1, Calendar.SUNDAY, 4000 * 3600);
625 timezones0.put("EET", tz);
626 timezones0.put("Asia/Istanbul", tz);
627 timezones0.put("Asia/Nicosia", tz);
628 timezones0.put("Europe/Athens", tz);
629 timezones0.put("Europe/Bucharest", tz);
630 timezones0.put("Europe/Chisinau", tz);
631 timezones0.put("Europe/Helsinki", tz);
632 timezones0.put("Europe/Istanbul", tz);
633 timezones0.put("Europe/Kiev", tz);
634 timezones0.put("Europe/Mariehamn", tz);
635 timezones0.put("Europe/Nicosia", tz);
636 timezones0.put("Europe/Riga", tz);
637 timezones0.put("Europe/Simferopol", tz);
638 timezones0.put("Europe/Sofia", tz);
639 timezones0.put("Europe/Tallinn", tz);
640 timezones0.put("Europe/Uzhgorod", tz);
641 timezones0.put("Europe/Vilnius", tz);
642 timezones0.put("Europe/Zaporozhye", tz);
643 tz = new SimpleTimeZone
644 (2000 * 3600, "Europe/Kaliningrad",
645 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
646 Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
647 timezones0.put("Europe/Kaliningrad", tz);
648 timezones0.put("Europe/Minsk", tz);
649 tz = new SimpleTimeZone
650 (3000 * 3600, "Asia/Baghdad",
651 Calendar.APRIL, 1, 0, 3000 * 3600,
652 Calendar.OCTOBER, 1, 0, 4000 * 3600);
653 timezones0.put("Asia/Baghdad", tz);
654 tz = new SimpleTimeZone
655 (3000 * 3600, "Europe/Moscow",
656 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
657 Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
658 timezones0.put("Europe/Moscow", tz);
659 timezones0.put("Europe/Volgograd", tz);
660 tz = new SimpleTimeZone(3000 * 3600, "EAT");
661 timezones0.put("EAT", tz);
662 timezones0.put("Africa/Addis_Ababa", tz);
663 timezones0.put("Africa/Asmara", tz);
664 timezones0.put("Africa/Dar_es_Salaam", tz);
665 timezones0.put("Africa/Djibouti", tz);
666 timezones0.put("Africa/Kampala", tz);
667 timezones0.put("Africa/Khartoum", tz);
668 timezones0.put("Africa/Mogadishu", tz);
669 timezones0.put("Africa/Nairobi", tz);
670 timezones0.put("Antarctica/Syowa", tz);
671 timezones0.put("Asia/Aden", tz);
672 timezones0.put("Asia/Bahrain", tz);
673 timezones0.put("Asia/Kuwait", tz);
674 timezones0.put("Asia/Qatar", tz);
675 timezones0.put("Asia/Riyadh", tz);
676 timezones0.put("Indian/Antananarivo", tz);
677 timezones0.put("Indian/Comoro", tz);
678 timezones0.put("Indian/Mayotte", tz);
679 tz = new SimpleTimeZone(3500 * 3600, "Asia/Tehran");
680 timezones0.put("Asia/Tehran", tz);
681 tz = new SimpleTimeZone
682 (4000 * 3600, "Asia/Baku",
683 Calendar.MARCH, -1, Calendar.SUNDAY, 4000 * 3600,
684 Calendar.OCTOBER, -1, Calendar.SUNDAY, 5000 * 3600);
685 timezones0.put("Asia/Baku", tz);
686 tz = new SimpleTimeZone
687 (4000 * 3600, "Asia/Yerevan",
688 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
689 Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
690 timezones0.put("Asia/Yerevan", tz);
691 timezones0.put("Europe/Samara", tz);
692 tz = new SimpleTimeZone(4000 * 3600, "NET");
693 timezones0.put("NET", tz);
694 timezones0.put("Asia/Dubai", tz);
695 timezones0.put("Asia/Muscat", tz);
696 timezones0.put("Asia/Tbilisi", tz);
697 timezones0.put("Indian/Mahe", tz);
698 timezones0.put("Indian/Mauritius", tz);
699 timezones0.put("Indian/Reunion", tz);
700 tz = new SimpleTimeZone(4500 * 3600, "Asia/Kabul");
701 timezones0.put("Asia/Kabul", tz);
702 tz = new SimpleTimeZone
703 (5000 * 3600, "Asia/Yekaterinburg",
704 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
705 Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
706 timezones0.put("Asia/Yekaterinburg", tz);
707 tz = new SimpleTimeZone(5000 * 3600, "PLT");
708 timezones0.put("PLT", tz);
709 timezones0.put("Asia/Aqtau", tz);
710 timezones0.put("Asia/Aqtobe", tz);
711 timezones0.put("Asia/Ashgabat", tz);
712 timezones0.put("Asia/Dushanbe", tz);
713 timezones0.put("Asia/Karachi", tz);
714 timezones0.put("Asia/Oral", tz);
715 timezones0.put("Asia/Samarkand", tz);
716 timezones0.put("Asia/Tashkent", tz);
717 timezones0.put("Indian/Kerguelen", tz);
718 timezones0.put("Indian/Maldives", tz);
719 tz = new SimpleTimeZone(5500 * 3600, "BST");
720 timezones0.put("BST", tz);
721 timezones0.put("IST", tz);
722 timezones0.put("Asia/Calcutta", tz);
723 timezones0.put("Asia/Colombo", tz);
724 tz = new SimpleTimeZone(5750 * 3600, "Asia/Katmandu");
725 timezones0.put("Asia/Katmandu", tz);
726 tz = new SimpleTimeZone(6000 * 3600, "Antarctica/Mawson");
727 timezones0.put("Antarctica/Mawson", tz);
728 timezones0.put("Antarctica/Vostok", tz);
729 timezones0.put("Asia/Almaty", tz);
730 timezones0.put("Asia/Bishkek", tz);
731 timezones0.put("Asia/Dhaka", tz);
732 timezones0.put("Asia/Qyzylorda", tz);
733 timezones0.put("Asia/Thimphu", tz);
734 timezones0.put("Indian/Chagos", tz);
735 tz = new SimpleTimeZone
736 (6000 * 3600, "Asia/Novosibirsk",
737 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
738 Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
739 timezones0.put("Asia/Novosibirsk", tz);
740 timezones0.put("Asia/Omsk", tz);
741 tz = new SimpleTimeZone(6500 * 3600, "Asia/Rangoon");
742 timezones0.put("Asia/Rangoon", tz);
743 timezones0.put("Indian/Cocos", tz);
744 tz = new SimpleTimeZone(7000 * 3600, "VST");
745 timezones0.put("VST", tz);
746 timezones0.put("Antarctica/Davis", tz);
747 timezones0.put("Asia/Bangkok", tz);
748 timezones0.put("Asia/Jakarta", tz);
749 timezones0.put("Asia/Phnom_Penh", tz);
750 timezones0.put("Asia/Pontianak", tz);
751 timezones0.put("Asia/Saigon", tz);
752 timezones0.put("Asia/Vientiane", tz);
753 timezones0.put("Indian/Christmas", tz);
754 tz = new SimpleTimeZone
755 (7000 * 3600, "Asia/Hovd",
756 Calendar.MARCH, -1, Calendar.SATURDAY, 2000 * 3600,
757 Calendar.SEPTEMBER, -1, Calendar.SATURDAY, 2000 * 3600);
758 timezones0.put("Asia/Hovd", tz);
759 tz = new SimpleTimeZone
760 (7000 * 3600, "Asia/Krasnoyarsk",
761 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
762 Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
763 timezones0.put("Asia/Krasnoyarsk", tz);
764 tz = new SimpleTimeZone(8000 * 3600, "CTT");
765 timezones0.put("CTT", tz);
766 timezones0.put("Antarctica/Casey", tz);
767 timezones0.put("Asia/Brunei", tz);
768 timezones0.put("Asia/Chongqing", tz);
769 timezones0.put("Asia/Harbin", tz);
770 timezones0.put("Asia/Hong_Kong", tz);
771 timezones0.put("Asia/Kashgar", tz);
772 timezones0.put("Asia/Kuala_Lumpur", tz);
773 timezones0.put("Asia/Kuching", tz);
774 timezones0.put("Asia/Macau", tz);
775 timezones0.put("Asia/Makassar", tz);
776 timezones0.put("Asia/Manila", tz);
777 timezones0.put("Asia/Shanghai", tz);
778 timezones0.put("Asia/Singapore", tz);
779 timezones0.put("Asia/Taipei", tz);
780 timezones0.put("Asia/Urumqi", tz);
781 timezones0.put("Australia/Perth", tz);
782 tz = new SimpleTimeZone
783 (8000 * 3600, "Asia/Irkutsk",
784 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
785 Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
786 timezones0.put("Asia/Irkutsk", tz);
787 tz = new SimpleTimeZone
788 (8000 * 3600, "Asia/Ulaanbaatar",
789 Calendar.MARCH, -1, Calendar.SATURDAY, 2000 * 3600,
790 Calendar.SEPTEMBER, -1, Calendar.SATURDAY, 2000 * 3600);
791 timezones0.put("Asia/Ulaanbaatar", tz);
792 tz = new SimpleTimeZone(8750 * 3600, "Australia/Eucla");
793 timezones0.put("Australia/Eucla", tz);
794 tz = new SimpleTimeZone
795 (9000 * 3600, "Asia/Choibalsan",
796 Calendar.MARCH, -1, Calendar.SATURDAY, 2000 * 3600,
797 Calendar.SEPTEMBER, -1, Calendar.SATURDAY, 2000 * 3600);
798 timezones0.put("Asia/Choibalsan", tz);
799 tz = new SimpleTimeZone(9000 * 3600, "JST");
800 timezones0.put("JST", tz);
801 timezones0.put("Asia/Dili", tz);
802 timezones0.put("Asia/Jayapura", tz);
803 timezones0.put("Asia/Pyongyang", tz);
804 timezones0.put("Asia/Seoul", tz);
805 timezones0.put("Asia/Tokyo", tz);
806 timezones0.put("Pacific/Palau", tz);
807 tz = new SimpleTimeZone
808 (9000 * 3600, "Asia/Yakutsk",
809 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
810 Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
811 timezones0.put("Asia/Yakutsk", tz);
812 tz = new SimpleTimeZone
813 (9500 * 3600, "Australia/Adelaide",
814 Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600,
815 Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600);
816 timezones0.put("Australia/Adelaide", tz);
817 timezones0.put("Australia/Broken_Hill", tz);
818 tz = new SimpleTimeZone(9500 * 3600, "ACT");
819 timezones0.put("ACT", tz);
820 timezones0.put("Australia/Darwin", tz);
821 tz = new SimpleTimeZone(10000 * 3600, "Antarctica/DumontDUrville");
822 timezones0.put("Antarctica/DumontDUrville", tz);
823 timezones0.put("Australia/Brisbane", tz);
824 timezones0.put("Australia/Lindeman", tz);
825 timezones0.put("Pacific/Guam", tz);
826 timezones0.put("Pacific/Port_Moresby", tz);
827 timezones0.put("Pacific/Saipan", tz);
828 timezones0.put("Pacific/Truk", tz);
829 tz = new SimpleTimeZone
830 (10000 * 3600, "Asia/Sakhalin",
831 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
832 Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
833 timezones0.put("Asia/Sakhalin", tz);
834 timezones0.put("Asia/Vladivostok", tz);
835 tz = new SimpleTimeZone
836 (10000 * 3600, "Australia/Currie",
837 Calendar.OCTOBER, 1, Calendar.SUNDAY, 2000 * 3600,
838 Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600);
839 timezones0.put("Australia/Currie", tz);
840 timezones0.put("Australia/Hobart", tz);
841 tz = new SimpleTimeZone
842 (10000 * 3600, "AET",
843 Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600,
844 Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600);
845 timezones0.put("AET", tz);
846 timezones0.put("Australia/Melbourne", tz);
847 timezones0.put("Australia/Sydney", tz);
848 tz = new SimpleTimeZone
849 (10500 * 3600, "Australia/Lord_Howe",
850 Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600,
851 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, 500 * 3600);
852 timezones0.put("Australia/Lord_Howe", tz);
853 tz = new SimpleTimeZone
854 (11000 * 3600, "Asia/Magadan",
855 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
856 Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
857 timezones0.put("Asia/Magadan", tz);
858 tz = new SimpleTimeZone(11000 * 3600, "SST");
859 timezones0.put("SST", tz);
860 timezones0.put("Pacific/Efate", tz);
861 timezones0.put("Pacific/Guadalcanal", tz);
862 timezones0.put("Pacific/Kosrae", tz);
863 timezones0.put("Pacific/Noumea", tz);
864 timezones0.put("Pacific/Ponape", tz);
865 tz = new SimpleTimeZone(11500 * 3600, "Pacific/Norfolk");
866 timezones0.put("Pacific/Norfolk", tz);
867 tz = new SimpleTimeZone
868 (12000 * 3600, "NST",
869 Calendar.OCTOBER, 1, Calendar.SUNDAY, 2000 * 3600,
870 Calendar.MARCH, 3, Calendar.SUNDAY, 3000 * 3600);
871 timezones0.put("NST", tz);
872 timezones0.put("Antarctica/McMurdo", tz);
873 timezones0.put("Antarctica/South_Pole", tz);
874 timezones0.put("Pacific/Auckland", tz);
875 tz = new SimpleTimeZone
876 (12000 * 3600, "Asia/Anadyr",
877 Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
878 Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
879 timezones0.put("Asia/Anadyr", tz);
880 timezones0.put("Asia/Kamchatka", tz);
881 tz = new SimpleTimeZone(12000 * 3600, "Pacific/Fiji");
882 timezones0.put("Pacific/Fiji", tz);
883 timezones0.put("Pacific/Funafuti", tz);
884 timezones0.put("Pacific/Kwajalein", tz);
885 timezones0.put("Pacific/Majuro", tz);
886 timezones0.put("Pacific/Nauru", tz);
887 timezones0.put("Pacific/Tarawa", tz);
888 timezones0.put("Pacific/Wake", tz);
889 timezones0.put("Pacific/Wallis", tz);
890 tz = new SimpleTimeZone
891 (12750 * 3600, "Pacific/Chatham",
892 Calendar.OCTOBER, 1, Calendar.SUNDAY, 2750 * 3600,
893 Calendar.MARCH, 3, Calendar.SUNDAY, 3750 * 3600);
894 timezones0.put("Pacific/Chatham", tz);
895 tz = new SimpleTimeZone(13000 * 3600, "Pacific/Enderbury");
896 timezones0.put("Pacific/Enderbury", tz);
897 timezones0.put("Pacific/Tongatapu", tz);
898 tz = new SimpleTimeZone(14000 * 3600, "Pacific/Kiritimati");
899 timezones0.put("Pacific/Kiritimati", tz);
900 }
901 return timezones0;
902 }
903
904 /**
905 * Maps a time zone name (with optional GMT offset and daylight time
906 * zone name) to one of the known time zones. This method called
907 * with the result of <code>System.getProperty("user.timezone")</code>
908 * or <code>getDefaultTimeZoneId()</code>. Note that giving one of
909 * the standard tz data names from ftp://elsie.nci.nih.gov/pub/ is
910 * preferred.
911 * The time zone name can be given as follows:
912 * <code>(standard zone name)[(GMT offset)[(DST zone name)[DST offset]]]
913 * </code>
914 * <p>
915 * If only a (standard zone name) is given (no numbers in the
916 * String) then it gets mapped directly to the TimeZone with that
917 * name, if that fails null is returned.
918 * <p>
919 * Alternately, a POSIX-style TZ string can be given, defining the time zone:
920 * <code>std offset dst offset,date/time,date/time</code>
921 * See the glibc manual, or the man page for <code>tzset</code> for details
922 * of this format.
923 * <p>
924 * A GMT offset is the offset to add to the local time to get GMT.
925 * If a (GMT offset) is included (either in seconds or hours) then
926 * an attempt is made to find a TimeZone name matching both the name
927 * and the offset (that doesn't observe daylight time, if the
928 * timezone observes daylight time then you must include a daylight
929 * time zone name after the offset), if that fails then a TimeZone
930 * with the given GMT offset is returned (whether or not the
931 * TimeZone observes daylight time is ignored), if that also fails
932 * the GMT TimeZone is returned.
933 * <p>
934 * If the String ends with (GMT offset)(daylight time zone name)
935 * then an attempt is made to find a TimeZone with the given name and
936 * GMT offset that also observes (the daylight time zone name is not
937 * currently used in any other way), if that fails a TimeZone with
938 * the given GMT offset that observes daylight time is returned, if
939 * that also fails the GMT TimeZone is returned.
940 * <p>
941 * Examples: In Chicago, the time zone id could be "CST6CDT", but
942 * the preferred name would be "America/Chicago". In Indianapolis
943 * (which does not have Daylight Savings Time) the string could be
944 * "EST5", but the preferred name would be "America/Indianapolis".
945 * The standard time zone name for The Netherlands is "Europe/Amsterdam",
946 * but can also be given as "CET-1CEST".
947 */
948 static TimeZone getDefaultTimeZone(String sysTimeZoneId)
949 {
950 String stdName = null;
951 int stdOffs;
952 int dstOffs;
953 try
954 {
955 int idLength = sysTimeZoneId.length();
956
957 int index = 0;
958 int prevIndex;
959 char c;
960
961 // get std
962 do
963 c = sysTimeZoneId.charAt(index);
964 while (c != '+' && c != '-' && c != ',' && c != ':'
965 && ! Character.isDigit(c) && c != '\0' && ++index < idLength);
966
967 if (index >= idLength)
968 return getTimeZoneInternal(sysTimeZoneId);
969
970 stdName = sysTimeZoneId.substring(0, index);
971 prevIndex = index;
972
973 // get the std offset
974 do
975 c = sysTimeZoneId.charAt(index++);
976 while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c))
977 && index < idLength);
978 if (index < idLength)
979 index--;
980
981 { // convert the dst string to a millis number
982 String offset = sysTimeZoneId.substring(prevIndex, index);
983 prevIndex = index;
984
985 if (offset.charAt(0) == '+' || offset.charAt(0) == '-')
986 stdOffs = parseTime(offset.substring(1));
987 else
988 stdOffs = parseTime(offset);
989
990 if (offset.charAt(0) == '-')
991 stdOffs = -stdOffs;
992
993 // TZ timezone offsets are positive when WEST of the meridian.
994 stdOffs = -stdOffs;
995 }
996
997 // Done yet? (Format: std offset)
998 if (index >= idLength)
999 {
1000 // Do we have an existing timezone with that name and offset?
1001 TimeZone tz = getTimeZoneInternal(stdName);
1002 if (tz != null)
1003 if (tz.getRawOffset() == stdOffs)
1004 return tz;
1005
1006 // Custom then.
1007 return new SimpleTimeZone(stdOffs, stdName);
1008 }
1009
1010 // get dst
1011 do
1012 c = sysTimeZoneId.charAt(index);
1013 while (c != '+' && c != '-' && c != ',' && c != ':'
1014 && ! Character.isDigit(c) && c != '\0' && ++index < idLength);
1015
1016 // Done yet? (Format: std offset dst)
1017 if (index >= idLength)
1018 {
1019 // Do we have an existing timezone with that name and offset
1020 // which has DST?
1021 TimeZone tz = getTimeZoneInternal(stdName);
1022 if (tz != null)
1023 if (tz.getRawOffset() == stdOffs && tz.useDaylightTime())
1024 return tz;
1025
1026 // Custom then.
1027 return new SimpleTimeZone(stdOffs, stdName);
1028 }
1029
1030 // get the dst offset
1031 prevIndex = index;
1032 do
1033 c = sysTimeZoneId.charAt(index++);
1034 while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c))
1035 && index < idLength);
1036 if (index < idLength)
1037 index--;
1038
1039 if (index == prevIndex && (c == ',' || c == ';'))
1040 {
1041 // Missing dst offset defaults to one hour ahead of standard
1042 // time.
1043 dstOffs = stdOffs + 60 * 60 * 1000;
1044 }
1045 else
1046 { // convert the dst string to a millis number
1047 String offset = sysTimeZoneId.substring(prevIndex, index);
1048 prevIndex = index;
1049
1050 if (offset.charAt(0) == '+' || offset.charAt(0) == '-')
1051 dstOffs = parseTime(offset.substring(1));
1052 else
1053 dstOffs = parseTime(offset);
1054
1055 if (offset.charAt(0) == '-')
1056 dstOffs = -dstOffs;
1057
1058 // TZ timezone offsets are positive when WEST of the meridian.
1059 dstOffs = -dstOffs;
1060 }
1061
1062 // Done yet? (Format: std offset dst offset)
1063 // FIXME: We don't support DST without a rule given. Should we?
1064 if (index >= idLength)
1065 {
1066 // Time Zone existing with same name, dst and offsets?
1067 TimeZone tz = getTimeZoneInternal(stdName);
1068 if (tz != null)
1069 if (tz.getRawOffset() == stdOffs && tz.useDaylightTime()
1070 && tz.getDSTSavings() == (dstOffs - stdOffs))
1071 return tz;
1072
1073 return new SimpleTimeZone(stdOffs, stdName);
1074 }
1075
1076 // get the DST rule
1077 if (sysTimeZoneId.charAt(index) == ','
1078 || sysTimeZoneId.charAt(index) == ';')
1079 {
1080 index++;
1081 int offs = index;
1082 while (sysTimeZoneId.charAt(index) != ','
1083 && sysTimeZoneId.charAt(index) != ';')
1084 index++;
1085 String startTime = sysTimeZoneId.substring(offs, index);
1086 index++;
1087 String endTime = sysTimeZoneId.substring(index);
1088
1089 index = startTime.indexOf('/');
1090 int startMillis;
1091 int endMillis;
1092 String startDate;
1093 String endDate;
1094 if (index != -1)
1095 {
1096 startDate = startTime.substring(0, index);
1097 startMillis = parseTime(startTime.substring(index + 1));
1098 }
1099 else
1100 {
1101 startDate = startTime;
1102 // if time isn't given, default to 2:00:00 AM.
1103 startMillis = 2 * 60 * 60 * 1000;
1104 }
1105 index = endTime.indexOf('/');
1106 if (index != -1)
1107 {
1108 endDate = endTime.substring(0, index);
1109 endMillis = parseTime(endTime.substring(index + 1));
1110 }
1111 else
1112 {
1113 endDate = endTime;
1114 // if time isn't given, default to 2:00:00 AM.
1115 endMillis = 2 * 60 * 60 * 1000;
1116 }
1117
1118 int[] start = getDateParams(startDate);
1119 int[] end = getDateParams(endDate);
1120 return new SimpleTimeZone(stdOffs, stdName, start[0], start[1],
1121 start[2], startMillis, end[0], end[1],
1122 end[2], endMillis, (dstOffs - stdOffs));
1123 }
1124 }
1125
1126 // FIXME: Produce a warning here?
1127 catch (IndexOutOfBoundsException _)
1128 {
1129 }
1130 catch (NumberFormatException _)
1131 {
1132 }
1133
1134 return null;
1135 }
1136
1137 /**
1138 * Parses and returns the params for a POSIX TZ date field,
1139 * in the format int[]{ month, day, dayOfWeek }, following the
1140 * SimpleTimeZone constructor rules.
1141 */
1142 private static int[] getDateParams(String date)
1143 {
1144 int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
1145 int month;
1146
1147 if (date.charAt(0) == 'M' || date.charAt(0) == 'm')
1148 {
1149 int day;
1150
1151 // Month, week of month, day of week
1152
1153 // "Mm.w.d". d is between 0 (Sunday) and 6. Week w is
1154 // between 1 and 5; Week 1 is the first week in which day d
1155 // occurs and Week 5 specifies the last d day in the month.
1156 // Month m is between 1 and 12.
1157
1158 month = Integer.parseInt(date.substring(1, date.indexOf('.')));
1159 int week = Integer.parseInt(date.substring(date.indexOf('.') + 1,
1160 date.lastIndexOf('.')));
1161 int dayOfWeek = Integer.parseInt(date.substring(date.lastIndexOf('.')
1162 + 1));
1163 dayOfWeek++; // Java day of week is one-based, Sunday is first day.
1164
1165 if (week == 5)
1166 day = -1; // last day of month is -1 in java, 5 in TZ
1167 else
1168 {
1169 // First day of week starting on or after. For example,
1170 // to specify the second Sunday of April, set month to
1171 // APRIL, day-of-month to 8, and day-of-week to -SUNDAY.
1172 day = (week - 1) * 7 + 1;
1173 dayOfWeek = -dayOfWeek;
1174 }
1175
1176 month--; // Java month is zero-based.
1177 return new int[] { month, day, dayOfWeek };
1178 }
1179
1180 // julian day, either zero-based 0<=n<=365 (incl feb 29)
1181 // or one-based 1<=n<=365 (no feb 29)
1182 int julianDay; // Julian day,
1183
1184 if (date.charAt(0) != 'J' || date.charAt(0) != 'j')
1185 {
1186 julianDay = Integer.parseInt(date.substring(1));
1187 julianDay++; // make 1-based
1188 // Adjust day count to include feb 29.
1189 dayCount = new int[]
1190 {
1191 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
1192 };
1193 }
1194 else
1195 // 1-based julian day
1196 julianDay = Integer.parseInt(date);
1197
1198 int i = 11;
1199 while (i > 0)
1200 if (dayCount[i] < julianDay)
1201 break;
1202 else
1203 i--;
1204 julianDay -= dayCount[i];
1205 month = i;
1206 return new int[] { month, julianDay, 0 };
1207 }
1208
1209 /**
1210 * Parses a time field hh[:mm[:ss]], returning the result
1211 * in milliseconds. No leading sign.
1212 */
1213 private static int parseTime(String time)
1214 {
1215 int millis = 0;
1216 int i = 0;
1217
1218 while (i < time.length())
1219 if (time.charAt(i) == ':')
1220 break;
1221 else
1222 i++;
1223 millis = 60 * 60 * 1000 * Integer.parseInt(time.substring(0, i));
1224 if (i >= time.length())
1225 return millis;
1226
1227 int iprev = ++i;
1228 while (i < time.length())
1229 if (time.charAt(i) == ':')
1230 break;
1231 else
1232 i++;
1233 millis += 60 * 1000 * Integer.parseInt(time.substring(iprev, i));
1234 if (i >= time.length())
1235 return millis;
1236
1237 millis += 1000 * Integer.parseInt(time.substring(++i));
1238 return millis;
1239 }
1240
1241 /**
1242 * Gets the time zone offset, for current date, modified in case of
1243 * daylight savings. This is the offset to add to UTC to get the local
1244 * time.
1245 * @param era the era of the given date
1246 * @param year the year of the given date
1247 * @param month the month of the given date, 0 for January.
1248 * @param day the day of month
1249 * @param dayOfWeek the day of week
1250 * @param milliseconds the millis in the day (in local standard time)
1251 * @return the time zone offset in milliseconds.
1252 */
1253 public abstract int getOffset(int era, int year, int month,
1254 int day, int dayOfWeek, int milliseconds);
1255
1256 /**
1257 * Get the time zone offset for the specified date, modified in case of
1258 * daylight savings. This is the offset to add to UTC to get the local
1259 * time.
1260 * @param date the date represented in millisecends
1261 * since January 1, 1970 00:00:00 GMT.
1262 * @since 1.4
1263 */
1264 public int getOffset(long date)
1265 {
1266 return (inDaylightTime(new Date(date))
1267 ? getRawOffset() + getDSTSavings()
1268 : getRawOffset());
1269 }
1270
1271 /**
1272 * Gets the time zone offset, ignoring daylight savings. This is
1273 * the offset to add to UTC to get the local time.
1274 * @return the time zone offset in milliseconds.
1275 */
1276 public abstract int getRawOffset();
1277
1278 /**
1279 * Sets the time zone offset, ignoring daylight savings. This is
1280 * the offset to add to UTC to get the local time.
1281 * @param offsetMillis the time zone offset to GMT.
1282 */
1283 public abstract void setRawOffset(int offsetMillis);
1284
1285 /**
1286 * Gets the identifier of this time zone. For instance, PST for
1287 * Pacific Standard Time.
1288 * @returns the ID of this time zone.
1289 */
1290 public String getID()
1291 {
1292 return ID;
1293 }
1294
1295 /**
1296 * Sets the identifier of this time zone. For instance, PST for
1297 * Pacific Standard Time.
1298 * @param id the new time zone ID.
1299 * @throws NullPointerException if <code>id</code> is <code>null</code>
1300 */
1301 public void setID(String id)
1302 {
1303 if (id == null)
1304 throw new NullPointerException();
1305
1306 this.ID = id;
1307 }
1308
1309 /**
1310 * This method returns a string name of the time zone suitable
1311 * for displaying to the user. The string returned will be the long
1312 * description of the timezone in the current locale. The name
1313 * displayed will assume daylight savings time is not in effect.
1314 *
1315 * @return The name of the time zone.
1316 */
1317 public final String getDisplayName()
1318 {
1319 return (getDisplayName(false, LONG, Locale.getDefault()));
1320 }
1321
1322 /**
1323 * This method returns a string name of the time zone suitable
1324 * for displaying to the user. The string returned will be the long
1325 * description of the timezone in the specified locale. The name
1326 * displayed will assume daylight savings time is not in effect.
1327 *
1328 * @param locale The locale for this timezone name.
1329 *
1330 * @return The name of the time zone.
1331 */
1332 public final String getDisplayName(Locale locale)
1333 {
1334 return (getDisplayName(false, LONG, locale));
1335 }
1336
1337 /**
1338 * This method returns a string name of the time zone suitable
1339 * for displaying to the user. The string returned will be of the
1340 * specified type in the current locale.
1341 *
1342 * @param dst Whether or not daylight savings time is in effect.
1343 * @param style <code>LONG</code> for a long name, <code>SHORT</code> for
1344 * a short abbreviation.
1345 *
1346 * @return The name of the time zone.
1347 */
1348 public final String getDisplayName(boolean dst, int style)
1349 {
1350 return (getDisplayName(dst, style, Locale.getDefault()));
1351 }
1352
1353
1354 /**
1355 * This method returns a string name of the time zone suitable
1356 * for displaying to the user. The string returned will be of the
1357 * specified type in the specified locale.
1358 *
1359 * @param dst Whether or not daylight savings time is in effect.
1360 * @param style <code>LONG</code> for a long name, <code>SHORT</code> for
1361 * a short abbreviation.
1362 * @param locale The locale for this timezone name.
1363 *
1364 * @return The name of the time zone.
1365 */
1366 public String getDisplayName(boolean dst, int style, Locale locale)
1367 {
1368 DateFormatSymbols dfs;
1369 try
1370 {
1371 dfs = new DateFormatSymbols(locale);
1372
1373 // The format of the value returned is defined by us.
1374 String[][]zoneinfo = dfs.getZoneStrings();
1375 for (int i = 0; i < zoneinfo.length; i++)
1376 {
1377 if (zoneinfo[i][0].equals(getID()))
1378 {
1379 if (!dst)
1380 {
1381 if (style == SHORT)
1382 return (zoneinfo[i][2]);
1383 else
1384 return (zoneinfo[i][1]);
1385 }
1386 else
1387 {
1388 if (style == SHORT)
1389 return (zoneinfo[i][4]);
1390 else
1391 return (zoneinfo[i][3]);
1392 }
1393 }
1394 }
1395 }
1396 catch (MissingResourceException e)
1397 {
1398 }
1399
1400 return getDefaultDisplayName(dst);
1401 }
1402
1403 private String getDefaultDisplayName(boolean dst)
1404 {
1405 int offset = getRawOffset() + (dst ? getDSTSavings() : 0);
1406
1407 StringBuffer sb = new StringBuffer(9);
1408 sb.append("GMT");
1409
1410 offset = offset / (1000 * 60);
1411 int hours = Math.abs(offset) / 60;
1412 int minutes = Math.abs(offset) % 60;
1413
1414 if (minutes != 0 || hours != 0)
1415 {
1416 sb.append(offset >= 0 ? '+' : '-');
1417 sb.append((char) ('0' + hours / 10));
1418 sb.append((char) ('0' + hours % 10));
1419 sb.append(':');
1420 sb.append((char) ('0' + minutes / 10));
1421 sb.append((char) ('0' + minutes % 10));
1422 }
1423
1424 return sb.toString();
1425 }
1426
1427 /**
1428 * Returns true, if this time zone uses Daylight Savings Time.
1429 */
1430 public abstract boolean useDaylightTime();
1431
1432 /**
1433 * Returns true, if the given date is in Daylight Savings Time in this
1434 * time zone.
1435 * @param date the given Date.
1436 */
1437 public abstract boolean inDaylightTime(Date date);
1438
1439 /**
1440 * Gets the daylight savings offset. This is a positive offset in
1441 * milliseconds with respect to standard time. Typically this
1442 * is one hour, but for some time zones this may be half an our.
1443 * <p>The default implementation returns 3600000 milliseconds
1444 * (one hour) if the time zone uses daylight savings time
1445 * (as specified by {@link #useDaylightTime()}), otherwise
1446 * it returns 0.
1447 * @return the daylight savings offset in milliseconds.
1448 * @since 1.4
1449 */
1450 public int getDSTSavings ()
1451 {
1452 return useDaylightTime () ? 3600000 : 0;
1453 }
1454
1455 /**
1456 * Gets the TimeZone for the given ID.
1457 * @param ID the time zone identifier.
1458 * @return The time zone for the identifier or GMT, if no such time
1459 * zone exists.
1460 */
1461 private static TimeZone getTimeZoneInternal(String ID)
1462 {
1463 // First check timezones hash
1464 TimeZone tz = null;
1465 TimeZone tznew = null;
1466 for (int pass = 0; pass < 2; pass++)
1467 {
1468 synchronized (TimeZone.class)
1469 {
1470 tz = (TimeZone) timezones().get(ID);
1471 if (tz != null)
1472 {
1473 if (!tz.getID().equals(ID))
1474 {
1475 // We always return a timezone with the requested ID.
1476 // This is the same behaviour as with JDK1.2.
1477 tz = (TimeZone) tz.clone();
1478 tz.setID(ID);
1479 // We also save the alias, so that we return the same
1480 // object again if getTimeZone is called with the same
1481 // alias.
1482 timezones().put(ID, tz);
1483 }
1484 return tz;
1485 }
1486 else if (tznew != null)
1487 {
1488 timezones().put(ID, tznew);
1489 return tznew;
1490 }
1491 }
1492
1493 if (pass == 1 || zoneinfo_dir == null)
1494 return null;
1495
1496 // aliases0 is never changing after first timezones(), so should
1497 // be safe without synchronization.
1498 String zonename = (String) aliases0.get(ID);
1499 if (zonename == null)
1500 zonename = ID;
1501
1502 // Read the file outside of the critical section, it is expensive.
1503 tznew = ZoneInfo.readTZFile (ID, zoneinfo_dir
1504 + File.separatorChar + zonename);
1505 if (tznew == null)
1506 return null;
1507 }
1508
1509 return null;
1510 }
1511
1512 /**
1513 * Gets the TimeZone for the given ID.
1514 * @param ID the time zone identifier.
1515 * @return The time zone for the identifier or GMT, if no such time
1516 * zone exists.
1517 */
1518 public static TimeZone getTimeZone(String ID)
1519 {
1520 // Check for custom IDs first
1521 if (ID.startsWith("GMT") && ID.length() > 3)
1522 {
1523 int pos = 3;
1524 int offset_direction = 1;
1525
1526 if (ID.charAt(pos) == '-')
1527 {
1528 offset_direction = -1;
1529 pos++;
1530 }
1531 else if (ID.charAt(pos) == '+')
1532 {
1533 pos++;
1534 }
1535
1536 try
1537 {
1538 int hour, minute;
1539
1540 String offset_str = ID.substring(pos);
1541 int idx = offset_str.indexOf(":");
1542 if (idx != -1)
1543 {
1544 hour = Integer.parseInt(offset_str.substring(0, idx));
1545 minute = Integer.parseInt(offset_str.substring(idx + 1));
1546 }
1547 else
1548 {
1549 int offset_length = offset_str.length();
1550 if (offset_length <= 2)
1551 {
1552 // Only hour
1553 hour = Integer.parseInt(offset_str);
1554 minute = 0;
1555 }
1556 else
1557 {
1558 // hour and minute, not separated by colon
1559 hour = Integer.parseInt
1560 (offset_str.substring(0, offset_length - 2));
1561 minute = Integer.parseInt
1562 (offset_str.substring(offset_length - 2));
1563 }
1564 }
1565
1566 // Custom IDs have to be normalized
1567 StringBuffer sb = new StringBuffer(9);
1568 sb.append("GMT");
1569
1570 sb.append(offset_direction >= 0 ? '+' : '-');
1571 sb.append((char) ('0' + hour / 10));
1572 sb.append((char) ('0' + hour % 10));
1573 sb.append(':');
1574 sb.append((char) ('0' + minute / 10));
1575 sb.append((char) ('0' + minute % 10));
1576 ID = sb.toString();
1577
1578 return new SimpleTimeZone((hour * (60 * 60 * 1000)
1579 + minute * (60 * 1000))
1580 * offset_direction, ID);
1581 }
1582 catch (NumberFormatException e)
1583 {
1584 }
1585 }
1586
1587 TimeZone tz = getTimeZoneInternal(ID);
1588 if (tz != null)
1589 return tz;
1590
1591 return new SimpleTimeZone(0, "GMT");
1592 }
1593
1594 /**
1595 * Gets the available IDs according to the given time zone
1596 * offset.
1597 * @param rawOffset the given time zone GMT offset.
1598 * @return An array of IDs, where the time zone has the specified GMT
1599 * offset. For example <code>{"Phoenix", "Denver"}</code>, since both have
1600 * GMT-07:00, but differ in daylight savings behaviour.
1601 */
1602 public static String[] getAvailableIDs(int rawOffset)
1603 {
1604 synchronized (TimeZone.class)
1605 {
1606 HashMap h = timezones();
1607 int count = 0;
1608 if (zoneinfo_dir == null)
1609 {
1610 Iterator iter = h.entrySet().iterator();
1611 while (iter.hasNext())
1612 {
1613 // Don't iterate the values, since we want to count
1614 // doubled values (aliases)
1615 Map.Entry entry = (Map.Entry) iter.next();
1616 if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset)
1617 count++;
1618 }
1619
1620 String[] ids = new String[count];
1621 count = 0;
1622 iter = h.entrySet().iterator();
1623 while (iter.hasNext())
1624 {
1625 Map.Entry entry = (Map.Entry) iter.next();
1626 if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset)
1627 ids[count++] = (String) entry.getKey();
1628 }
1629 return ids;
1630 }
1631 }
1632
1633 String[] s = getAvailableIDs();
1634 int count = 0;
1635 for (int i = 0; i < s.length; i++)
1636 {
1637 TimeZone t = getTimeZoneInternal(s[i]);
1638 if (t == null || t.getRawOffset() != rawOffset)
1639 s[i] = null;
1640 else
1641 count++;
1642 }
1643 String[] ids = new String[count];
1644 count = 0;
1645 for (int i = 0; i < s.length; i++)
1646 if (s[i] != null)
1647 ids[count++] = s[i];
1648
1649 return ids;
1650 }
1651
1652 private static int getAvailableIDs(File d, String prefix, ArrayList list)
1653 {
1654 String[] files = d.list();
1655 int count = files.length;
1656 boolean top = prefix.length() == 0;
1657 list.add (files);
1658 for (int i = 0; i < files.length; i++)
1659 {
1660 if (top
1661 && (files[i].equals("posix")
1662 || files[i].equals("right")
1663 || files[i].endsWith(".tab")
1664 || aliases0.get(files[i]) != null))
1665 {
1666 files[i] = null;
1667 count--;
1668 continue;
1669 }
1670
1671 File f = new File(d, files[i]);
1672 if (f.isDirectory())
1673 {
1674 count += getAvailableIDs(f, prefix + files[i]
1675 + File.separatorChar, list) - 1;
1676 files[i] = null;
1677 }
1678 else
1679 files[i] = prefix + files[i];
1680 }
1681 return count;
1682 }
1683
1684 /**
1685 * Gets all available IDs.
1686 * @return An array of all supported IDs.
1687 */
1688 public static String[] getAvailableIDs()
1689 {
1690 synchronized (TimeZone.class)
1691 {
1692 HashMap h = timezones();
1693 if (zoneinfo_dir == null)
1694 return (String[]) h.keySet().toArray(new String[h.size()]);
1695
1696 if (availableIDs != null)
1697 {
1698 String[] ids = new String[availableIDs.length];
1699 for (int i = 0; i < availableIDs.length; i++)
1700 ids[i] = availableIDs[i];
1701 return ids;
1702 }
1703
1704 File d = new File(zoneinfo_dir);
1705 ArrayList list = new ArrayList(30);
1706 int count = getAvailableIDs(d, "", list) + aliases0.size();
1707 availableIDs = new String[count];
1708 String[] ids = new String[count];
1709
1710 count = 0;
1711 for (int i = 0; i < list.size(); i++)
1712 {
1713 String[] s = (String[]) list.get(i);
1714 for (int j = 0; j < s.length; j++)
1715 if (s[j] != null)
1716 {
1717 availableIDs[count] = s[j];
1718 ids[count++] = s[j];
1719 }
1720 }
1721
1722 Iterator iter = aliases0.entrySet().iterator();
1723 while (iter.hasNext())
1724 {
1725 Map.Entry entry = (Map.Entry) iter.next();
1726 availableIDs[count] = (String) entry.getKey();
1727 ids[count++] = (String) entry.getKey();
1728 }
1729
1730 return ids;
1731 }
1732 }
1733
1734 /**
1735 * Returns the time zone under which the host is running. This
1736 * can be changed with setDefault.
1737 *
1738 * @return A clone of the current default time zone for this host.
1739 * @see #setDefault
1740 */
1741 public static TimeZone getDefault()
1742 {
1743 return (TimeZone) defaultZone().clone();
1744 }
1745
1746 public static void setDefault(TimeZone zone)
1747 {
1748 // Hmmmm. No Security checks?
1749 defaultZone0 = zone;
1750 }
1751
1752 /**
1753 * Test if the other time zone uses the same rule and only
1754 * possibly differs in ID. This implementation for this particular
1755 * class will return true if the raw offsets are identical. Subclasses
1756 * should override this method if they use daylight savings.
1757 * @return true if this zone has the same raw offset
1758 */
1759 public boolean hasSameRules(TimeZone other)
1760 {
1761 return other.getRawOffset() == getRawOffset();
1762 }
1763
1764 /**
1765 * Returns a clone of this object. I can't imagine, why this is
1766 * useful for a time zone.
1767 */
1768 public Object clone()
1769 {
1770 try
1771 {
1772 return super.clone();
1773 }
1774 catch (CloneNotSupportedException ex)
1775 {
1776 return null;
1777 }
1778 }
1779 }