KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > text > DateFormatSymbols


1 /*
2  * @(#)DateFormatSymbols.java 1.41 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 /*
9  * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
10  * (C) Copyright IBM Corp. 1996 - All Rights Reserved
11  *
12  * The original version of this source code and documentation is copyrighted
13  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
14  * materials are provided under terms of a License Agreement between Taligent
15  * and Sun. This technology is protected by multiple US and International
16  * patents. This notice and attribution to Taligent may not be removed.
17  * Taligent is a registered trademark of Taligent, Inc.
18  *
19  */

20
21 package java.text;
22 import java.util.Locale JavaDoc;
23 import java.util.ResourceBundle JavaDoc;
24 import java.io.Serializable JavaDoc;
25 import java.lang.ref.SoftReference JavaDoc;
26 import java.util.Vector JavaDoc;
27 import java.util.Enumeration JavaDoc;
28 import sun.text.Utility;
29 import sun.text.resources.LocaleData;
30 import java.util.Hashtable JavaDoc;
31
32 /**
33  * <code>DateFormatSymbols</code> is a public class for encapsulating
34  * localizable date-time formatting data, such as the names of the
35  * months, the names of the days of the week, and the time zone data.
36  * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
37  * <code>DateFormatSymbols</code> to encapsulate this information.
38  *
39  * <p>
40  * Typically you shouldn't use <code>DateFormatSymbols</code> directly.
41  * Rather, you are encouraged to create a date-time formatter with the
42  * <code>DateFormat</code> class's factory methods: <code>getTimeInstance</code>,
43  * <code>getDateInstance</code>, or <code>getDateTimeInstance</code>.
44  * These methods automatically create a <code>DateFormatSymbols</code> for
45  * the formatter so that you don't have to. After the
46  * formatter is created, you may modify its format pattern using the
47  * <code>setPattern</code> method. For more information about
48  * creating formatters using <code>DateFormat</code>'s factory methods,
49  * see {@link DateFormat}.
50  *
51  * <p>
52  * If you decide to create a date-time formatter with a specific
53  * format pattern for a specific locale, you can do so with:
54  * <blockquote>
55  * <pre>
56  * new SimpleDateFormat(aPattern, new DateFormatSymbols(aLocale)).
57  * </pre>
58  * </blockquote>
59  *
60  * <p>
61  * <code>DateFormatSymbols</code> objects are cloneable. When you obtain
62  * a <code>DateFormatSymbols</code> object, feel free to modify the
63  * date-time formatting data. For instance, you can replace the localized
64  * date-time format pattern characters with the ones that you feel easy
65  * to remember. Or you can change the representative cities
66  * to your favorite ones.
67  *
68  * <p>
69  * New <code>DateFormatSymbols</code> subclasses may be added to support
70  * <code>SimpleDateFormat</code> for date-time formatting for additional locales.
71
72  * @see DateFormat
73  * @see SimpleDateFormat
74  * @see java.util.SimpleTimeZone
75  * @version 1.41 12/19/03
76  * @author Chen-Lieh Huang
77  */

78 public class DateFormatSymbols implements Serializable JavaDoc, Cloneable JavaDoc {
79
80     /**
81      * Construct a DateFormatSymbols object by loading format data from
82      * resources for the default locale.
83      *
84      * @exception java.util.MissingResourceException
85      * if the resources for the default locale cannot be
86      * found or cannot be loaded.
87      */

88     public DateFormatSymbols()
89     {
90         initializeData(Locale.getDefault());
91     }
92
93     /**
94      * Construct a DateFormatSymbols object by loading format data from
95      * resources for the given locale.
96      *
97      * @exception java.util.MissingResourceException
98      * if the resources for the specified locale cannot be
99      * found or cannot be loaded.
100      */

101     public DateFormatSymbols(Locale JavaDoc locale)
102     {
103         initializeData(locale);
104     }
105
106     /**
107      * Era strings. For example: "AD" and "BC". An array of 2 strings,
108      * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
109      * @serial
110      */

111     String JavaDoc eras[] = null;
112
113     /**
114      * Month strings. For example: "January", "February", etc. An array
115      * of 13 strings (some calendars have 13 months), indexed by
116      * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.
117      * @serial
118      */

119     String JavaDoc months[] = null;
120
121     /**
122      * Short month strings. For example: "Jan", "Feb", etc. An array of
123      * 13 strings (some calendars have 13 months), indexed by
124      * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.
125
126      * @serial
127      */

128     String JavaDoc shortMonths[] = null;
129
130     /**
131      * Weekday strings. For example: "Sunday", "Monday", etc. An array
132      * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
133      * <code>Calendar.MONDAY</code>, etc.
134      * The element <code>weekdays[0]</code> is ignored.
135      * @serial
136      */

137     String JavaDoc weekdays[] = null;
138
139     /**
140      * Short weekday strings. For example: "Sun", "Mon", etc. An array
141      * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
142      * <code>Calendar.MONDAY</code>, etc.
143      * The element <code>shortWeekdays[0]</code> is ignored.
144      * @serial
145      */

146     String JavaDoc shortWeekdays[] = null;
147
148     /**
149      * AM and PM strings. For example: "AM" and "PM". An array of
150      * 2 strings, indexed by <code>Calendar.AM</code> and
151      * <code>Calendar.PM</code>.
152      * @serial
153      */

154     String JavaDoc ampms[] = null;
155
156     /**
157      * Localized names of time zones in this locale. This is a
158      * two-dimensional array of strings of size <em>n</em> by <em>m</em>,
159      * where <em>m</em> is at least 5. Each of the <em>n</em> rows is an
160      * entry containing the localized names for a single <code>TimeZone</code>.
161      * Each such row contains (with <code>i</code> ranging from
162      * 0..<em>n</em>-1):
163      * <ul>
164      * <li><code>zoneStrings[i][0]</code> - time zone ID</li>
165      * <li><code>zoneStrings[i][1]</code> - long name of zone in standard
166      * time</li>
167      * <li><code>zoneStrings[i][2]</code> - short name of zone in
168      * standard time</li>
169      * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight
170      * savings time</li>
171      * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight
172      * savings time</li>
173      * </ul>
174      * The zone ID is <em>not</em> localized; it corresponds to the ID
175      * value associated with a system time zone object. All other entries
176      * are localized names. If a zone does not implement daylight savings
177      * time, the daylight savings time names are ignored.
178      * @see java.util.TimeZone
179      * @serial
180      */

181     String JavaDoc zoneStrings[][] = null;
182
183     /**
184      * Unlocalized date-time pattern characters. For example: 'y', 'd', etc.
185      * All locales use the same these unlocalized pattern characters.
186      */

187     static final String JavaDoc patternChars = "GyMdkHmsSEDFwWahKzZ";
188
189     /**
190      * Localized date-time pattern characters. For example, a locale may
191      * wish to use 'u' rather than 'y' to represent years in its date format
192      * pattern strings.
193      * This string must be exactly 18 characters long, with the index of
194      * the characters described by <code>DateFormat.ERA_FIELD</code>,
195      * <code>DateFormat.YEAR_FIELD</code>, etc. Thus, if the string were
196      * "Xz...", then localized patterns would use 'X' for era and 'z' for year.
197      * @serial
198      */

199     String JavaDoc localPatternChars = null;
200
201     /* use serialVersionUID from JDK 1.1.4 for interoperability */
202     static final long serialVersionUID = -5987973545549424702L;
203
204     /**
205      * Gets era strings. For example: "AD" and "BC".
206      * @return the era strings.
207      */

208     public String JavaDoc[] getEras() {
209         return duplicate(eras);
210     }
211
212     /**
213      * Sets era strings. For example: "AD" and "BC".
214      * @param newEras the new era strings.
215      */

216     public void setEras(String JavaDoc[] newEras) {
217         eras = duplicate(newEras);
218     }
219
220     /**
221      * Gets month strings. For example: "January", "February", etc.
222      * @return the month strings.
223      */

224     public String JavaDoc[] getMonths() {
225         return duplicate(months);
226     }
227
228     /**
229      * Sets month strings. For example: "January", "February", etc.
230      * @param newMonths the new month strings.
231      */

232     public void setMonths(String JavaDoc[] newMonths) {
233         months = duplicate(newMonths);
234     }
235
236     /**
237      * Gets short month strings. For example: "Jan", "Feb", etc.
238      * @return the short month strings.
239      */

240     public String JavaDoc[] getShortMonths() {
241         return duplicate(shortMonths);
242     }
243
244     /**
245      * Sets short month strings. For example: "Jan", "Feb", etc.
246      * @param newShortMonths the new short month strings.
247      */

248     public void setShortMonths(String JavaDoc[] newShortMonths) {
249         shortMonths = duplicate(newShortMonths);
250     }
251
252     /**
253      * Gets weekday strings. For example: "Sunday", "Monday", etc.
254      * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
255      * <code>Calendar.MONDAY</code>, etc. to index the result array.
256      */

257     public String JavaDoc[] getWeekdays() {
258         return duplicate(weekdays);
259     }
260
261     /**
262      * Sets weekday strings. For example: "Sunday", "Monday", etc.
263      * @param newWeekdays the new weekday strings. The array should
264      * be indexed by <code>Calendar.SUNDAY</code>,
265      * <code>Calendar.MONDAY</code>, etc.
266      */

267     public void setWeekdays(String JavaDoc[] newWeekdays) {
268         weekdays = duplicate(newWeekdays);
269     }
270
271     /**
272      * Gets short weekday strings. For example: "Sun", "Mon", etc.
273      * @return the short weekday strings. Use <code>Calendar.SUNDAY</code>,
274      * <code>Calendar.MONDAY</code>, etc. to index the result array.
275      */

276     public String JavaDoc[] getShortWeekdays() {
277         return duplicate(shortWeekdays);
278     }
279
280     /**
281      * Sets short weekday strings. For example: "Sun", "Mon", etc.
282      * @param newShortWeekdays the new short weekday strings. The array should
283      * be indexed by <code>Calendar.SUNDAY</code>,
284      * <code>Calendar.MONDAY</code>, etc.
285      */

286     public void setShortWeekdays(String JavaDoc[] newShortWeekdays) {
287         shortWeekdays = duplicate(newShortWeekdays);
288     }
289
290     /**
291      * Gets ampm strings. For example: "AM" and "PM".
292      * @return the ampm strings.
293      */

294     public String JavaDoc[] getAmPmStrings() {
295         return duplicate(ampms);
296     }
297
298     /**
299      * Sets ampm strings. For example: "AM" and "PM".
300      * @param newAmpms the new ampm strings.
301      */

302     public void setAmPmStrings(String JavaDoc[] newAmpms) {
303         ampms = duplicate(newAmpms);
304     }
305
306     /**
307      * Gets timezone strings.
308      * @return the timezone strings.
309      */

310     public String JavaDoc[][] getZoneStrings() {
311         String JavaDoc[][] aCopy = new String JavaDoc[zoneStrings.length][];
312         for (int i = 0; i < zoneStrings.length; ++i)
313             aCopy[i] = duplicate(zoneStrings[i]);
314         return aCopy;
315     }
316
317     /**
318      * Sets timezone strings.
319      * @param newZoneStrings the new timezone strings.
320      */

321     public void setZoneStrings(String JavaDoc[][] newZoneStrings) {
322         String JavaDoc[][] aCopy = new String JavaDoc[newZoneStrings.length][];
323         for (int i = 0; i < newZoneStrings.length; ++i)
324             aCopy[i] = duplicate(newZoneStrings[i]);
325         zoneStrings = aCopy;
326     }
327
328     /**
329      * Gets localized date-time pattern characters. For example: 'u', 't', etc.
330      * @return the localized date-time pattern characters.
331      */

332     public String JavaDoc getLocalPatternChars() {
333         return new String JavaDoc(localPatternChars);
334     }
335
336     /**
337      * Sets localized date-time pattern characters. For example: 'u', 't', etc.
338      * @param newLocalPatternChars the new localized date-time
339      * pattern characters.
340      */

341     public void setLocalPatternChars(String JavaDoc newLocalPatternChars) {
342         localPatternChars = new String JavaDoc(newLocalPatternChars);
343     }
344
345     /**
346      * Overrides Cloneable
347      */

348     public Object JavaDoc clone()
349     {
350         try
351         {
352             DateFormatSymbols JavaDoc other = (DateFormatSymbols JavaDoc)super.clone();
353             copyMembers(this, other);
354             return other;
355         } catch (CloneNotSupportedException JavaDoc e) {
356             throw new InternalError JavaDoc();
357         }
358     }
359
360     /**
361      * Override hashCode.
362      * Generates a hash code for the DateFormatSymbols object.
363      */

364     public int hashCode() {
365         int hashcode = 0;
366         for (int index = 0; index < this.zoneStrings[0].length; ++index)
367             hashcode ^= this.zoneStrings[0][index].hashCode();
368         return hashcode;
369     }
370
371     /**
372      * Override equals
373      */

374     public boolean equals(Object JavaDoc obj)
375     {
376         if (this == obj) return true;
377         if (obj == null || getClass() != obj.getClass()) return false;
378         DateFormatSymbols JavaDoc that = (DateFormatSymbols JavaDoc) obj;
379         return (Utility.arrayEquals(eras, that.eras)
380                 && Utility.arrayEquals(months, that.months)
381                 && Utility.arrayEquals(shortMonths, that.shortMonths)
382                 && Utility.arrayEquals(weekdays, that.weekdays)
383                 && Utility.arrayEquals(shortWeekdays, that.shortWeekdays)
384                 && Utility.arrayEquals(ampms, that.ampms)
385                 && Utility.arrayEquals(zoneStrings, that.zoneStrings)
386                 && Utility.arrayEquals(localPatternChars,
387                                        that.localPatternChars));
388     }
389
390     // =======================privates===============================
391

392     /**
393      * Useful constant for defining timezone offsets.
394      */

395     static final int millisPerHour = 60*60*1000;
396
397     /**
398      * Cache to hold the LocaleElements and DateFormatZoneData ResourceBundles
399      * of a Locale.
400      */

401     private static Hashtable JavaDoc cachedLocaleData = new Hashtable JavaDoc(3);
402
403     /**
404      * cache to hold time zone localized strings. Keyed by Locale
405      */

406     private static Hashtable JavaDoc cachedZoneData = new Hashtable JavaDoc();
407
408     /**
409      * Look up resource data for the desiredLocale in the cache; update the
410      * cache if necessary.
411      */

412     private ResourceBundle JavaDoc[] cacheLookup(Locale JavaDoc desiredLocale) {
413     ResourceBundle JavaDoc[] rbs = new ResourceBundle JavaDoc[2];
414     SoftReference JavaDoc[] data
415         = (SoftReference JavaDoc[])cachedLocaleData.get(desiredLocale);
416     if (data == null) {
417         rbs[0] = LocaleData.getLocaleElements(desiredLocale);
418         rbs[1] = LocaleData.getDateFormatZoneData(desiredLocale);
419         data = new SoftReference JavaDoc[] { new SoftReference JavaDoc(rbs[0]),
420                          new SoftReference JavaDoc(rbs[1]) };
421         cachedLocaleData.put(desiredLocale, data);
422     } else {
423         ResourceBundle JavaDoc r;
424         if ((r = (ResourceBundle JavaDoc)data[0].get()) == null) {
425         r = LocaleData.getLocaleElements(desiredLocale);
426         data[0] = new SoftReference JavaDoc(r);
427         }
428         rbs[0] = r;
429         if ((r = (ResourceBundle JavaDoc)data[1].get()) == null) {
430         r = LocaleData.getDateFormatZoneData(desiredLocale);
431         data[1] = new SoftReference JavaDoc(r);
432         }
433         rbs[1] = r;
434     }
435     return rbs;
436     }
437
438     /**
439      * Load time zone localized strings. Enumerate all keys (except
440      * "localPatternChars" and "zoneStrings").
441      */

442     private String JavaDoc[][] loadZoneStrings(Locale JavaDoc desiredLocale,
443                        ResourceBundle JavaDoc rsrc)
444     {
445     String JavaDoc[][] zones;
446     SoftReference JavaDoc data = (SoftReference JavaDoc)cachedZoneData.get(desiredLocale);
447     if (data == null || ((zones = (String JavaDoc[][])data.get()) == null)) {
448         Vector JavaDoc vec = new Vector JavaDoc();
449         Enumeration JavaDoc keys = rsrc.getKeys();
450         while(keys.hasMoreElements()) {
451         String JavaDoc key = (String JavaDoc)keys.nextElement();
452         if (!key.equals("localPatternChars") &&
453             !key.equals("zoneStrings")) {
454             vec.add(rsrc.getObject(key));
455         }
456         }
457         zones = new String JavaDoc[vec.size()][];
458         vec.toArray(zones);
459         data = new SoftReference JavaDoc(zones);
460         cachedZoneData.put(desiredLocale, data);
461     }
462     return zones;
463     }
464
465     private void initializeData(Locale JavaDoc desiredLocale)
466     {
467     int i;
468     ResourceBundle JavaDoc[] rbs = cacheLookup(desiredLocale);
469     ResourceBundle JavaDoc resource = rbs[0];
470     ResourceBundle JavaDoc zoneResource = rbs[1];
471
472     // FIXME: cache only ResourceBundle. Hence every time, will do
473
// getObject(). This won't be necessary if the Resource itself
474
// is cached.
475
eras = (String JavaDoc[])resource.getObject("Eras");
476         months = resource.getStringArray("MonthNames");
477         shortMonths = resource.getStringArray("MonthAbbreviations");
478         String JavaDoc[] lWeekdays = resource.getStringArray("DayNames");
479         weekdays = new String JavaDoc[8];
480         weekdays[0] = ""; // 1-based
481
for (i=0; i<lWeekdays.length; i++)
482             weekdays[i+1] = lWeekdays[i];
483         String JavaDoc[] sWeekdays = resource.getStringArray("DayAbbreviations");
484         shortWeekdays = new String JavaDoc[8];
485         shortWeekdays[0] = ""; // 1-based
486
for (i=0; i<sWeekdays.length; i++)
487             shortWeekdays[i+1] = sWeekdays[i];
488         ampms = resource.getStringArray("AmPmMarkers");
489     zoneStrings = (String JavaDoc[][])loadZoneStrings(desiredLocale,
490                           zoneResource);
491         localPatternChars
492             = (String JavaDoc) zoneResource.getObject("localPatternChars");
493     }
494
495     /**
496      * Package private: used by SimpleDateFormat
497      * Gets the index for the given time zone ID to obtain the timezone
498      * strings for formatting. The time zone ID is just for programmatic
499      * lookup. NOT LOCALIZED!!!
500      * @param ID the given time zone ID.
501      * @return the index of the given time zone ID. Returns -1 if
502      * the given time zone ID can't be located in the DateFormatSymbols object.
503      * @see java.util.SimpleTimeZone
504      */

505     final int getZoneIndex (String JavaDoc ID)
506     {
507         for (int index=0; index<zoneStrings.length; index++)
508         {
509             if (ID.equalsIgnoreCase(zoneStrings[index][0])) return index;
510         }
511
512         return -1;
513     }
514
515     /**
516      * Clones an array of Strings.
517      * @param srcArray the source array to be cloned.
518      * @param count the number of elements in the given source array.
519      * @return a cloned array.
520      */

521     private final String JavaDoc[] duplicate(String JavaDoc[] srcArray)
522     {
523         String JavaDoc[] dstArray = new String JavaDoc[srcArray.length];
524         System.arraycopy(srcArray, 0, dstArray, 0, srcArray.length);
525         return dstArray;
526     }
527
528     /**
529      * Clones all the data members from the source DateFormatSymbols to
530      * the target DateFormatSymbols. This is only for subclasses.
531      * @param src the source DateFormatSymbols.
532      * @param dst the target DateFormatSymbols.
533      */

534     private final void copyMembers(DateFormatSymbols JavaDoc src, DateFormatSymbols JavaDoc dst)
535     {
536         dst.eras = duplicate(src.eras);
537         dst.months = duplicate(src.months);
538         dst.shortMonths = duplicate(src.shortMonths);
539         dst.weekdays = duplicate(src.weekdays);
540         dst.shortWeekdays = duplicate(src.shortWeekdays);
541         dst.ampms = duplicate(src.ampms);
542         for (int i = 0; i < dst.zoneStrings.length; ++i)
543             dst.zoneStrings[i] = duplicate(src.zoneStrings[i]);
544         dst.localPatternChars = new String JavaDoc (src.localPatternChars);
545     }
546
547     /**
548      * Compares the equality of the two arrays of String.
549      * @param current this String array.
550      * @param other that String array.
551      */

552     private final boolean equals(String JavaDoc[] current, String JavaDoc[] other)
553     {
554         int count = current.length;
555
556         for (int i = 0; i < count; ++i)
557             if (!current[i].equals(other[i]))
558                 return false;
559         return true;
560     }
561
562 }
563
Popular Tags