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