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