]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/classes/core/src/com/ibm/icu/text/DateFormatSymbols.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / classes / core / src / com / ibm / icu / text / DateFormatSymbols.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 1996-2010, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 \r
8 package com.ibm.icu.text;\r
9 \r
10 import java.io.IOException;\r
11 import java.io.ObjectInputStream;\r
12 import java.io.Serializable;\r
13 import java.util.Locale;\r
14 import java.util.MissingResourceException;\r
15 import java.util.ResourceBundle;\r
16 \r
17 import com.ibm.icu.impl.CalendarData;\r
18 import com.ibm.icu.impl.CalendarUtil;\r
19 import com.ibm.icu.impl.ICUCache;\r
20 import com.ibm.icu.impl.ICUResourceBundle;\r
21 import com.ibm.icu.impl.SimpleCache;\r
22 import com.ibm.icu.impl.Utility;\r
23 import com.ibm.icu.impl.ZoneMeta;\r
24 import com.ibm.icu.impl.ZoneStringFormat;\r
25 import com.ibm.icu.util.Calendar;\r
26 import com.ibm.icu.util.ULocale;\r
27 import com.ibm.icu.util.UResourceBundle;\r
28 \r
29 /**\r
30  * {@icuenhanced java.text.DateFormatSymbols}.{@icu _usage_}\r
31  *\r
32  * <p><code>DateFormatSymbols</code> is a public class for encapsulating\r
33  * localizable date-time formatting data, such as the names of the\r
34  * months, the names of the days of the week, and the time zone data.\r
35  * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use\r
36  * <code>DateFormatSymbols</code> to encapsulate this information.\r
37  *\r
38  * <p>Typically you shouldn't use <code>DateFormatSymbols</code> directly.\r
39  * Rather, you are encouraged to create a date-time formatter with the\r
40  * <code>DateFormat</code> class's factory methods: <code>getTimeInstance</code>,\r
41  * <code>getDateInstance</code>, or <code>getDateTimeInstance</code>.\r
42  * These methods automatically create a <code>DateFormatSymbols</code> for\r
43  * the formatter so that you don't have to. After the\r
44  * formatter is created, you may modify its format pattern using the\r
45  * <code>setPattern</code> method. For more information about\r
46  * creating formatters using <code>DateFormat</code>'s factory methods,\r
47  * see {@link DateFormat}.\r
48  *\r
49  * <p>If you decide to create a date-time formatter with a specific\r
50  * format pattern for a specific locale, you can do so with:\r
51  * <blockquote>\r
52  * <pre>\r
53  * new SimpleDateFormat(aPattern, new DateFormatSymbols(aLocale)).\r
54  * </pre>\r
55  * </blockquote>\r
56  *\r
57  * <p><code>DateFormatSymbols</code> objects are clonable. When you obtain\r
58  * a <code>DateFormatSymbols</code> object, feel free to modify the\r
59  * date-time formatting data. For instance, you can replace the localized\r
60  * date-time format pattern characters with the ones that you feel easy\r
61  * to remember. Or you can change the representative cities\r
62  * to your favorite ones.\r
63  *\r
64  * <p>New <code>DateFormatSymbols</code> subclasses may be added to support\r
65  * <code>SimpleDateFormat</code> for date-time formatting for additional locales.\r
66  *\r
67  * @see          DateFormat\r
68  * @see          SimpleDateFormat\r
69  * @see          com.ibm.icu.util.SimpleTimeZone\r
70  * @author       Chen-Lieh Huang\r
71  * @stable ICU 2.0\r
72  */\r
73 public class DateFormatSymbols implements Serializable, Cloneable {\r
74 \r
75     // TODO make sure local pattern char string is 18 characters long,\r
76     // that is, that it encompasses the new 'u' char for\r
77     // EXTENDED_YEAR.  Two options: 1. Make sure resource data is\r
78     // correct; 2. Make code add in 'u' at end if len == 17.\r
79 \r
80     // Constants for context\r
81     /**\r
82      * {@icu} Constant for context.\r
83      * @stable ICU 3.6\r
84      */\r
85     public static final int FORMAT = 0;\r
86 \r
87     /**\r
88      * {@icu} Constant for context.\r
89      * @stable ICU 3.6\r
90      */\r
91     public static final int STANDALONE = 1;\r
92 \r
93     /**\r
94      * {@icu} Constant for context.\r
95      * @internal\r
96      * @deprecated This API is ICU internal only.\r
97      */\r
98     public static final int DT_CONTEXT_COUNT = 2;\r
99 \r
100     // Constants for width\r
101 \r
102     /**\r
103      * {@icu} Constant for width.\r
104      * @stable ICU 3.6\r
105      */\r
106     public static final int ABBREVIATED = 0;\r
107 \r
108     /**\r
109      * {@icu} Constant for width.\r
110      * @stable ICU 3.6\r
111      */\r
112     public static final int WIDE = 1;\r
113 \r
114     /**\r
115      * {@icu} Constant for width.\r
116      * @stable ICU 3.6\r
117      */\r
118     public static final int NARROW = 2;\r
119 \r
120     /**\r
121      * {@icu} Constant for width.\r
122      * @internal\r
123      * @deprecated This API is ICU internal only.\r
124      */\r
125     public static final int DT_WIDTH_COUNT = 3;\r
126 \r
127     /**\r
128      * Constructs a DateFormatSymbols object by loading format data from\r
129      * resources for the default locale.\r
130      *\r
131      * @throws java.util.MissingResourceException if the resources for the default locale\r
132      *          cannot be found or cannot be loaded.\r
133      * @stable ICU 2.0\r
134      */\r
135     public DateFormatSymbols()\r
136     {\r
137         this(ULocale.getDefault());\r
138     }\r
139 \r
140     /**\r
141      * Constructs a DateFormatSymbols object by loading format data from\r
142      * resources for the given locale.\r
143      *\r
144      * @throws java.util.MissingResourceException if the resources for the specified\r
145      *          locale cannot be found or cannot be loaded.\r
146      * @stable ICU 2.0\r
147      */\r
148     public DateFormatSymbols(Locale locale)\r
149     {\r
150         this(ULocale.forLocale(locale));\r
151     }\r
152 \r
153     /**\r
154      * {@icu} Constructs a DateFormatSymbols object by loading format data from\r
155      * resources for the given ulocale.\r
156      *\r
157      * @throws java.util.MissingResourceException if the resources for the specified\r
158      *          locale cannot be found or cannot be loaded.\r
159      * @stable ICU 3.2\r
160      */\r
161     public DateFormatSymbols(ULocale locale)\r
162     {\r
163         initializeData(locale, CalendarUtil.getCalendarType(locale));\r
164     }\r
165 \r
166     /**\r
167      * Returns a DateFormatSymbols instance for the default locale.\r
168      *\r
169      * {@icunote} Unlike <code>java.text.DateFormatSymbols#getInstance</code>,\r
170      * this method simply returns <code>new com.ibm.icu.text.DateFormatSymbols()</code>.\r
171      * ICU does not support <code>DateFormatSymbolsProvider</code> introduced in Java 6\r
172      * or its equivalent implementation for now.\r
173      *\r
174      * @return A DateFormatSymbols instance.\r
175      * @stable ICU 3.8\r
176      */\r
177     public static DateFormatSymbols getInstance() {\r
178         return new DateFormatSymbols();\r
179     }\r
180 \r
181     /**\r
182      * Returns a DateFormatSymbols instance for the given locale.\r
183      *\r
184      * {@icunote} Unlike <code>java.text.DateFormatSymbols#getInstance</code>,\r
185      * this method simply returns <code>new com.ibm.icu.text.DateFormatSymbols(locale)</code>.\r
186      * ICU does not support <code>DateFormatSymbolsProvider</code> introduced in Java 6\r
187      * or its equivalent implementation for now.\r
188      *\r
189      * @param locale the locale.\r
190      * @return A DateFormatSymbols instance.\r
191      * @stable ICU 3.8\r
192      */\r
193     public static DateFormatSymbols getInstance(Locale locale) {\r
194         return new DateFormatSymbols(locale);\r
195     }\r
196 \r
197     /**\r
198      * {@icu} Returns a DateFormatSymbols instance for the given locale.\r
199      *\r
200      * {@icunote} Unlike <code>java.text.DateFormatSymbols#getInstance</code>,\r
201      * this method simply returns <code>new com.ibm.icu.text.DateFormatSymbols(locale)</code>.\r
202      * ICU does not support <code>DateFormatSymbolsProvider</code> introduced in Java 6\r
203      * or its equivalent implementation for now.\r
204      *\r
205      * @param locale the locale.\r
206      * @return A DateFormatSymbols instance.\r
207      * @stable ICU 3.8\r
208      */\r
209     public static DateFormatSymbols getInstance(ULocale locale) {\r
210         return new DateFormatSymbols(locale);\r
211     }\r
212 \r
213     /**\r
214      * Returns an array of all locales for which the <code>getInstance</code> methods of\r
215      * this class can return localized instances.\r
216      *\r
217      * {@icunote} Unlike <code>java.text.DateFormatSymbols#getAvailableLocales</code>,\r
218      * this method simply returns the array of <code>Locale</code>s available in this\r
219      * class.  ICU does not support <code>DateFormatSymbolsProvider</code> introduced in\r
220      * Java 6 or its equivalent implementation for now.\r
221      *\r
222      * @return An array of <code>Locale</code>s for which localized\r
223      * <code>DateFormatSymbols</code> instances are available.\r
224      * @stable ICU 3.8\r
225      */\r
226     public static Locale[] getAvailableLocales() {\r
227         return ICUResourceBundle.getAvailableLocales();\r
228     }\r
229 \r
230     /**\r
231      * {@icu} Returns an array of all locales for which the <code>getInstance</code>\r
232      * methods of this class can return localized instances.\r
233      *\r
234      * {@icunote} Unlike <code>java.text.DateFormatSymbols#getAvailableLocales</code>,\r
235      * this method simply returns the array of <code>ULocale</code>s available in this\r
236      * class.  ICU does not support <code>DateFormatSymbolsProvider</code> introduced in\r
237      * Java 6 or its equivalent implementation for now.\r
238      *\r
239      * @return An array of <code>ULocale</code>s for which localized\r
240      * <code>DateFormatSymbols</code> instances are available.\r
241      * @draft ICU 3.8 (retain)\r
242      * @provisional This API might change or be removed in a future release.\r
243      */\r
244     public static ULocale[] getAvailableULocales() {\r
245         return ICUResourceBundle.getAvailableULocales();\r
246     }\r
247 \r
248     /**\r
249      * Era strings. For example: "AD" and "BC".  An array of 2 strings,\r
250      * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.\r
251      * @serial\r
252      */\r
253     String eras[] = null;\r
254 \r
255     /**\r
256      * Era name strings. For example: "Anno Domini" and "Before Christ".  An array of 2 strings,\r
257      * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.\r
258      * @serial\r
259      */\r
260     String eraNames[] = null;\r
261 \r
262     /**\r
263      * Narrow era names. For example: "A" and "B". An array of 2 strings,\r
264      * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.\r
265      * @serial\r
266      */\r
267     String narrowEras[] = null;\r
268 \r
269     /**\r
270      * Month strings. For example: "January", "February", etc.  An array\r
271      * of 13 strings (some calendars have 13 months), indexed by\r
272      * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.\r
273      * @serial\r
274      */\r
275     String months[] = null;\r
276 \r
277     /**\r
278      * Short month strings. For example: "Jan", "Feb", etc.  An array of\r
279      * 13 strings (some calendars have 13 months), indexed by\r
280      * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.\r
281 \r
282      * @serial\r
283      */\r
284     String shortMonths[] = null;\r
285 \r
286     /**\r
287      * Narrow month strings. For example: "J", "F", etc.  An array of\r
288      * 13 strings (some calendars have 13 months), indexed by\r
289      * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.\r
290 \r
291      * @serial\r
292      */\r
293     String narrowMonths[] = null;\r
294 \r
295     /**\r
296      * Standalone month strings. For example: "January", "February", etc.  An array\r
297      * of 13 strings (some calendars have 13 months), indexed by\r
298      * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.\r
299      * @serial\r
300      */\r
301     String standaloneMonths[] = null;\r
302 \r
303     /**\r
304      * Standalone short month strings. For example: "Jan", "Feb", etc.  An array of\r
305      * 13 strings (some calendars have 13 months), indexed by\r
306      * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.\r
307 \r
308      * @serial\r
309      */\r
310     String standaloneShortMonths[] = null;\r
311 \r
312     /**\r
313      * Standalone narrow month strings. For example: "J", "F", etc.  An array of\r
314      * 13 strings (some calendars have 13 months), indexed by\r
315      * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.\r
316 \r
317      * @serial\r
318      */\r
319     String standaloneNarrowMonths[] = null;\r
320 \r
321     /**\r
322      * Weekday strings. For example: "Sunday", "Monday", etc.  An array\r
323      * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,\r
324      * <code>Calendar.MONDAY</code>, etc.\r
325      * The element <code>weekdays[0]</code> is ignored.\r
326      * @serial\r
327      */\r
328     String weekdays[] = null;\r
329 \r
330     /**\r
331      * Short weekday strings. For example: "Sun", "Mon", etc.  An array\r
332      * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,\r
333      * <code>Calendar.MONDAY</code>, etc.\r
334      * The element <code>shortWeekdays[0]</code> is ignored.\r
335      * @serial\r
336      */\r
337     String shortWeekdays[] = null;\r
338 \r
339     /**\r
340      * Narrow weekday strings. For example: "S", "M", etc.  An array\r
341      * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,\r
342      * <code>Calendar.MONDAY</code>, etc.\r
343      * The element <code>narrowWeekdays[0]</code> is ignored.\r
344      * @serial\r
345      */\r
346     String narrowWeekdays[] = null;\r
347 \r
348     /**\r
349      * Standalone weekday strings. For example: "Sunday", "Monday", etc.  An array\r
350      * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,\r
351      * <code>Calendar.MONDAY</code>, etc.\r
352      * The element <code>standaloneWeekdays[0]</code> is ignored.\r
353      * @serial\r
354      */\r
355     String standaloneWeekdays[] = null;\r
356 \r
357     /**\r
358      * Standalone short weekday strings. For example: "Sun", "Mon", etc.  An array\r
359      * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,\r
360      * <code>Calendar.MONDAY</code>, etc.\r
361      * The element <code>standaloneShortWeekdays[0]</code> is ignored.\r
362      * @serial\r
363      */\r
364     String standaloneShortWeekdays[] = null;\r
365 \r
366     /**\r
367      * Standalone narrow weekday strings. For example: "S", "M", etc.  An array\r
368      * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,\r
369      * <code>Calendar.MONDAY</code>, etc.\r
370      * The element <code>standaloneNarrowWeekdays[0]</code> is ignored.\r
371      * @serial\r
372      */\r
373     String standaloneNarrowWeekdays[] = null;\r
374 \r
375     /**\r
376      * AM and PM strings. For example: "AM" and "PM".  An array of\r
377      * 2 strings, indexed by <code>Calendar.AM</code> and\r
378      * <code>Calendar.PM</code>.\r
379      * @serial\r
380      */\r
381     String ampms[] = null;\r
382 \r
383     /**\r
384      * Abbreviated quarter names. For example: "Q1", "Q2", "Q3", "Q4". An array\r
385      * of 4 strings indexed by the month divided by 3.\r
386      * @serial\r
387      */\r
388     String shortQuarters[] = null;\r
389 \r
390     /**\r
391      * Full quarter names. For example: "1st Quarter", "2nd Quarter", "3rd Quarter",\r
392      * "4th Quarter". An array of 4 strings, indexed by the month divided by 3.\r
393      * @serial\r
394      */\r
395     String quarters[] = null;\r
396 \r
397     /**\r
398      * Standalone abbreviated quarter names. For example: "Q1", "Q2", "Q3", "Q4". An array\r
399      * of 4 strings indexed by the month divided by 3.\r
400      * @serial\r
401      */\r
402     String standaloneShortQuarters[] = null;\r
403 \r
404     /**\r
405      * Standalone full quarter names. For example: "1st Quarter", "2nd Quarter", "3rd Quarter",\r
406      * "4th Quarter". An array of 4 strings, indexed by the month divided by 3.\r
407      * @serial\r
408      */\r
409     String standaloneQuarters[] = null;\r
410 \r
411     /**\r
412      * Pattern string used for localized time zone GMT format.  For example, "GMT{0}"\r
413      * @serial\r
414      */\r
415     String gmtFormat = null;\r
416 \r
417     /**\r
418      * Pattern strings used for formatting zone offset in a localized time zone GMT string.\r
419      * This is 2x2 String array holding followings\r
420      * [0][0] Negative H + m + s\r
421      * [0][1] Negative H + m\r
422      * [1][0] Positive H + m + s\r
423      * [1][1] Positive H + m\r
424      * @serial\r
425      */\r
426     String gmtHourFormats[][] = null;\r
427 \r
428     /**\r
429      * Localized names of time zones in this locale.  This is a\r
430      * two-dimensional array of strings of size <em>n</em> by <em>m</em>,\r
431      * where <em>m</em> is at least 5 and up to 7.  Each of the <em>n</em> rows is an\r
432      * entry containing the localized names for a single <code>TimeZone</code>.\r
433      * Each such row contains (with <code>i</code> ranging from\r
434      * 0..<em>n</em>-1):\r
435      * <ul>\r
436      * <li><code>zoneStrings[i][0]</code> - time zone ID</li>\r
437      * <li><code>zoneStrings[i][1]</code> - long name of zone in standard\r
438      * time</li>\r
439      * <li><code>zoneStrings[i][2]</code> - short name of zone in\r
440      * standard time</li>\r
441      * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight\r
442      * savings time</li>\r
443      * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight\r
444      * savings time</li>\r
445      * <li><code>zoneStrings[i][5]</code> - location name of zone</li>\r
446      * <li><code>zoneStrings[i][6]</code> - long generic name of zone</li>\r
447      * <li><code>zoneStrings[i][7]</code> - short generic of zone</li>\r
448      * The zone ID is <em>not</em> localized; it corresponds to the ID\r
449      * value associated with a system time zone object.  All other entries\r
450      * are localized names.  If a zone does not implement daylight savings\r
451      * time, the daylight savings time names are ignored.\r
452      * <em>Note:</em>CLDR 1.5 introduced metazone and its historical mappings.\r
453      * This simple two-dimensional array is no longer sufficient to represent\r
454      * localized names and its historic changes.  Since ICU 3.8.1, localized\r
455      * zone names extracted from ICU locale data is stored in a ZoneStringFormat\r
456      * instance.  But we still need to support the old way of customizing\r
457      * localized zone names, so we keep this field for the purpose.\r
458      * @see com.ibm.icu.util.TimeZone\r
459      * @serial\r
460      */\r
461     private String zoneStrings[][] = null;\r
462 \r
463      /**\r
464       * Since ICU 3.8.1, we use ZoneStringFormat to access localized\r
465       * zone names.  This field remains null unless setZoneStrings is\r
466       * called.\r
467       */\r
468     private transient ZoneStringFormat zsformat = null;\r
469 \r
470      /**\r
471      * Unlocalized date-time pattern characters. For example: 'y', 'd', etc.\r
472      * All locales use the same unlocalized pattern characters.\r
473      */\r
474     static final String  patternChars = "GyMdkHmsSEDFwWahKzYeugAZvcLQqV";\r
475 \r
476     /**\r
477      * Localized date-time pattern characters. For example, a locale may\r
478      * wish to use 'u' rather than 'y' to represent years in its date format\r
479      * pattern strings.\r
480      * This string must be exactly 18 characters long, with the index of\r
481      * the characters described by <code>DateFormat.ERA_FIELD</code>,\r
482      * <code>DateFormat.YEAR_FIELD</code>, etc.  Thus, if the string were\r
483      * "Xz...", then localized patterns would use 'X' for era and 'z' for year.\r
484      * @serial\r
485      */\r
486     String localPatternChars = null;\r
487 \r
488     /* use serialVersionUID from JDK 1.1.4 for interoperability */\r
489     private static final long serialVersionUID = -5987973545549424702L;\r
490 \r
491     /**\r
492      * Returns era strings. For example: "AD" and "BC".\r
493      * @return the era strings.\r
494      * @stable ICU 2.0\r
495      */\r
496     public String[] getEras() {\r
497         return duplicate(eras);\r
498     }\r
499 \r
500     /**\r
501      * Sets era strings. For example: "AD" and "BC".\r
502      * @param newEras the new era strings.\r
503      * @stable ICU 2.0\r
504      */\r
505     public void setEras(String[] newEras) {\r
506         eras = duplicate(newEras);\r
507     }\r
508 \r
509     /**\r
510      * {@icu} Returns era name strings. For example: "Anno Domini" and "Before Christ".\r
511      * @return the era strings.\r
512      * @stable ICU 3.4\r
513      */\r
514     public String[] getEraNames() {\r
515         return duplicate(eraNames);\r
516     }\r
517 \r
518     /**\r
519      * {@icu} Sets era name strings. For example: "Anno Domini" and "Before Christ".\r
520      * @param newEraNames the new era strings.\r
521      * @stable ICU 3.8\r
522      */\r
523     public void setEraNames(String[] newEraNames) {\r
524         eraNames = duplicate(newEraNames);\r
525     }\r
526 \r
527     /**\r
528      * Returns month strings. For example: "January", "February", etc.\r
529      * @return the month strings.\r
530      * @stable ICU 2.0\r
531      */\r
532     public String[] getMonths() {\r
533         return duplicate(months);\r
534     }\r
535 \r
536     /**\r
537      * Returns month strings. For example: "January", "February", etc.\r
538      * @param context    The month context, FORMAT or STANDALONE.\r
539      * @param width      The width or the returned month string,\r
540      *                   either WIDE, ABBREVIATED, or NARROW.\r
541      * @return the month strings.\r
542      * @stable ICU 3.4\r
543      */\r
544     public String[] getMonths(int context, int width) {\r
545         String [] returnValue = null;\r
546         switch (context) {\r
547            case FORMAT :\r
548               switch(width) {\r
549                  case WIDE :\r
550                     returnValue = months;\r
551                     break;\r
552                  case ABBREVIATED :\r
553                     returnValue = shortMonths;\r
554                     break;\r
555                  case NARROW :\r
556                     returnValue = narrowMonths;\r
557                     break;\r
558               }\r
559               break;\r
560            case STANDALONE :\r
561               switch(width) {\r
562                  case WIDE :\r
563                     returnValue = standaloneMonths;\r
564                     break;\r
565                  case ABBREVIATED :\r
566                     returnValue = standaloneShortMonths;\r
567                     break;\r
568                  case NARROW :\r
569                     returnValue = standaloneNarrowMonths;\r
570                     break;\r
571               }\r
572               break;\r
573         }\r
574         return duplicate(returnValue);\r
575     }\r
576 \r
577     /**\r
578      * Sets month strings. For example: "January", "February", etc.\r
579      * @param newMonths the new month strings.\r
580      * @stable ICU 2.0\r
581      */\r
582     public void setMonths(String[] newMonths) {\r
583         months = duplicate(newMonths);\r
584     }\r
585 \r
586     /**\r
587      * Sets month strings. For example: "January", "February", etc.\r
588      * @param newMonths the new month strings.\r
589      * @param context    The formatting context, FORMAT or STANDALONE.\r
590      * @param width      The width of the month string,\r
591      *                   either WIDE, ABBREVIATED, or NARROW.\r
592      * @stable ICU 3.8\r
593      */\r
594     public void setMonths(String[] newMonths, int context, int width) {\r
595         switch (context) {\r
596            case FORMAT :\r
597               switch(width) {\r
598                  case WIDE :\r
599                     months = duplicate(newMonths);\r
600                     break;\r
601                  case ABBREVIATED :\r
602                     shortMonths = duplicate(newMonths);\r
603                     break;\r
604                  case NARROW :\r
605                     narrowMonths = duplicate(newMonths);\r
606                     break;\r
607               }\r
608               break;\r
609            case STANDALONE :\r
610               switch(width) {\r
611                  case WIDE :\r
612                     standaloneMonths = duplicate(newMonths);\r
613                     break;\r
614                  case ABBREVIATED :\r
615                     standaloneShortMonths = duplicate(newMonths);\r
616                     break;\r
617                  case NARROW :\r
618                     standaloneNarrowMonths = duplicate(newMonths);\r
619                     break;\r
620               }\r
621               break;\r
622         }\r
623     }\r
624 \r
625     /**\r
626      * Returns short month strings. For example: "Jan", "Feb", etc.\r
627      * @return the short month strings.\r
628      * @stable ICU 2.0\r
629      */\r
630     public String[] getShortMonths() {\r
631         return duplicate(shortMonths);\r
632     }\r
633 \r
634     /**\r
635      * Sets short month strings. For example: "Jan", "Feb", etc.\r
636      * @param newShortMonths the new short month strings.\r
637      * @stable ICU 2.0\r
638      */\r
639     public void setShortMonths(String[] newShortMonths) {\r
640         shortMonths = duplicate(newShortMonths);\r
641     }\r
642 \r
643     /**\r
644      * Returns weekday strings. For example: "Sunday", "Monday", etc.\r
645      * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,\r
646      * <code>Calendar.MONDAY</code>, etc. to index the result array.\r
647      * @stable ICU 2.0\r
648      */\r
649     public String[] getWeekdays() {\r
650         return duplicate(weekdays);\r
651     }\r
652 \r
653     /**\r
654      * Returns weekday strings. For example: "Sunday", "Monday", etc.\r
655      * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,\r
656      * <code>Calendar.MONDAY</code>, etc. to index the result array.\r
657      * @param context    Formatting context, either FORMAT or STANDALONE.\r
658      * @param width      Width of strings to be returned, either\r
659      *                   WIDE, ABBREVIATED, or NARROW\r
660      * @stable ICU 3.4\r
661      */\r
662     public String[] getWeekdays(int context, int width) {\r
663         String [] returnValue = null;\r
664         switch (context) {\r
665            case FORMAT :\r
666               switch(width) {\r
667                  case WIDE :\r
668                     returnValue = weekdays;\r
669                     break;\r
670                  case ABBREVIATED :\r
671                     returnValue = shortWeekdays;\r
672                     break;\r
673                  case NARROW :\r
674                     returnValue = narrowWeekdays;\r
675                     break;\r
676               }\r
677               break;\r
678            case STANDALONE :\r
679               switch(width) {\r
680                  case WIDE :\r
681                     returnValue = standaloneWeekdays;\r
682                     break;\r
683                  case ABBREVIATED :\r
684                     returnValue = standaloneShortWeekdays;\r
685                     break;\r
686                  case NARROW :\r
687                     returnValue = standaloneNarrowWeekdays;\r
688                     break;\r
689               }\r
690               break;\r
691         }\r
692         return duplicate(returnValue);\r
693     }\r
694 \r
695     /**\r
696      * Sets weekday strings. For example: "Sunday", "Monday", etc.\r
697      * @param newWeekdays The new weekday strings.\r
698      * @param context     The formatting context, FORMAT or STANDALONE.\r
699      * @param width       The width of the strings,\r
700      *                    either WIDE, ABBREVIATED, or NARROW.\r
701      * @stable ICU 3.8\r
702      */\r
703     public void setWeekdays(String[] newWeekdays, int context, int width) {\r
704         switch (context) {\r
705            case FORMAT :\r
706               switch(width) {\r
707                  case WIDE :\r
708                     weekdays = duplicate(newWeekdays);\r
709                     break;\r
710                  case ABBREVIATED :\r
711                     shortWeekdays = duplicate(newWeekdays);\r
712                     break;\r
713                  case NARROW :\r
714                     narrowWeekdays = duplicate(newWeekdays);\r
715                     break;\r
716               }\r
717               break;\r
718            case STANDALONE :\r
719               switch(width) {\r
720                  case WIDE :\r
721                     standaloneWeekdays = duplicate(newWeekdays);\r
722                     break;\r
723                  case ABBREVIATED :\r
724                     standaloneShortWeekdays = duplicate(newWeekdays);\r
725                     break;\r
726                  case NARROW :\r
727                     standaloneNarrowWeekdays = duplicate(newWeekdays);\r
728                     break;\r
729               }\r
730               break;\r
731         }\r
732     }\r
733 \r
734     /**\r
735      * Sets weekday strings. For example: "Sunday", "Monday", etc.\r
736      * @param newWeekdays the new weekday strings. The array should\r
737      * be indexed by <code>Calendar.SUNDAY</code>,\r
738      * <code>Calendar.MONDAY</code>, etc.\r
739      * @stable ICU 2.0\r
740      */\r
741     public void setWeekdays(String[] newWeekdays) {\r
742         weekdays = duplicate(newWeekdays);\r
743     }\r
744 \r
745     /**\r
746      * Returns short weekday strings. For example: "Sun", "Mon", etc.\r
747      * @return the short weekday strings. Use <code>Calendar.SUNDAY</code>,\r
748      * <code>Calendar.MONDAY</code>, etc. to index the result array.\r
749      * @stable ICU 2.0\r
750      */\r
751     public String[] getShortWeekdays() {\r
752         return duplicate(shortWeekdays);\r
753     }\r
754 \r
755     /**\r
756      * Sets short weekday strings. For example: "Sun", "Mon", etc.\r
757      * @param newShortWeekdays the new short weekday strings. The array should\r
758      * be indexed by <code>Calendar.SUNDAY</code>,\r
759      * <code>Calendar.MONDAY</code>, etc.\r
760      * @stable ICU 2.0\r
761      */\r
762     public void setShortWeekdays(String[] newShortWeekdays) {\r
763         shortWeekdays = duplicate(newShortWeekdays);\r
764     }\r
765     /**\r
766      * {@icu} Returns quarter strings. For example: "1st Quarter", "2nd Quarter", etc.\r
767      * @param context    The quarter context, FORMAT or STANDALONE.\r
768      * @param width      The width or the returned quarter string,\r
769      *                   either WIDE or ABBREVIATED. There are no NARROW quarters.\r
770      * @return the quarter strings.\r
771      * @stable ICU 3.6\r
772      */\r
773     public String[] getQuarters(int context, int width) {\r
774         String [] returnValue = null;\r
775         switch (context) {\r
776            case FORMAT :\r
777               switch(width) {\r
778                  case WIDE :\r
779                     returnValue = quarters;\r
780                     break;\r
781                  case ABBREVIATED :\r
782                     returnValue = shortQuarters;\r
783                     break;\r
784                  case NARROW :\r
785                      returnValue = null;\r
786                      break;\r
787               }\r
788               break;\r
789 \r
790            case STANDALONE :\r
791               switch(width) {\r
792                  case WIDE :\r
793                     returnValue = standaloneQuarters;\r
794                     break;\r
795                  case ABBREVIATED :\r
796                     returnValue = standaloneShortQuarters;\r
797                     break;\r
798                  case NARROW:\r
799                      returnValue = null;\r
800                      break;\r
801               }\r
802               break;\r
803         }\r
804         return duplicate(returnValue);\r
805     }\r
806 \r
807     /**\r
808      * {@icu} Sets quarter strings. For example: "1st Quarter", "2nd Quarter", etc.\r
809      * @param newQuarters the new quarter strings.\r
810      * @param context    The formatting context, FORMAT or STANDALONE.\r
811      * @param width      The width of the quarter string,\r
812      *                   either WIDE or ABBREVIATED. There are no NARROW quarters.\r
813      * @stable ICU 3.8\r
814      */\r
815     public void setQuarters(String[] newQuarters, int context, int width) {\r
816         switch (context) {\r
817            case FORMAT :\r
818               switch(width) {\r
819                  case WIDE :\r
820                     quarters = duplicate(newQuarters);\r
821                     break;\r
822                  case ABBREVIATED :\r
823                     shortQuarters = duplicate(newQuarters);\r
824                     break;\r
825                  case NARROW :\r
826                     //narrowQuarters = duplicate(newQuarters);\r
827                     break;\r
828               }\r
829               break;\r
830            case STANDALONE :\r
831               switch(width) {\r
832                  case WIDE :\r
833                     standaloneQuarters = duplicate(newQuarters);\r
834                     break;\r
835                  case ABBREVIATED :\r
836                     standaloneShortQuarters = duplicate(newQuarters);\r
837                     break;\r
838                  case NARROW :\r
839                     //standaloneNarrowQuarters = duplicate(newQuarters);\r
840                     break;\r
841               }\r
842               break;\r
843         }\r
844     }\r
845 \r
846     /**\r
847      * Returns am/pm strings. For example: "AM" and "PM".\r
848      * @return the weekday strings.\r
849      * @stable ICU 2.0\r
850      */\r
851     public String[] getAmPmStrings() {\r
852         return duplicate(ampms);\r
853     }\r
854 \r
855     /**\r
856      * Sets am/pm strings. For example: "AM" and "PM".\r
857      * @param newAmpms the new ampm strings.\r
858      * @stable ICU 2.0\r
859      */\r
860     public void setAmPmStrings(String[] newAmpms) {\r
861         ampms = duplicate(newAmpms);\r
862     }\r
863 \r
864     /**\r
865      * Returns timezone strings.\r
866      * @return the timezone strings.\r
867      * @stable ICU 2.0\r
868      */\r
869     public String[][] getZoneStrings() {\r
870         if (zoneStrings != null) {\r
871             return duplicate(zoneStrings);\r
872         }\r
873         return ZoneStringFormat.getInstance(requestedLocale).getZoneStrings();\r
874     }\r
875 \r
876     /**\r
877      * Sets timezone strings.\r
878      * @param newZoneStrings the new timezone strings.\r
879      * @stable ICU 2.0\r
880      */\r
881     public void setZoneStrings(String[][] newZoneStrings) {\r
882         zoneStrings = duplicate(newZoneStrings);\r
883         zsformat = new ZoneStringFormat(zoneStrings);\r
884     }\r
885 \r
886     /**\r
887      * Returns localized date-time pattern characters. For example: 'u', 't', etc.\r
888      *\r
889      * <p>Note: ICU no longer provides localized date-time pattern characters for a locale\r
890      * starting ICU 3.8.  This method returns the non-localized date-time pattern\r
891      * characters unless user defined localized data is set by setLocalPatternChars.\r
892      * @return the localized date-time pattern characters.\r
893      * @stable ICU 2.0\r
894      */\r
895     public String getLocalPatternChars() {\r
896         return localPatternChars;\r
897     }\r
898 \r
899     /**\r
900      * Sets localized date-time pattern characters. For example: 'u', 't', etc.\r
901      * @param newLocalPatternChars the new localized date-time\r
902      * pattern characters.\r
903      * @stable ICU 2.0\r
904      */\r
905     public void setLocalPatternChars(String newLocalPatternChars) {\r
906         localPatternChars = newLocalPatternChars;\r
907     }\r
908 \r
909     /**\r
910      * Overrides clone.\r
911      * @stable ICU 2.0\r
912      */\r
913     public Object clone()\r
914     {\r
915         try {\r
916             DateFormatSymbols other = (DateFormatSymbols)super.clone();\r
917             return other;\r
918         } catch (CloneNotSupportedException e) {\r
919             ///CLOVER:OFF\r
920             throw new IllegalStateException();\r
921             ///CLOVER:ON\r
922         }\r
923     }\r
924 \r
925     /**\r
926      * Override hashCode.\r
927      * Generates a hash code for the DateFormatSymbols object.\r
928      * @stable ICU 2.0\r
929      */\r
930     public int hashCode() {\r
931         // Is this sufficient?\r
932         return requestedLocale.toString().hashCode();\r
933     }\r
934 \r
935     /**\r
936      * Overrides equals.\r
937      * @stable ICU 2.0\r
938      */\r
939     public boolean equals(Object obj)\r
940     {\r
941         if (this == obj) return true;\r
942         if (obj == null || getClass() != obj.getClass()) return false;\r
943         DateFormatSymbols that = (DateFormatSymbols) obj;\r
944         return (Utility.arrayEquals(eras, that.eras)\r
945                 && Utility.arrayEquals(eraNames, that.eraNames)\r
946                 && Utility.arrayEquals(months, that.months)\r
947                 && Utility.arrayEquals(shortMonths, that.shortMonths)\r
948                 && Utility.arrayEquals(narrowMonths, that.narrowMonths)\r
949                 && Utility.arrayEquals(standaloneMonths, that.standaloneMonths)\r
950                 && Utility.arrayEquals(standaloneShortMonths, that.standaloneShortMonths)\r
951                 && Utility.arrayEquals(standaloneNarrowMonths, that.standaloneNarrowMonths)\r
952                 && Utility.arrayEquals(weekdays, that.weekdays)\r
953                 && Utility.arrayEquals(shortWeekdays, that.shortWeekdays)\r
954                 && Utility.arrayEquals(narrowWeekdays, that.narrowWeekdays)\r
955                 && Utility.arrayEquals(standaloneWeekdays, that.standaloneWeekdays)\r
956                 && Utility.arrayEquals(standaloneShortWeekdays, that.standaloneShortWeekdays)\r
957                 && Utility.arrayEquals(standaloneNarrowWeekdays, that.standaloneNarrowWeekdays)\r
958                 && Utility.arrayEquals(ampms, that.ampms)\r
959                 && gmtFormat.equals(that.gmtFormat)\r
960                 && arrayOfArrayEquals(gmtHourFormats, that.gmtHourFormats)\r
961                 && arrayOfArrayEquals(zoneStrings, that.zoneStrings)\r
962                 // getDiplayName maps deprecated country and language codes to the current ones\r
963                 // too bad there is no way to get the current codes!\r
964                 // I thought canolicalize() would map the codes but .. alas! it doesn't.\r
965                 && requestedLocale.getDisplayName().equals(that.requestedLocale.getDisplayName())\r
966                 && Utility.arrayEquals(localPatternChars,\r
967                                        that.localPatternChars));\r
968     }\r
969 \r
970     // =======================privates===============================\r
971 \r
972     /**\r
973      * Useful constant for defining timezone offsets.\r
974      */\r
975     static final int millisPerHour = 60*60*1000;\r
976 \r
977     // DateFormatSymbols cache\r
978     private static ICUCache<String, DateFormatSymbols> DFSCACHE =\r
979         new SimpleCache<String, DateFormatSymbols>();\r
980 \r
981     /**\r
982      * Initializes format symbols for the locale and calendar type\r
983      * @param desiredLocale The locale whose symbols are desired.\r
984      * @param type          The calendar type whose date format symbols are desired.\r
985      * @stable ICU 3.0\r
986      */\r
987     //TODO: This protected seems to be marked as @stable accidentally.\r
988     // We may need to deescalate this API to @internal.\r
989     protected void initializeData(ULocale desiredLocale, String type)\r
990     {\r
991         String key = desiredLocale.toString() + "+" + type;\r
992         DateFormatSymbols dfs = DFSCACHE.get(key);\r
993         if (dfs == null) {\r
994             // Initialize data from scratch put a clone of this instance into the cache\r
995             CalendarData calData = new CalendarData(desiredLocale, type);\r
996             initializeData(desiredLocale, calData);\r
997             dfs = (DateFormatSymbols)this.clone();\r
998             DFSCACHE.put(key, dfs);\r
999         } else {\r
1000             initializeData(dfs);\r
1001         }\r
1002     }\r
1003 \r
1004     /**\r
1005      * Initializes format symbols using another instance.\r
1006      *\r
1007      * TODO Clean up initialization methods for subclasses\r
1008      */\r
1009     void initializeData(DateFormatSymbols dfs) {\r
1010         this.eras = dfs.eras;\r
1011         this.eraNames = dfs.eraNames;\r
1012         this.narrowEras = dfs.narrowEras;\r
1013         this.months = dfs.months;\r
1014         this.shortMonths = dfs.shortMonths;\r
1015         this.narrowMonths = dfs.narrowMonths;\r
1016         this.standaloneMonths = dfs.standaloneMonths;\r
1017         this.standaloneShortMonths = dfs.standaloneShortMonths;\r
1018         this.standaloneNarrowMonths = dfs.standaloneNarrowMonths;\r
1019         this.weekdays = dfs.weekdays;\r
1020         this.shortWeekdays = dfs.shortWeekdays;\r
1021         this.narrowWeekdays = dfs.narrowWeekdays;\r
1022         this.standaloneWeekdays = dfs.standaloneWeekdays;\r
1023         this.standaloneShortWeekdays = dfs.standaloneShortWeekdays;\r
1024         this.standaloneNarrowWeekdays = dfs.standaloneNarrowWeekdays;\r
1025         this.ampms = dfs.ampms;\r
1026         this.shortQuarters = dfs.shortQuarters;\r
1027         this.quarters = dfs.quarters;\r
1028         this.standaloneShortQuarters = dfs.standaloneShortQuarters;\r
1029         this.standaloneQuarters = dfs.standaloneQuarters;\r
1030 \r
1031         this.gmtFormat = dfs.gmtFormat;\r
1032         this.gmtHourFormats = dfs.gmtHourFormats;\r
1033 \r
1034         this.zoneStrings = dfs.zoneStrings; // always null at initialization time for now\r
1035         this.localPatternChars = dfs.localPatternChars;\r
1036 \r
1037         this.actualLocale = dfs.actualLocale;\r
1038         this.validLocale = dfs.validLocale;\r
1039         this.requestedLocale = dfs.requestedLocale;\r
1040     }\r
1041 \r
1042     /**\r
1043      * Initializes format symbols for the locale and calendar type\r
1044      * @param desiredLocale The locale whose symbols are desired.\r
1045      * @param calData       The calendar resource data\r
1046      * @internal\r
1047      * @deprecated This API is ICU internal only.\r
1048      */\r
1049     // This API was accidentally marked as @stable ICU 3.0 formerly.\r
1050     protected void initializeData(ULocale desiredLocale, CalendarData calData)\r
1051     {\r
1052         // FIXME: cache only ResourceBundle. Hence every time, will do\r
1053         // getObject(). This won't be necessary if the Resource itself\r
1054         // is cached.\r
1055         eras = calData.getEras("abbreviated");\r
1056 \r
1057         try {\r
1058            eraNames = calData.getEras("wide");\r
1059         }\r
1060         catch (MissingResourceException e) {\r
1061            eraNames = calData.getEras("abbreviated");\r
1062         }\r
1063 \r
1064         // NOTE: since the above code assumes that abbreviated\r
1065         // era names exist, we make the same assumption here too.\r
1066         try {\r
1067             narrowEras = calData.getEras("narrow");\r
1068         } catch (MissingResourceException e) {\r
1069             narrowEras = calData.getEras("abbreviated");\r
1070         }\r
1071 \r
1072         months = calData.getStringArray("monthNames", "wide");\r
1073         shortMonths = calData.getStringArray("monthNames", "abbreviated");\r
1074 \r
1075         try {\r
1076            narrowMonths = calData.getStringArray("monthNames", "narrow");\r
1077         }\r
1078         catch (MissingResourceException e) {\r
1079             try {\r
1080                 narrowMonths = calData.getStringArray("monthNames", "stand-alone", "narrow");\r
1081             }\r
1082             catch (MissingResourceException e1) {\r
1083                narrowMonths = calData.getStringArray("monthNames", "abbreviated");\r
1084             }\r
1085         }\r
1086 \r
1087         try {\r
1088            standaloneMonths = calData.getStringArray("monthNames", "stand-alone", "wide");\r
1089         }\r
1090         catch (MissingResourceException e) {\r
1091            standaloneMonths = calData.getStringArray("monthNames", "format", "wide");\r
1092         }\r
1093 \r
1094         try {\r
1095            standaloneShortMonths =\r
1096                calData.getStringArray("monthNames", "stand-alone", "abbreviated");\r
1097         }\r
1098         catch (MissingResourceException e) {\r
1099            standaloneShortMonths = calData.getStringArray("monthNames", "format", "abbreviated");\r
1100         }\r
1101 \r
1102         try {\r
1103            standaloneNarrowMonths = calData.getStringArray("monthNames", "stand-alone", "narrow");\r
1104         }\r
1105         catch (MissingResourceException e) {\r
1106            try {\r
1107               standaloneNarrowMonths = calData.getStringArray("monthNames", "format", "narrow");\r
1108            }\r
1109            catch (MissingResourceException e1) {\r
1110               standaloneNarrowMonths =\r
1111                   calData.getStringArray("monthNames", "format", "abbreviated");\r
1112            }\r
1113         }\r
1114 \r
1115         String[] lWeekdays = calData.getStringArray("dayNames", "wide");\r
1116         weekdays = new String[8];\r
1117         weekdays[0] = "";  // 1-based\r
1118         System.arraycopy(lWeekdays, 0, weekdays, 1, lWeekdays.length);\r
1119 \r
1120         String[] sWeekdays = calData.getStringArray("dayNames", "abbreviated");\r
1121         shortWeekdays = new String[8];\r
1122         shortWeekdays[0] = "";  // 1-based\r
1123         System.arraycopy(sWeekdays, 0, shortWeekdays, 1, sWeekdays.length);\r
1124 \r
1125         String [] nWeekdays = null;\r
1126         try {\r
1127            nWeekdays = calData.getStringArray("dayNames", "narrow");\r
1128         }\r
1129         catch (MissingResourceException e) {\r
1130             try {\r
1131                 nWeekdays = calData.getStringArray("dayNames", "stand-alone", "narrow");\r
1132             }\r
1133             catch (MissingResourceException e1) {\r
1134                 nWeekdays = calData.getStringArray("dayNames", "abbreviated");\r
1135             }\r
1136         }\r
1137         narrowWeekdays = new String[8];\r
1138         narrowWeekdays[0] = "";  // 1-based\r
1139         System.arraycopy(nWeekdays, 0, narrowWeekdays, 1, nWeekdays.length);\r
1140 \r
1141         String [] saWeekdays = null;\r
1142         try {\r
1143            saWeekdays = calData.getStringArray("dayNames", "stand-alone", "wide");\r
1144         }\r
1145         catch (MissingResourceException e) {\r
1146            saWeekdays = calData.getStringArray("dayNames", "format", "wide");\r
1147         }\r
1148         standaloneWeekdays = new String[8];\r
1149         standaloneWeekdays[0] = "";  // 1-based\r
1150         System.arraycopy(saWeekdays, 0, standaloneWeekdays, 1, saWeekdays.length);\r
1151 \r
1152         String [] ssWeekdays = null;\r
1153         try {\r
1154            ssWeekdays = calData.getStringArray("dayNames", "stand-alone", "abbreviated");\r
1155         }\r
1156         catch (MissingResourceException e) {\r
1157            ssWeekdays = calData.getStringArray("dayNames", "format", "abbreviated");\r
1158         }\r
1159         standaloneShortWeekdays = new String[8];\r
1160         standaloneShortWeekdays[0] = "";  // 1-based\r
1161         System.arraycopy(ssWeekdays, 0, standaloneShortWeekdays, 1, ssWeekdays.length);\r
1162 \r
1163         String [] snWeekdays = null;\r
1164         try {\r
1165            snWeekdays = calData.getStringArray("dayNames", "stand-alone", "narrow");\r
1166         }\r
1167         catch (MissingResourceException e) {\r
1168            try {\r
1169               snWeekdays = calData.getStringArray("dayNames", "format", "narrow");\r
1170            }\r
1171            catch (MissingResourceException e1) {\r
1172               snWeekdays = calData.getStringArray("dayNames", "format", "abbreviated");\r
1173            }\r
1174         }\r
1175         standaloneNarrowWeekdays = new String[8];\r
1176         standaloneNarrowWeekdays[0] = "";  // 1-based\r
1177         System.arraycopy(snWeekdays, 0, standaloneNarrowWeekdays, 1, snWeekdays.length);\r
1178 \r
1179         ampms = calData.getStringArray("AmPmMarkers");\r
1180 \r
1181         quarters = calData.getStringArray("quarters", "wide");\r
1182         shortQuarters = calData.getStringArray("quarters", "abbreviated");\r
1183 \r
1184         try {\r
1185            standaloneQuarters = calData.getStringArray("quarters", "stand-alone", "wide");\r
1186         }\r
1187         catch (MissingResourceException e) {\r
1188            standaloneQuarters = calData.getStringArray("quarters", "format", "wide");\r
1189         }\r
1190 \r
1191         try {\r
1192            standaloneShortQuarters = calData.getStringArray("quarters", "stand-alone", "abbreviated");\r
1193         }\r
1194         catch (MissingResourceException e) {\r
1195             standaloneShortQuarters = calData.getStringArray("quarters", "format", "abbreviated");\r
1196         }\r
1197 \r
1198         // Initialize localized GMT format patterns\r
1199         initializeGMTFormat(desiredLocale);\r
1200 \r
1201         requestedLocale = desiredLocale;\r
1202 \r
1203         ICUResourceBundle rb =\r
1204             (ICUResourceBundle)UResourceBundle.getBundleInstance(\r
1205                 ICUResourceBundle.ICU_BASE_NAME, desiredLocale);\r
1206 \r
1207         // Because localized date/time pattern characters will be obsolete in CLDR,\r
1208         // we decided not to maintain localized pattern characters in ICU any more.\r
1209         // We always use the base pattern characters by default. (ticket#5597)\r
1210 \r
1211         //localPatternChars = rb.getString("localPatternChars");\r
1212         localPatternChars = patternChars;\r
1213 \r
1214         // TODO: obtain correct actual/valid locale later\r
1215         ULocale uloc = rb.getULocale();\r
1216         setLocale(uloc, uloc);\r
1217     }\r
1218 \r
1219     static final String DEFAULT_GMT_PATTERN = "GMT{0}";\r
1220     static final String[][] DEFAULT_GMT_HOUR_PATTERNS = {\r
1221         {"-HH:mm:ss", "-HH:mm"},\r
1222         {"+HH:mm:ss", "+HH:mm"}\r
1223     };\r
1224 \r
1225     /**\r
1226      * Initializes localized GMT format patterns\r
1227      */\r
1228     private void initializeGMTFormat(ULocale desiredLocale) {\r
1229         // TimeZone format localization is not included in CalendarData\r
1230         gmtFormat = ZoneMeta.getTZLocalizationInfo(desiredLocale, ZoneMeta.GMT);\r
1231         if (gmtFormat == null) {\r
1232             gmtFormat = DEFAULT_GMT_PATTERN;\r
1233         }\r
1234 \r
1235         try {\r
1236             String offsetHM = ZoneMeta.getTZLocalizationInfo(desiredLocale, ZoneMeta.HOUR);\r
1237             gmtHourFormats = new String[2][2];\r
1238             int sepIdx = offsetHM.indexOf(';');\r
1239             if (sepIdx != -1) {\r
1240                 gmtHourFormats[OFFSET_POSITIVE][OFFSET_HM] = offsetHM.substring(0, sepIdx);\r
1241                 gmtHourFormats[OFFSET_NEGATIVE][OFFSET_HM] = offsetHM.substring(sepIdx + 1);\r
1242             } else {\r
1243                 gmtHourFormats[OFFSET_POSITIVE][OFFSET_HM] = "+HH:mm";\r
1244                 gmtHourFormats[OFFSET_NEGATIVE][OFFSET_HM] = "-HH:mm";\r
1245             }\r
1246             // CLDR 1.5 does not have GMT offset pattern including second field.\r
1247             // For now, append "ss" to the end.\r
1248             if (gmtHourFormats[OFFSET_POSITIVE][OFFSET_HM].indexOf(':') != -1) {\r
1249                 gmtHourFormats[OFFSET_POSITIVE][OFFSET_HMS] =\r
1250                     gmtHourFormats[OFFSET_POSITIVE][OFFSET_HM] + ":ss";\r
1251             } else if (gmtHourFormats[OFFSET_POSITIVE][OFFSET_HM].indexOf('.') != -1) {\r
1252                 gmtHourFormats[OFFSET_POSITIVE][OFFSET_HMS] =\r
1253                     gmtHourFormats[OFFSET_POSITIVE][OFFSET_HM] + ".ss";\r
1254             } else {\r
1255                 gmtHourFormats[OFFSET_POSITIVE][OFFSET_HMS] =\r
1256                     gmtHourFormats[OFFSET_POSITIVE][OFFSET_HM] + "ss";\r
1257             }\r
1258             if (gmtHourFormats[OFFSET_NEGATIVE][OFFSET_HM].indexOf(':') != -1) {\r
1259                 gmtHourFormats[OFFSET_NEGATIVE][OFFSET_HMS] =\r
1260                     gmtHourFormats[OFFSET_NEGATIVE][OFFSET_HM] + ":ss";\r
1261             } else if (gmtHourFormats[OFFSET_NEGATIVE][OFFSET_HM].indexOf('.') != -1) {\r
1262                 gmtHourFormats[OFFSET_NEGATIVE][OFFSET_HMS] =\r
1263                     gmtHourFormats[OFFSET_NEGATIVE][OFFSET_HM] + ".ss";\r
1264             } else {\r
1265                 gmtHourFormats[OFFSET_NEGATIVE][OFFSET_HMS] =\r
1266                     gmtHourFormats[OFFSET_NEGATIVE][OFFSET_HM] + "ss";\r
1267             }\r
1268         } catch (MissingResourceException e) {\r
1269             gmtHourFormats = DEFAULT_GMT_HOUR_PATTERNS;\r
1270         }\r
1271     }\r
1272 \r
1273     private static final boolean arrayOfArrayEquals(Object[][] aa1, Object[][]aa2) {\r
1274         if (aa1 == aa2) { // both are null\r
1275             return true;\r
1276         }\r
1277         if (aa1 == null || aa2 == null) { // one is null and the other is not\r
1278             return false;\r
1279         }\r
1280         if (aa1.length != aa2.length) {\r
1281             return false;\r
1282         }\r
1283         boolean equal = true;\r
1284         for (int i = 0; i < aa1.length; i++) {\r
1285             equal = Utility.arrayEquals(aa1[i], aa2[i]);\r
1286             if (!equal) {\r
1287                 break;\r
1288             }\r
1289         }\r
1290         return equal;\r
1291     }\r
1292 \r
1293     /**\r
1294      * Package local method (for now) to get localized GMT format pattern.\r
1295      */\r
1296     String getGmtFormat() {\r
1297         return gmtFormat;\r
1298     }\r
1299 \r
1300     static final int OFFSET_HMS = 0;\r
1301     static final int OFFSET_HM = 1;\r
1302     static final int OFFSET_NEGATIVE = 0;\r
1303     static final int OFFSET_POSITIVE = 1;\r
1304 \r
1305     /*\r
1306      * Package local method (for now) to get hour format pattern used by localized\r
1307      * GMT string.\r
1308      */\r
1309     String getGmtHourFormat(int sign, int width) {\r
1310         return gmtHourFormats[sign][width];\r
1311     }\r
1312 \r
1313     /*\r
1314      * Package local method to access ZoneStringFormat used by this\r
1315      * DateFormatSymbols instance.\r
1316      */\r
1317     ZoneStringFormat getZoneStringFormat() {\r
1318         if (zsformat != null) {\r
1319             return zsformat;\r
1320         }\r
1321         if (zoneStrings != null) {\r
1322             zsformat = new ZoneStringFormat(zoneStrings);\r
1323             return zsformat;\r
1324         }\r
1325         // We do not want to hold the reference to an instance of\r
1326         // ZoneStringFormat.  An instance of ZoneStringFormat for\r
1327         // a locale is shared and cached in ZoneStringFormat class\r
1328         // itself.\r
1329         return ZoneStringFormat.getInstance(requestedLocale);\r
1330     }\r
1331 \r
1332     /*\r
1333      * save the input locale\r
1334      */\r
1335     private ULocale requestedLocale;\r
1336 \r
1337     /*\r
1338      * Clones an array of Strings.\r
1339      * @param srcArray the source array to be cloned.\r
1340      * @return a cloned array.\r
1341      */\r
1342     private final String[] duplicate(String[] srcArray)\r
1343     {\r
1344         return srcArray.clone();\r
1345     }\r
1346 \r
1347     private final String[][] duplicate(String[][] srcArray)\r
1348     {\r
1349         String[][] aCopy = new String[srcArray.length][];\r
1350         for (int i = 0; i < srcArray.length; ++i)\r
1351             aCopy[i] = duplicate(srcArray[i]);\r
1352         return aCopy;\r
1353     }\r
1354 \r
1355     /*\r
1356      * Compares the equality of the two arrays of String.\r
1357      * @param current this String array.\r
1358      * @param other that String array.\r
1359     private final boolean equals(String[] current, String[] other)\r
1360     {\r
1361         int count = current.length;\r
1362 \r
1363         for (int i = 0; i < count; ++i)\r
1364             if (!current[i].equals(other[i]))\r
1365                 return false;\r
1366         return true;\r
1367     }\r
1368      */\r
1369 \r
1370     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
1371 \r
1372     /**\r
1373      * Returns the {@link DateFormatSymbols} object that should be used to format a\r
1374      * calendar system's dates in the given locale.\r
1375      * <p>\r
1376      * <b>Subclassing:</b><br>\r
1377      * When creating a new Calendar subclass, you must create the\r
1378      * {@link ResourceBundle ResourceBundle}\r
1379      * containing its {@link DateFormatSymbols DateFormatSymbols} in a specific place.\r
1380      * The resource bundle name is based on the calendar's fully-specified\r
1381      * class name, with ".resources" inserted at the end of the package name\r
1382      * (just before the class name) and "Symbols" appended to the end.\r
1383      * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"\r
1384      * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".\r
1385      * <p>\r
1386      * Within the ResourceBundle, this method searches for five keys:\r
1387      * <ul>\r
1388      * <li><b>DayNames</b> -\r
1389      *      An array of strings corresponding to each possible\r
1390      *      value of the <code>DAY_OF_WEEK</code> field.  Even though\r
1391      *      <code>DAY_OF_WEEK</code> starts with <code>SUNDAY</code> = 1,\r
1392      *      This array is 0-based; the name for Sunday goes in the\r
1393      *      first position, at index 0.  If this key is not found\r
1394      *      in the bundle, the day names are inherited from the\r
1395      *      default <code>DateFormatSymbols</code> for the requested locale.\r
1396      *\r
1397      * <li><b>DayAbbreviations</b> -\r
1398      *      An array of abbreviated day names corresponding\r
1399      *      to the values in the "DayNames" array.  If this key\r
1400      *      is not found in the resource bundle, the "DayNames"\r
1401      *      values are used instead.  If neither key is found,\r
1402      *      the day abbreviations are inherited from the default\r
1403      *      <code>DateFormatSymbols</code> for the locale.\r
1404      *\r
1405      * <li><b>MonthNames</b> -\r
1406      *      An array of strings corresponding to each possible\r
1407      *      value of the <code>MONTH</code> field.  If this key is not found\r
1408      *      in the bundle, the month names are inherited from the\r
1409      *      default <code>DateFormatSymbols</code> for the requested locale.\r
1410      *\r
1411      * <li><b>MonthAbbreviations</b> -\r
1412      *      An array of abbreviated day names corresponding\r
1413      *      to the values in the "MonthNames" array.  If this key\r
1414      *      is not found in the resource bundle, the "MonthNames"\r
1415      *      values are used instead.  If neither key is found,\r
1416      *      the day abbreviations are inherited from the default\r
1417      *      <code>DateFormatSymbols</code> for the locale.\r
1418      *\r
1419      * <li><b>Eras</b> -\r
1420      *      An array of strings corresponding to each possible\r
1421      *      value of the <code>ERA</code> field.  If this key is not found\r
1422      *      in the bundle, the era names are inherited from the\r
1423      *      default <code>DateFormatSymbols</code> for the requested locale.\r
1424      * </ul>\r
1425      * <p>\r
1426      * @param cal       The calendar system whose date format symbols are desired.\r
1427      * @param locale    The locale whose symbols are desired.\r
1428      *\r
1429      * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)\r
1430      * @stable ICU 2.0\r
1431      */\r
1432     public DateFormatSymbols(Calendar cal, Locale locale) {\r
1433         initializeData(ULocale.forLocale(locale), cal.getType());\r
1434     }\r
1435 \r
1436     /**\r
1437      * Returns the {@link DateFormatSymbols} object that should be used to format a\r
1438      * calendar system's dates in the given locale.\r
1439      * <p>\r
1440      * <b>Subclassing:</b><br>\r
1441      * When creating a new Calendar subclass, you must create the\r
1442      * {@link ResourceBundle ResourceBundle}\r
1443      * containing its {@link DateFormatSymbols DateFormatSymbols} in a specific place.\r
1444      * The resource bundle name is based on the calendar's fully-specified\r
1445      * class name, with ".resources" inserted at the end of the package name\r
1446      * (just before the class name) and "Symbols" appended to the end.\r
1447      * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"\r
1448      * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".\r
1449      * <p>\r
1450      * Within the ResourceBundle, this method searches for five keys:\r
1451      * <ul>\r
1452      * <li><b>DayNames</b> -\r
1453      *      An array of strings corresponding to each possible\r
1454      *      value of the <code>DAY_OF_WEEK</code> field.  Even though\r
1455      *      <code>DAY_OF_WEEK</code> starts with <code>SUNDAY</code> = 1,\r
1456      *      This array is 0-based; the name for Sunday goes in the\r
1457      *      first position, at index 0.  If this key is not found\r
1458      *      in the bundle, the day names are inherited from the\r
1459      *      default <code>DateFormatSymbols</code> for the requested locale.\r
1460      *\r
1461      * <li><b>DayAbbreviations</b> -\r
1462      *      An array of abbreviated day names corresponding\r
1463      *      to the values in the "DayNames" array.  If this key\r
1464      *      is not found in the resource bundle, the "DayNames"\r
1465      *      values are used instead.  If neither key is found,\r
1466      *      the day abbreviations are inherited from the default\r
1467      *      <code>DateFormatSymbols</code> for the locale.\r
1468      *\r
1469      * <li><b>MonthNames</b> -\r
1470      *      An array of strings corresponding to each possible\r
1471      *      value of the <code>MONTH</code> field.  If this key is not found\r
1472      *      in the bundle, the month names are inherited from the\r
1473      *      default <code>DateFormatSymbols</code> for the requested locale.\r
1474      *\r
1475      * <li><b>MonthAbbreviations</b> -\r
1476      *      An array of abbreviated day names corresponding\r
1477      *      to the values in the "MonthNames" array.  If this key\r
1478      *      is not found in the resource bundle, the "MonthNames"\r
1479      *      values are used instead.  If neither key is found,\r
1480      *      the day abbreviations are inherited from the default\r
1481      *      <code>DateFormatSymbols</code> for the locale.\r
1482      *\r
1483      * <li><b>Eras</b> -\r
1484      *      An array of strings corresponding to each possible\r
1485      *      value of the <code>ERA</code> field.  If this key is not found\r
1486      *      in the bundle, the era names are inherited from the\r
1487      *      default <code>DateFormatSymbols</code> for the requested locale.\r
1488      * </ul>\r
1489      * <p>\r
1490      * @param cal       The calendar system whose date format symbols are desired.\r
1491      * @param locale    The ulocale whose symbols are desired.\r
1492      *\r
1493      * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)\r
1494      * @stable ICU 3.2\r
1495      */\r
1496     public DateFormatSymbols(Calendar cal, ULocale locale) {\r
1497         initializeData(locale, cal.getType());\r
1498     }\r
1499 \r
1500     /**\r
1501      * Variant of DateFormatSymbols(Calendar, Locale) that takes the Calendar class\r
1502      * instead of a Calandar instance.\r
1503      * @see #DateFormatSymbols(Calendar, Locale)\r
1504      * @stable ICU 2.2\r
1505      */\r
1506     public DateFormatSymbols(Class<? extends Calendar> calendarClass, Locale locale) {\r
1507         this(calendarClass, ULocale.forLocale(locale));\r
1508     }\r
1509 \r
1510     /**\r
1511      * Variant of DateFormatSymbols(Calendar, ULocale) that takes the Calendar class\r
1512      * instead of a Calandar instance.\r
1513      * @see #DateFormatSymbols(Calendar, Locale)\r
1514      * @stable ICU 3.2\r
1515      */\r
1516     public DateFormatSymbols(Class<? extends Calendar> calendarClass, ULocale locale) {\r
1517         String fullName = calendarClass.getName();\r
1518         int lastDot = fullName.lastIndexOf('.');\r
1519         String className = fullName.substring(lastDot+1);\r
1520         String calType = className.replaceAll("Calendar", "").toLowerCase();\r
1521 \r
1522         initializeData(locale, calType);\r
1523     }\r
1524 \r
1525     /**\r
1526      * Fetches a custom calendar's DateFormatSymbols out of the given resource\r
1527      * bundle.  Symbols that are not overridden are inherited from the\r
1528      * default DateFormatSymbols for the locale.\r
1529      * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)\r
1530      * @stable ICU 2.0\r
1531      */\r
1532     public DateFormatSymbols(ResourceBundle bundle, Locale locale) {\r
1533         this(bundle, ULocale.forLocale(locale));\r
1534     }\r
1535 \r
1536     /**\r
1537      * Fetches a custom calendar's DateFormatSymbols out of the given resource\r
1538      * bundle.  Symbols that are not overridden are inherited from the\r
1539      * default DateFormatSymbols for the locale.\r
1540      * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)\r
1541      * @stable ICU 3.2\r
1542      */\r
1543     public DateFormatSymbols(ResourceBundle bundle, ULocale locale) {\r
1544         initializeData(locale,\r
1545             new CalendarData((ICUResourceBundle)bundle, CalendarUtil.getCalendarType(locale)));\r
1546     }\r
1547 \r
1548     /**\r
1549      * Finds the ResourceBundle containing the date format information for\r
1550      * a specified calendar subclass in a given locale.\r
1551      * <p>\r
1552      * The resource bundle name is based on the calendar's fully-specified\r
1553      * class name, with ".resources" inserted at the end of the package name\r
1554      * (just before the class name) and "Symbols" appended to the end.\r
1555      * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"\r
1556      * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".\r
1557      * <p>\r
1558      * <b>Note:</b>Because of the structural changes in the ICU locale bundle,\r
1559      * this API no longer works as described.  This method always returns null.\r
1560      * @deprecated ICU 4.0\r
1561      */\r
1562     // This API was formerly @stable ICU 2.0\r
1563     static public ResourceBundle getDateFormatBundle(Class<? extends Calendar> calendarClass,\r
1564                                                      Locale locale)\r
1565         throws MissingResourceException {\r
1566         return null;\r
1567     }\r
1568 \r
1569     /**\r
1570      * Finds the ResourceBundle containing the date format information for\r
1571      * a specified calendar subclass in a given locale.\r
1572      * <p>\r
1573      * The resource bundle name is based on the calendar's fully-specified\r
1574      * class name, with ".resources" inserted at the end of the package name\r
1575      * (just before the class name) and "Symbols" appended to the end.\r
1576      * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"\r
1577      * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".\r
1578      * <p>\r
1579      * <b>Note:</b>Because of the structural changes in the ICU locale bundle,\r
1580      * this API no longer works as described.  This method always returns null.\r
1581      * @deprecated ICU 4.0\r
1582      */\r
1583     // This API was formerly @stable ICU 3.2\r
1584     static public ResourceBundle getDateFormatBundle(Class<? extends Calendar> calendarClass,\r
1585                                                      ULocale locale)\r
1586         throws MissingResourceException {\r
1587         return null;\r
1588     }\r
1589 \r
1590     /**\r
1591      * Variant of getDateFormatBundle(java.lang.Class, java.util.Locale) that takes\r
1592      * a Calendar instance instead of a Calendar class.\r
1593      * <p>\r
1594      * <b>Note:</b>Because of the structural changes in the ICU locale bundle,\r
1595      * this API no longer works as described.  This method always returns null.\r
1596      * @see #getDateFormatBundle(java.lang.Class, java.util.Locale)\r
1597      * @deprecated ICU 4.0\r
1598      */\r
1599     // This API was formerly @stable ICU 2.2\r
1600     public static ResourceBundle getDateFormatBundle(Calendar cal, Locale locale)\r
1601         throws MissingResourceException {\r
1602         return null;\r
1603     }\r
1604 \r
1605     /**\r
1606      * Variant of getDateFormatBundle(java.lang.Class, java.util.Locale) that takes\r
1607      * a Calendar instance instead of a Calendar class.\r
1608      * <p>\r
1609      * <b>Note:</b>Because of the structural changes in the ICU locale bundle,\r
1610      * this API no longer works as described.  This method always returns null.\r
1611      * @see #getDateFormatBundle(java.lang.Class, java.util.Locale)\r
1612      * @deprecated ICU 4.0\r
1613      */\r
1614     // This API was formerly @stable ICU 3.2\r
1615     public static ResourceBundle getDateFormatBundle(Calendar cal, ULocale locale)\r
1616         throws MissingResourceException {\r
1617         return null;\r
1618     }\r
1619 \r
1620     // -------- BEGIN ULocale boilerplate --------\r
1621 \r
1622     /**\r
1623      * Returns the locale that was used to create this object, or null.\r
1624      * This may may differ from the locale requested at the time of\r
1625      * this object's creation.  For example, if an object is created\r
1626      * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be\r
1627      * drawn from <tt>en</tt> (the <i>actual</i> locale), and\r
1628      * <tt>en_US</tt> may be the most specific locale that exists (the\r
1629      * <i>valid</i> locale).\r
1630      *\r
1631      * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8\r
1632      * contains a partial preview implementation.  The * <i>actual</i>\r
1633      * locale is returned correctly, but the <i>valid</i> locale is\r
1634      * not, in most cases.\r
1635      * @param type type of information requested, either {@link\r
1636      * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link\r
1637      * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.\r
1638      * @return the information specified by <i>type</i>, or null if\r
1639      * this object was not constructed from locale data.\r
1640      * @see com.ibm.icu.util.ULocale\r
1641      * @see com.ibm.icu.util.ULocale#VALID_LOCALE\r
1642      * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE\r
1643      * @draft ICU 2.8 (retain)\r
1644      * @provisional This API might change or be removed in a future release.\r
1645      */\r
1646     public final ULocale getLocale(ULocale.Type type) {\r
1647         return type == ULocale.ACTUAL_LOCALE ?\r
1648             this.actualLocale : this.validLocale;\r
1649     }\r
1650 \r
1651     /**\r
1652      * Sets information about the locales that were used to create this\r
1653      * object.  If the object was not constructed from locale data,\r
1654      * both arguments should be set to null.  Otherwise, neither\r
1655      * should be null.  The actual locale must be at the same level or\r
1656      * less specific than the valid locale.  This method is intended\r
1657      * for use by factories or other entities that create objects of\r
1658      * this class.\r
1659      * @param valid the most specific locale containing any resource\r
1660      * data, or null\r
1661      * @param actual the locale containing data used to construct this\r
1662      * object, or null\r
1663      * @see com.ibm.icu.util.ULocale\r
1664      * @see com.ibm.icu.util.ULocale#VALID_LOCALE\r
1665      * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE\r
1666      */\r
1667     final void setLocale(ULocale valid, ULocale actual) {\r
1668         // Change the following to an assertion later\r
1669         if ((valid == null) != (actual == null)) {\r
1670             ///CLOVER:OFF\r
1671             throw new IllegalArgumentException();\r
1672             ///CLOVER:ON\r
1673         }\r
1674         // Another check we could do is that the actual locale is at\r
1675         // the same level or less specific than the valid locale.\r
1676         this.validLocale = valid;\r
1677         this.actualLocale = actual;\r
1678     }\r
1679 \r
1680     /**\r
1681      * The most specific locale containing any resource data, or null.\r
1682      * @see com.ibm.icu.util.ULocale\r
1683      */\r
1684     private ULocale validLocale;\r
1685 \r
1686     /**\r
1687      * The locale containing data used to construct this object, or\r
1688      * null.\r
1689      * @see com.ibm.icu.util.ULocale\r
1690      */\r
1691     private ULocale actualLocale;\r
1692 \r
1693     // -------- END ULocale boilerplate --------\r
1694 \r
1695     /**\r
1696      * 3.8 or older version did not have localized GMT format\r
1697      * patterns.\r
1698      */\r
1699     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {\r
1700         stream.defaultReadObject();\r
1701         if (gmtFormat == null) {\r
1702             initializeGMTFormat(requestedLocale);\r
1703         }\r
1704     }\r
1705 }\r