Calendar.java revision 162b0775772fa66b7eb634760a8159a60c1ddcea
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.util;
19
20import java.io.IOException;
21import java.io.ObjectInputStream;
22import java.io.ObjectOutputStream;
23import java.io.ObjectStreamField;
24import java.io.Serializable;
25import java.text.DateFormatSymbols;
26import libcore.icu.ICU;
27import libcore.icu.LocaleData;
28
29/**
30 * {@code Calendar} is an abstract base class for converting between a
31 * {@code Date} object and a set of integer fields such as
32 * {@code YEAR}, {@code MONTH}, {@code DAY},
33 * {@code HOUR}, and so on. (A {@code Date} object represents a
34 * specific instant in time with millisecond precision. See {@link Date} for
35 * information about the {@code Date} class.)
36 *
37 * <p>
38 * Subclasses of {@code Calendar} interpret a {@code Date}
39 * according to the rules of a specific calendar system.
40 *
41 * <p>
42 * Like other locale-sensitive classes, {@code Calendar} provides a class
43 * method, {@code getInstance}, for getting a default instance of
44 * this class for general use. {@code Calendar}'s {@code getInstance} method
45 * returns a calendar whose locale is based on system settings and whose time fields
46 * have been initialized with the current date and time: <blockquote>
47 *
48 * <pre>Calendar rightNow = Calendar.getInstance()</pre>
49 *
50 * </blockquote>
51 *
52 * <p>
53 * A {@code Calendar} object can produce all the time field values needed
54 * to implement the date-time formatting for a particular language and calendar
55 * style (for example, Japanese-Gregorian, Japanese-Traditional).
56 * {@code Calendar} defines the range of values returned by certain
57 * fields, as well as their meaning. For example, the first month of the year
58 * has value {@code MONTH} == {@code JANUARY} for all calendars.
59 * Other values are defined by the concrete subclass, such as {@code ERA}
60 * and {@code YEAR}. See individual field documentation and subclass
61 * documentation for details.
62 *
63 * <p>
64 * When a {@code Calendar} is <em>lenient</em>, it accepts a wider
65 * range of field values than it produces. For example, a lenient
66 * {@code GregorianCalendar} interprets {@code MONTH} ==
67 * {@code JANUARY}, {@code DAY_OF_MONTH} == 32 as February 1. A
68 * non-lenient {@code GregorianCalendar} throws an exception when given
69 * out-of-range field settings. When calendars recompute field values for return
70 * by {@code get()}, they normalize them. For example, a
71 * {@code GregorianCalendar} always produces {@code DAY_OF_MONTH}
72 * values between 1 and the length of the month.
73 *
74 * <p>
75 * {@code Calendar} defines a locale-specific seven day week using two
76 * parameters: the first day of the week and the minimal days in first week
77 * (from 1 to 7). These numbers are taken from the locale resource data when a
78 * {@code Calendar} is constructed. They may also be specified explicitly
79 * through the API.
80 *
81 * <p>
82 * When setting or getting the {@code WEEK_OF_MONTH} or
83 * {@code WEEK_OF_YEAR} fields, {@code Calendar} must determine
84 * the first week of the month or year as a reference point. The first week of a
85 * month or year is defined as the earliest seven day period beginning on
86 * {@code getFirstDayOfWeek()} and containing at least
87 * {@code getMinimalDaysInFirstWeek()} days of that month or year. Weeks
88 * numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow
89 * it. Note that the normalized numbering returned by {@code get()} may
90 * be different. For example, a specific {@code Calendar} subclass may
91 * designate the week before week 1 of a year as week <em>n</em> of the
92 * previous year.
93 *
94 * <p>
95 * When computing a {@code Date} from time fields, two special
96 * circumstances may arise: there may be insufficient information to compute the
97 * {@code Date} (such as only year and month but no day in the month), or
98 * there may be inconsistent information (such as "Tuesday, July 15, 1996" --
99 * July 15, 1996 is actually a Monday).
100 *
101 * <p>
102 * <strong>Insufficient information.</strong> The calendar will use default
103 * information to specify the missing fields. This may vary by calendar; for the
104 * Gregorian calendar, the default for a field is the same as that of the start
105 * of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc.
106 *
107 * <p>
108 * <strong>Inconsistent information.</strong> If fields conflict, the calendar
109 * will give preference to fields set more recently. For example, when
110 * determining the day, the calendar will look for one of the following
111 * combinations of fields. The most recent combination, as determined by the
112 * most recently set single field, will be used.
113 *
114 * <blockquote>
115 *
116 * <pre>
117 * MONTH + DAY_OF_MONTH
118 * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
119 * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
120 * DAY_OF_YEAR
121 * DAY_OF_WEEK + WEEK_OF_YEAR</pre>
122 *
123 * </blockquote>
124 *
125 * For the time of day:
126 *
127 * <blockquote>
128 *
129 * <pre>
130 * HOUR_OF_DAY
131 * AM_PM + HOUR</pre>
132 *
133 * </blockquote>
134 *
135 * <p>
136 * <strong>Note:</strong> There are certain possible ambiguities in
137 * interpretation of certain singular times, which are resolved in the following
138 * ways:
139 * <ol>
140 * <li> 24:00:00 "belongs" to the following day. That is, 23:59 on Dec 31, 1969
141 * &lt; 24:00 on Jan 1, 1970 &lt; 24:01:00 on Jan 1, 1970 form a sequence of
142 * three consecutive minutes in time.
143 *
144 * <li> Although historically not precise, midnight also belongs to "am", and
145 * noon belongs to "pm", so on the same day, we have 12:00 am (midnight) &lt; 12:01 am,
146 * and 12:00 pm (noon) &lt; 12:01 pm
147 * </ol>
148 *
149 * <p>
150 * The date or time format strings are not part of the definition of a calendar,
151 * as those must be modifiable or overridable by the user at runtime. Use
152 * {@link java.text.DateFormat} to format dates.
153 *
154 * <p>
155 * <strong>Field manipulation methods</strong>
156 *
157 * <p>
158 * {@code Calendar} fields can be changed using three methods:
159 * {@code set()}, {@code add()}, and {@code roll()}.
160 *
161 * <p>
162 * <strong>{@code set(f, value)}</strong> changes field {@code f}
163 * to {@code value}. In addition, it sets an internal member variable to
164 * indicate that field {@code f} has been changed. Although field
165 * {@code f} is changed immediately, the calendar's milliseconds is not
166 * recomputed until the next call to {@code get()},
167 * {@code getTime()}, or {@code getTimeInMillis()} is made. Thus,
168 * multiple calls to {@code set()} do not trigger multiple, unnecessary
169 * computations. As a result of changing a field using {@code set()},
170 * other fields may also change, depending on the field, the field value, and
171 * the calendar system. In addition, {@code get(f)} will not necessarily
172 * return {@code value} after the fields have been recomputed. The
173 * specifics are determined by the concrete calendar class.
174 *
175 * <p>
176 * <em>Example</em>: Consider a {@code GregorianCalendar} originally
177 * set to August 31, 1999. Calling <code>set(Calendar.MONTH,
178 * Calendar.SEPTEMBER)</code>
179 * sets the calendar to September 31, 1999. This is a temporary internal
180 * representation that resolves to October 1, 1999 if {@code getTime()}is
181 * then called. However, a call to {@code set(Calendar.DAY_OF_MONTH, 30)}
182 * before the call to {@code getTime()} sets the calendar to September
183 * 30, 1999, since no recomputation occurs after {@code set()} itself.
184 *
185 * <p>
186 * <strong>{@code add(f, delta)}</strong> adds {@code delta} to
187 * field {@code f}. This is equivalent to calling <code>set(f,
188 * get(f) + delta)</code>
189 * with two adjustments:
190 *
191 * <blockquote>
192 * <p>
193 * <strong>Add rule 1</strong>. The value of field {@code f} after the
194 * call minus the value of field {@code f} before the call is
195 * {@code delta}, modulo any overflow that has occurred in field
196 * {@code f}. Overflow occurs when a field value exceeds its range and,
197 * as a result, the next larger field is incremented or decremented and the
198 * field value is adjusted back into its range.
199 *
200 * <p>
201 * <strong>Add rule 2</strong>. If a smaller field is expected to be invariant,
202 * but &nbsp; it is impossible for it to be equal to its prior value because of
203 * changes in its minimum or maximum after field {@code f} is changed,
204 * then its value is adjusted to be as close as possible to its expected value.
205 * A smaller field represents a smaller unit of time. {@code HOUR} is a
206 * smaller field than {@code DAY_OF_MONTH}. No adjustment is made to
207 * smaller fields that are not expected to be invariant. The calendar system
208 * determines what fields are expected to be invariant.
209 * </blockquote>
210 *
211 * <p>
212 * In addition, unlike {@code set()}, {@code add()} forces an
213 * immediate recomputation of the calendar's milliseconds and all fields.
214 *
215 * <p>
216 * <em>Example</em>: Consider a {@code GregorianCalendar} originally
217 * set to August 31, 1999. Calling {@code add(Calendar.MONTH, 13)} sets
218 * the calendar to September 30, 2000. <strong>Add rule 1</strong> sets the
219 * {@code MONTH} field to September, since adding 13 months to August
220 * gives September of the next year. Since {@code DAY_OF_MONTH} cannot be
221 * 31 in September in a {@code GregorianCalendar}, <strong>add rule 2</strong>
222 * sets the {@code DAY_OF_MONTH} to 30, the closest possible value.
223 * Although it is a smaller field, {@code DAY_OF_WEEK} is not adjusted by
224 * rule 2, since it is expected to change when the month changes in a
225 * {@code GregorianCalendar}.
226 *
227 * <p>
228 * <strong>{@code roll(f, delta)}</strong> adds {@code delta} to
229 * field {@code f} without changing larger fields. This is equivalent to
230 * calling {@code add(f, delta)} with the following adjustment:
231 *
232 * <blockquote>
233 * <p>
234 * <strong>Roll rule</strong>. Larger fields are unchanged after the call. A
235 * larger field represents a larger unit of time. {@code DAY_OF_MONTH} is
236 * a larger field than {@code HOUR}.
237 * </blockquote>
238 *
239 * <p>
240 * <em>Example</em>: Consider a {@code GregorianCalendar} originally
241 * set to August 31, 1999. Calling <code>roll(Calendar.MONTH,
242 * 8)</code> sets
243 * the calendar to April 30, <strong>1999</strong>. Add rule 1 sets the
244 * {@code MONTH} field to April. Using a {@code GregorianCalendar},
245 * the {@code DAY_OF_MONTH} cannot be 31 in the month April. Add rule 2
246 * sets it to the closest possible value, 30. Finally, the <strong>roll rule</strong>
247 * maintains the {@code YEAR} field value of 1999.
248 *
249 * <p>
250 * <em>Example</em>: Consider a {@code GregorianCalendar} originally
251 * set to Sunday June 6, 1999. Calling
252 * {@code roll(Calendar.WEEK_OF_MONTH, -1)} sets the calendar to Tuesday
253 * June 1, 1999, whereas calling {@code add(Calendar.WEEK_OF_MONTH, -1)}
254 * sets the calendar to Sunday May 30, 1999. This is because the roll rule
255 * imposes an additional constraint: The {@code MONTH} must not change
256 * when the {@code WEEK_OF_MONTH} is rolled. Taken together with add rule
257 * 1, the resultant date must be between Tuesday June 1 and Saturday June 5.
258 * According to add rule 2, the {@code DAY_OF_WEEK}, an invariant when
259 * changing the {@code WEEK_OF_MONTH}, is set to Tuesday, the closest
260 * possible value to Sunday (where Sunday is the first day of the week).
261 *
262 * <p>
263 * <strong>Usage model</strong>. To motivate the behavior of {@code add()}
264 * and {@code roll()}, consider a user interface component with
265 * increment and decrement buttons for the month, day, and year, and an
266 * underlying {@code GregorianCalendar}. If the interface reads January
267 * 31, 1999 and the user presses the month increment button, what should it
268 * read? If the underlying implementation uses {@code set()}, it might
269 * read March 3, 1999. A better result would be February 28, 1999. Furthermore,
270 * if the user presses the month increment button again, it should read March
271 * 31, 1999, not March 28, 1999. By saving the original date and using either
272 * {@code add()} or {@code roll()}, depending on whether larger
273 * fields should be affected, the user interface can behave as most users will
274 * intuitively expect.
275 *
276 * <p>
277 * <b>Note:</b> You should always use {@code roll} and {@code add} rather than
278 * attempting to perform arithmetic operations directly on the fields of a
279 * <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses
280 * to have fields with non-linear behavior, for example missing months or days
281 * during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt>
282 * methods will take this into account, while simple arithmetic manipulations
283 * may give invalid results.
284 *
285 * @see Date
286 * @see GregorianCalendar
287 * @see TimeZone
288 */
289public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {
290
291    private static final long serialVersionUID = -1807547505821590642L;
292
293    /**
294     * True iff the values in {@code fields[]} correspond to {@code time}. Despite the name, this
295     * is effectively "are the values in fields[] up-to-date?" --- {@code fields[]} may contain
296     * non-zero values and {@code isSet[]} may contain {@code true} values even when
297     * {@code areFieldsSet} is false.
298     * Accessing the fields via {@code get} will ensure the fields are up-to-date.
299     */
300    protected boolean areFieldsSet;
301
302    /**
303     * Contains broken-down field values for the current value of {@code time} if
304     * {@code areFieldsSet} is true, or stale data corresponding to some previous value otherwise.
305     * Accessing the fields via {@code get} will ensure the fields are up-to-date.
306     * The array length is always {@code FIELD_COUNT}.
307     */
308    protected int[] fields;
309
310    /**
311     * Whether the corresponding element in {@code field[]} has been set. Initially, these are all
312     * false. The first time the fields are computed, these are set to true and remain set even if
313     * the data becomes stale: you <i>must</i> check {@code areFieldsSet} if you want to know
314     * whether the value is up-to-date.
315     * Note that {@code isSet} is <i>not</i> a safe alternative to accessing this array directly,
316     * and will likewise return stale data!
317     * The array length is always {@code FIELD_COUNT}.
318     */
319    protected boolean[] isSet;
320
321    /**
322     * Whether {@code time} corresponds to the values in {@code fields[]}. If false, {@code time}
323     * is out-of-date with respect to changes {@code fields[]}.
324     * Accessing the time via {@code getTimeInMillis} will always return the correct value.
325     */
326    protected boolean isTimeSet;
327
328    /**
329     * A time in milliseconds since January 1, 1970. See {@code isTimeSet}.
330     * Accessing the time via {@code getTimeInMillis} will always return the correct value.
331     */
332    protected long time;
333
334    transient int lastTimeFieldSet;
335
336    transient int lastDateFieldSet;
337
338    private boolean lenient;
339
340    private int firstDayOfWeek;
341
342    private int minimalDaysInFirstWeek;
343
344    private TimeZone zone;
345
346    /**
347     * Value of the {@code MONTH} field indicating the first month of the
348     * year.
349     */
350    public static final int JANUARY = 0;
351
352    /**
353     * Value of the {@code MONTH} field indicating the second month of
354     * the year.
355     */
356    public static final int FEBRUARY = 1;
357
358    /**
359     * Value of the {@code MONTH} field indicating the third month of the
360     * year.
361     */
362    public static final int MARCH = 2;
363
364    /**
365     * Value of the {@code MONTH} field indicating the fourth month of
366     * the year.
367     */
368    public static final int APRIL = 3;
369
370    /**
371     * Value of the {@code MONTH} field indicating the fifth month of the
372     * year.
373     */
374    public static final int MAY = 4;
375
376    /**
377     * Value of the {@code MONTH} field indicating the sixth month of the
378     * year.
379     */
380    public static final int JUNE = 5;
381
382    /**
383     * Value of the {@code MONTH} field indicating the seventh month of
384     * the year.
385     */
386    public static final int JULY = 6;
387
388    /**
389     * Value of the {@code MONTH} field indicating the eighth month of
390     * the year.
391     */
392    public static final int AUGUST = 7;
393
394    /**
395     * Value of the {@code MONTH} field indicating the ninth month of the
396     * year.
397     */
398    public static final int SEPTEMBER = 8;
399
400    /**
401     * Value of the {@code MONTH} field indicating the tenth month of the
402     * year.
403     */
404    public static final int OCTOBER = 9;
405
406    /**
407     * Value of the {@code MONTH} field indicating the eleventh month of
408     * the year.
409     */
410    public static final int NOVEMBER = 10;
411
412    /**
413     * Value of the {@code MONTH} field indicating the twelfth month of
414     * the year.
415     */
416    public static final int DECEMBER = 11;
417
418    /**
419     * Value of the {@code MONTH} field indicating the thirteenth month
420     * of the year. Although {@code GregorianCalendar} does not use this
421     * value, lunar calendars do.
422     */
423    public static final int UNDECIMBER = 12;
424
425    /**
426     * Value of the {@code DAY_OF_WEEK} field indicating Sunday.
427     */
428    public static final int SUNDAY = 1;
429
430    /**
431     * Value of the {@code DAY_OF_WEEK} field indicating Monday.
432     */
433    public static final int MONDAY = 2;
434
435    /**
436     * Value of the {@code DAY_OF_WEEK} field indicating Tuesday.
437     */
438    public static final int TUESDAY = 3;
439
440    /**
441     * Value of the {@code DAY_OF_WEEK} field indicating Wednesday.
442     */
443    public static final int WEDNESDAY = 4;
444
445    /**
446     * Value of the {@code DAY_OF_WEEK} field indicating Thursday.
447     */
448    public static final int THURSDAY = 5;
449
450    /**
451     * Value of the {@code DAY_OF_WEEK} field indicating Friday.
452     */
453    public static final int FRIDAY = 6;
454
455    /**
456     * Value of the {@code DAY_OF_WEEK} field indicating Saturday.
457     */
458    public static final int SATURDAY = 7;
459
460    /**
461     * Field number for {@code get} and {@code set} indicating the
462     * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific
463     * value; see subclass documentation.
464     *
465     * @see GregorianCalendar#AD
466     * @see GregorianCalendar#BC
467     */
468    public static final int ERA = 0;
469
470    /**
471     * Field number for {@code get} and {@code set} indicating the
472     * year. This is a calendar-specific value; see subclass documentation.
473     */
474    public static final int YEAR = 1;
475
476    /**
477     * Field number for {@code get} and {@code set} indicating the
478     * month. This is a calendar-specific value. The first month of the year is
479     * {@code JANUARY}; the last depends on the number of months in a
480     * year.
481     *
482     * @see #JANUARY
483     * @see #FEBRUARY
484     * @see #MARCH
485     * @see #APRIL
486     * @see #MAY
487     * @see #JUNE
488     * @see #JULY
489     * @see #AUGUST
490     * @see #SEPTEMBER
491     * @see #OCTOBER
492     * @see #NOVEMBER
493     * @see #DECEMBER
494     * @see #UNDECIMBER
495     */
496    public static final int MONTH = 2;
497
498    /**
499     * Field number for {@code get} and {@code set} indicating the
500     * week number within the current year. The first week of the year, as
501     * defined by {@code getFirstDayOfWeek()} and
502     * {@code getMinimalDaysInFirstWeek()}, has value 1. Subclasses
503     * define the value of {@code WEEK_OF_YEAR} for days before the first
504     * week of the year.
505     *
506     * @see #getFirstDayOfWeek
507     * @see #getMinimalDaysInFirstWeek
508     */
509    public static final int WEEK_OF_YEAR = 3;
510
511    /**
512     * Field number for {@code get} and {@code set} indicating the
513     * week number within the current month. The first week of the month, as
514     * defined by {@code getFirstDayOfWeek()} and
515     * {@code getMinimalDaysInFirstWeek()}, has value 1. Subclasses
516     * define the value of {@code WEEK_OF_MONTH} for days before the
517     * first week of the month.
518     *
519     * @see #getFirstDayOfWeek
520     * @see #getMinimalDaysInFirstWeek
521     */
522    public static final int WEEK_OF_MONTH = 4;
523
524    /**
525     * Field number for {@code get} and {@code set} indicating the
526     * day of the month. This is a synonym for {@code DAY_OF_MONTH}. The
527     * first day of the month has value 1.
528     *
529     * @see #DAY_OF_MONTH
530     */
531    public static final int DATE = 5;
532
533    /**
534     * Field number for {@code get} and {@code set} indicating the
535     * day of the month. This is a synonym for {@code DATE}. The first
536     * day of the month has value 1.
537     *
538     * @see #DATE
539     */
540    public static final int DAY_OF_MONTH = 5;
541
542    /**
543     * Field number for {@code get} and {@code set} indicating the
544     * day number within the current year. The first day of the year has value
545     * 1.
546     */
547    public static final int DAY_OF_YEAR = 6;
548
549    /**
550     * Field number for {@code get} and {@code set} indicating the
551     * day of the week. This field takes values {@code SUNDAY},
552     * {@code MONDAY}, {@code TUESDAY}, {@code WEDNESDAY},
553     * {@code THURSDAY}, {@code FRIDAY}, and
554     * {@code SATURDAY}.
555     *
556     * @see #SUNDAY
557     * @see #MONDAY
558     * @see #TUESDAY
559     * @see #WEDNESDAY
560     * @see #THURSDAY
561     * @see #FRIDAY
562     * @see #SATURDAY
563     */
564    public static final int DAY_OF_WEEK = 7;
565
566    /**
567     * Field number for {@code get} and {@code set} indicating the
568     * ordinal number of the day of the week within the current month. Together
569     * with the {@code DAY_OF_WEEK} field, this uniquely specifies a day
570     * within a month. Unlike {@code WEEK_OF_MONTH} and
571     * {@code WEEK_OF_YEAR}, this field's value does <em>not</em>
572     * depend on {@code getFirstDayOfWeek()} or
573     * {@code getMinimalDaysInFirstWeek()}. {@code DAY_OF_MONTH 1}
574     * through {@code 7} always correspond to <code>DAY_OF_WEEK_IN_MONTH
575     * 1</code>;
576     * {@code 8} through {@code 15} correspond to
577     * {@code DAY_OF_WEEK_IN_MONTH 2}, and so on.
578     * {@code DAY_OF_WEEK_IN_MONTH 0} indicates the week before
579     * {@code DAY_OF_WEEK_IN_MONTH 1}. Negative values count back from
580     * the end of the month, so the last Sunday of a month is specified as
581     * {@code DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1}. Because
582     * negative values count backward they will usually be aligned differently
583     * within the month than positive values. For example, if a month has 31
584     * days, {@code DAY_OF_WEEK_IN_MONTH -1} will overlap
585     * {@code DAY_OF_WEEK_IN_MONTH 5} and the end of {@code 4}.
586     *
587     * @see #DAY_OF_WEEK
588     * @see #WEEK_OF_MONTH
589     */
590    public static final int DAY_OF_WEEK_IN_MONTH = 8;
591
592    /**
593     * Field number for {@code get} and {@code set} indicating
594     * whether the {@code HOUR} is before or after noon. E.g., at
595     * 10:04:15.250 PM the {@code AM_PM} is {@code PM}.
596     *
597     * @see #AM
598     * @see #PM
599     * @see #HOUR
600     */
601    public static final int AM_PM = 9;
602
603    /**
604     * Field number for {@code get} and {@code set} indicating the
605     * hour of the morning or afternoon. {@code HOUR} is used for the
606     * 12-hour clock. E.g., at 10:04:15.250 PM the {@code HOUR} is 10.
607     *
608     * @see #AM_PM
609     * @see #HOUR_OF_DAY
610     */
611    public static final int HOUR = 10;
612
613    /**
614     * Field number for {@code get} and {@code set} indicating the
615     * hour of the day. {@code HOUR_OF_DAY} is used for the 24-hour
616     * clock. E.g., at 10:04:15.250 PM the {@code HOUR_OF_DAY} is 22.
617     *
618     * @see #HOUR
619     */
620    public static final int HOUR_OF_DAY = 11;
621
622    /**
623     * Field number for {@code get} and {@code set} indicating the
624     * minute within the hour. E.g., at 10:04:15.250 PM the {@code MINUTE}
625     * is 4.
626     */
627    public static final int MINUTE = 12;
628
629    /**
630     * Field number for {@code get} and {@code set} indicating the
631     * second within the minute. E.g., at 10:04:15.250 PM the
632     * {@code SECOND} is 15.
633     */
634    public static final int SECOND = 13;
635
636    /**
637     * Field number for {@code get} and {@code set} indicating the
638     * millisecond within the second. E.g., at 10:04:15.250 PM the
639     * {@code MILLISECOND} is 250.
640     */
641    public static final int MILLISECOND = 14;
642
643    /**
644     * Field number for {@code get} and {@code set} indicating the
645     * raw offset from GMT in milliseconds.
646     */
647    public static final int ZONE_OFFSET = 15;
648
649    /**
650     * Field number for {@code get} and {@code set} indicating the
651     * daylight savings offset in milliseconds.
652     */
653    public static final int DST_OFFSET = 16;
654
655    /**
656     * This is the total number of fields in this calendar.
657     */
658    public static final int FIELD_COUNT = 17;
659
660    /**
661     * Value of the {@code AM_PM} field indicating the period of the day
662     * from midnight to just before noon.
663     */
664    public static final int AM = 0;
665
666    /**
667     * Value of the {@code AM_PM} field indicating the period of the day
668     * from noon to just before midnight.
669     */
670    public static final int PM = 1;
671
672    /**
673     * Requests both {@code SHORT} and {@code LONG} styles in the map returned by
674     * {@link #getDisplayNames}.
675     * @since 1.6
676     */
677    public static final int ALL_STYLES = 0;
678
679    /**
680     * Requests short names (such as "Jan") from
681     * {@link #getDisplayName} or {@link #getDisplayNames}.
682     * @since 1.6
683     */
684    public static final int SHORT = 1;
685
686    /**
687     * Requests long names (such as "January") from
688     * {@link #getDisplayName} or {@link #getDisplayNames}.
689     * @since 1.6
690     */
691    public static final int LONG = 2;
692
693    private static final String[] FIELD_NAMES = { "ERA", "YEAR", "MONTH",
694            "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH", "DAY_OF_YEAR",
695            "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR",
696            "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND",
697            "ZONE_OFFSET", "DST_OFFSET" };
698
699    /**
700     * Constructs a {@code Calendar} instance using the default {@code TimeZone} and {@code Locale}.
701     */
702    protected Calendar() {
703        this(TimeZone.getDefault(), Locale.getDefault());
704    }
705
706    Calendar(TimeZone timezone) {
707        fields = new int[FIELD_COUNT];
708        isSet = new boolean[FIELD_COUNT];
709        areFieldsSet = isTimeSet = false;
710        setLenient(true);
711        setTimeZone(timezone);
712    }
713
714    /**
715     * Constructs a {@code Calendar} instance using the specified {@code TimeZone} and {@code Locale}.
716     *
717     * @param timezone
718     *            the timezone.
719     * @param locale
720     *            the locale.
721     */
722    protected Calendar(TimeZone timezone, Locale locale) {
723        this(timezone);
724        LocaleData localeData = LocaleData.get(locale);
725        setFirstDayOfWeek(localeData.firstDayOfWeek.intValue());
726        setMinimalDaysInFirstWeek(localeData.minimalDaysInFirstWeek.intValue());
727    }
728
729
730    /**
731     * Adds the specified amount to a {@code Calendar} field.
732     *
733     * @param field
734     *            the {@code Calendar} field to modify.
735     * @param value
736     *            the amount to add to the field.
737     * @throws IllegalArgumentException
738     *                if {@code field} is {@code DST_OFFSET} or {@code
739     *                ZONE_OFFSET}.
740     */
741    abstract public void add(int field, int value);
742
743    /**
744     * Returns whether the {@code Date} specified by this {@code Calendar} instance is after the {@code Date}
745     * specified by the parameter. The comparison is not dependent on the time
746     * zones of the {@code Calendar}.
747     *
748     * @param calendar
749     *            the {@code Calendar} instance to compare.
750     * @return {@code true} when this Calendar is after calendar, {@code false} otherwise.
751     * @throws IllegalArgumentException
752     *                if the time is not set and the time cannot be computed
753     *                from the current field values.
754     */
755    public boolean after(Object calendar) {
756        if (!(calendar instanceof Calendar)) {
757            return false;
758        }
759        return getTimeInMillis() > ((Calendar) calendar).getTimeInMillis();
760    }
761
762    /**
763     * Returns whether the {@code Date} specified by this {@code Calendar} instance is before the
764     * {@code Date} specified by the parameter. The comparison is not dependent on the
765     * time zones of the {@code Calendar}.
766     *
767     * @param calendar
768     *            the {@code Calendar} instance to compare.
769     * @return {@code true} when this Calendar is before calendar, {@code false} otherwise.
770     * @throws IllegalArgumentException
771     *                if the time is not set and the time cannot be computed
772     *                from the current field values.
773     */
774    public boolean before(Object calendar) {
775        if (!(calendar instanceof Calendar)) {
776            return false;
777        }
778        return getTimeInMillis() < ((Calendar) calendar).getTimeInMillis();
779    }
780
781    /**
782     * Clears all of the fields of this {@code Calendar}. All fields are initialized to
783     * zero.
784     */
785    public final void clear() {
786        for (int i = 0; i < FIELD_COUNT; i++) {
787            fields[i] = 0;
788            isSet[i] = false;
789        }
790        areFieldsSet = isTimeSet = false;
791    }
792
793    /**
794     * Clears the specified field to zero and sets the isSet flag to {@code false}.
795     *
796     * @param field
797     *            the field to clear.
798     */
799    public final void clear(int field) {
800        fields[field] = 0;
801        isSet[field] = false;
802        areFieldsSet = isTimeSet = false;
803    }
804
805    /**
806     * Returns a new {@code Calendar} with the same properties.
807     *
808     * @return a shallow copy of this {@code Calendar}.
809     *
810     * @see java.lang.Cloneable
811     */
812    @Override
813    public Object clone() {
814        try {
815            Calendar clone = (Calendar) super.clone();
816            clone.fields = fields.clone();
817            clone.isSet = isSet.clone();
818            clone.zone = (TimeZone) zone.clone();
819            return clone;
820        } catch (CloneNotSupportedException e) {
821            throw new AssertionError(e); // android-changed
822        }
823    }
824
825    /**
826     * Computes the time from the fields if the time has not already been set.
827     * Computes the fields from the time if the fields are not already set.
828     *
829     * @throws IllegalArgumentException
830     *                if the time is not set and the time cannot be computed
831     *                from the current field values.
832     */
833    protected void complete() {
834        if (!isTimeSet) {
835            computeTime();
836            isTimeSet = true;
837        }
838        if (!areFieldsSet) {
839            computeFields();
840            areFieldsSet = true;
841        }
842    }
843
844    /**
845     * Computes the {@code Calendar} fields from {@code time}.
846     */
847    protected abstract void computeFields();
848
849    /**
850     * Computes {@code time} from the Calendar fields.
851     *
852     * @throws IllegalArgumentException
853     *                if the time cannot be computed from the current field
854     *                values.
855     */
856    protected abstract void computeTime();
857
858    /**
859     * Compares the specified object to this {@code Calendar} and returns whether they are
860     * equal. The object must be an instance of {@code Calendar} and have the same
861     * properties.
862     *
863     * @param object
864     *            the object to compare with this object.
865     * @return {@code true} if the specified object is equal to this {@code Calendar}, {@code false}
866     *         otherwise.
867     */
868    @Override
869    public boolean equals(Object object) {
870        if (this == object) {
871            return true;
872        }
873        if (!(object instanceof Calendar)) {
874            return false;
875        }
876        Calendar cal = (Calendar) object;
877        return getTimeInMillis() == cal.getTimeInMillis()
878                && isLenient() == cal.isLenient()
879                && getFirstDayOfWeek() == cal.getFirstDayOfWeek()
880                && getMinimalDaysInFirstWeek() == cal
881                        .getMinimalDaysInFirstWeek()
882                && getTimeZone().equals(cal.getTimeZone());
883    }
884
885    /**
886     * Gets the value of the specified field after computing the field values by
887     * calling {@code complete()} first.
888     *
889     * @param field
890     *            the field to get.
891     * @return the value of the specified field.
892     *
893     * @throws IllegalArgumentException
894     *                if the fields are not set, the time is not set, and the
895     *                time cannot be computed from the current field values.
896     * @throws ArrayIndexOutOfBoundsException
897     *                if the field is not inside the range of possible fields.
898     *                The range is starting at 0 up to {@code FIELD_COUNT}.
899     */
900    public int get(int field) {
901        complete();
902        return fields[field];
903    }
904
905    /**
906     * Gets the maximum value of the specified field for the current date.
907     *
908     * @param field
909     *            the field.
910     * @return the maximum value of the specified field.
911     */
912    public int getActualMaximum(int field) {
913        int value, next;
914        if (getMaximum(field) == (next = getLeastMaximum(field))) {
915            return next;
916        }
917        complete();
918        long orgTime = time;
919        set(field, next);
920        do {
921            value = next;
922            roll(field, true);
923            next = get(field);
924        } while (next > value);
925        time = orgTime;
926        areFieldsSet = false;
927        return value;
928    }
929
930    /**
931     * Gets the minimum value of the specified field for the current date.
932     *
933     * @param field
934     *            the field.
935     * @return the minimum value of the specified field.
936     */
937    public int getActualMinimum(int field) {
938        int value, next;
939        if (getMinimum(field) == (next = getGreatestMinimum(field))) {
940            return next;
941        }
942        complete();
943        long orgTime = time;
944        set(field, next);
945        do {
946            value = next;
947            roll(field, false);
948            next = get(field);
949        } while (next < value);
950        time = orgTime;
951        areFieldsSet = false;
952        return value;
953    }
954
955    /**
956     * Returns an array of locales for which custom {@code Calendar} instances
957     * are available.
958     * <p>Note that Android does not support user-supplied locale service providers.
959     */
960    public static synchronized Locale[] getAvailableLocales() {
961        return ICU.getAvailableCalendarLocales();
962    }
963
964    /**
965     * Gets the first day of the week for this {@code Calendar}.
966     *
967     * @return the first day of the week.
968     */
969    public int getFirstDayOfWeek() {
970        return firstDayOfWeek;
971    }
972
973    /**
974     * Gets the greatest minimum value of the specified field. This is the
975     * biggest value that {@code getActualMinimum} can return for any possible
976     * time.
977     *
978     * @param field
979     *            the field.
980     * @return the greatest minimum value of the specified field.
981     */
982    abstract public int getGreatestMinimum(int field);
983
984    /**
985     * Constructs a new instance of the {@code Calendar} subclass appropriate for the
986     * default {@code Locale}.
987     *
988     * @return a {@code Calendar} subclass instance set to the current date and time in
989     *         the default {@code Timezone}.
990     */
991    public static synchronized Calendar getInstance() {
992        return new GregorianCalendar();
993    }
994
995    /**
996     * Constructs a new instance of the {@code Calendar} subclass appropriate for the
997     * specified {@code Locale}.
998     *
999     * @param locale
1000     *            the locale to use.
1001     * @return a {@code Calendar} subclass instance set to the current date and time.
1002     */
1003    public static synchronized Calendar getInstance(Locale locale) {
1004        return new GregorianCalendar(locale);
1005    }
1006
1007    /**
1008     * Constructs a new instance of the {@code Calendar} subclass appropriate for the
1009     * default {@code Locale}, using the specified {@code TimeZone}.
1010     *
1011     * @param timezone
1012     *            the {@code TimeZone} to use.
1013     * @return a {@code Calendar} subclass instance set to the current date and time in
1014     *         the specified timezone.
1015     */
1016    public static synchronized Calendar getInstance(TimeZone timezone) {
1017        return new GregorianCalendar(timezone);
1018    }
1019
1020    /**
1021     * Constructs a new instance of the {@code Calendar} subclass appropriate for the
1022     * specified {@code Locale}.
1023     *
1024     * @param timezone
1025     *            the {@code TimeZone} to use.
1026     * @param locale
1027     *            the {@code Locale} to use.
1028     * @return a {@code Calendar} subclass instance set to the current date and time in
1029     *         the specified timezone.
1030     */
1031    public static synchronized Calendar getInstance(TimeZone timezone,
1032            Locale locale) {
1033        return new GregorianCalendar(timezone, locale);
1034    }
1035
1036    /**
1037     * Gets the smallest maximum value of the specified field. This is the
1038     * smallest value that {@code getActualMaximum()} can return for any
1039     * possible time.
1040     *
1041     * @param field
1042     *            the field number.
1043     * @return the smallest maximum value of the specified field.
1044     */
1045    abstract public int getLeastMaximum(int field);
1046
1047    /**
1048     * Gets the greatest maximum value of the specified field. This returns the
1049     * biggest value that {@code get} can return for the specified field.
1050     *
1051     * @param field
1052     *            the field.
1053     * @return the greatest maximum value of the specified field.
1054     */
1055    abstract public int getMaximum(int field);
1056
1057    /**
1058     * Gets the minimal days in the first week of the year.
1059     *
1060     * @return the minimal days in the first week of the year.
1061     */
1062    public int getMinimalDaysInFirstWeek() {
1063        return minimalDaysInFirstWeek;
1064    }
1065
1066    /**
1067     * Gets the smallest minimum value of the specified field. this returns the
1068     * smallest value thet {@code get} can return for the specified field.
1069     *
1070     * @param field
1071     *            the field number.
1072     * @return the smallest minimum value of the specified field.
1073     */
1074    abstract public int getMinimum(int field);
1075
1076    /**
1077     * Gets the time of this {@code Calendar} as a {@code Date} object.
1078     *
1079     * @return a new {@code Date} initialized to the time of this {@code Calendar}.
1080     *
1081     * @throws IllegalArgumentException
1082     *                if the time is not set and the time cannot be computed
1083     *                from the current field values.
1084     */
1085    public final Date getTime() {
1086        return new Date(getTimeInMillis());
1087    }
1088
1089    /**
1090     * Computes the time from the fields if required and returns the time.
1091     *
1092     * @return the time of this {@code Calendar}.
1093     *
1094     * @throws IllegalArgumentException
1095     *                if the time is not set and the time cannot be computed
1096     *                from the current field values.
1097     */
1098    public long getTimeInMillis() {
1099        if (!isTimeSet) {
1100            computeTime();
1101            isTimeSet = true;
1102        }
1103        return time;
1104    }
1105
1106    /**
1107     * Gets the timezone of this {@code Calendar}.
1108     *
1109     * @return the {@code TimeZone} used by this {@code Calendar}.
1110     */
1111    public TimeZone getTimeZone() {
1112        return zone;
1113    }
1114
1115    /**
1116     * Returns an integer hash code for the receiver. Objects which are equal
1117     * return the same value for this method.
1118     *
1119     * @return the receiver's hash.
1120     *
1121     * @see #equals
1122     */
1123    @Override
1124    public int hashCode() {
1125        return (isLenient() ? 1237 : 1231) + getFirstDayOfWeek()
1126                + getMinimalDaysInFirstWeek() + getTimeZone().hashCode();
1127    }
1128
1129    /**
1130     * Gets the value of the specified field without recomputing.
1131     *
1132     * @param field
1133     *            the field.
1134     * @return the value of the specified field.
1135     */
1136    protected final int internalGet(int field) {
1137        return fields[field];
1138    }
1139
1140    /**
1141     * Returns if this {@code Calendar} accepts field values which are outside the valid
1142     * range for the field.
1143     *
1144     * @return {@code true} if this {@code Calendar} is lenient, {@code false} otherwise.
1145     */
1146    public boolean isLenient() {
1147        return lenient;
1148    }
1149
1150    /**
1151     * Returns whether the specified field is set. Note that the interpretation of "is set" is
1152     * somewhat technical. In particular, it does <i>not</i> mean that the field's value is up
1153     * to date. If you want to know whether a field contains an up-to-date value, you must also
1154     * check {@code areFieldsSet}, making this method somewhat useless unless you're a subclass,
1155     * in which case you can access the {@code isSet} array directly.
1156     * <p>
1157     * A field remains "set" from the first time its value is computed until it's cleared by one
1158     * of the {@code clear} methods. Thus "set" does not mean "valid". You probably want to call
1159     * {@code get} -- which will update fields as necessary -- rather than try to make use of
1160     * this method.
1161     *
1162     * @param field
1163     *            a {@code Calendar} field number.
1164     * @return {@code true} if the specified field is set, {@code false} otherwise.
1165     */
1166    public final boolean isSet(int field) {
1167        return isSet[field];
1168    }
1169
1170    /**
1171     * Adds the specified amount to the specified field and wraps the value of
1172     * the field when it goes beyond the maximum or minimum value for the
1173     * current date. Other fields will be adjusted as required to maintain a
1174     * consistent date.
1175     *
1176     * @param field
1177     *            the field to roll.
1178     * @param value
1179     *            the amount to add.
1180     */
1181    public void roll(int field, int value) {
1182        boolean increment = value >= 0;
1183        int count = increment ? value : -value;
1184        for (int i = 0; i < count; i++) {
1185            roll(field, increment);
1186        }
1187    }
1188
1189    /**
1190     * Increment or decrement the specified field and wrap the value of the
1191     * field when it goes beyond the maximum or minimum value for the current
1192     * date. Other fields will be adjusted as required to maintain a consistent
1193     * date.
1194     *
1195     * @param field
1196     *            the number indicating the field to roll.
1197     * @param increment
1198     *            {@code true} to increment the field, {@code false} to decrement.
1199     */
1200    abstract public void roll(int field, boolean increment);
1201
1202    /**
1203     * Sets a field to the specified value.
1204     *
1205     * @param field
1206     *            the code indicating the {@code Calendar} field to modify.
1207     * @param value
1208     *            the value.
1209     */
1210    public void set(int field, int value) {
1211        fields[field] = value;
1212        isSet[field] = true;
1213        areFieldsSet = isTimeSet = false;
1214        if (field > MONTH && field < AM_PM) {
1215            lastDateFieldSet = field;
1216        }
1217        if (field == HOUR || field == HOUR_OF_DAY) {
1218            lastTimeFieldSet = field;
1219        }
1220        if (field == AM_PM) {
1221            lastTimeFieldSet = HOUR;
1222        }
1223    }
1224
1225    /**
1226     * Sets the year, month and day of the month fields. Other fields are not
1227     * changed.
1228     *
1229     * @param year
1230     *            the year.
1231     * @param month
1232     *            the month.
1233     * @param day
1234     *            the day of the month.
1235     */
1236    public final void set(int year, int month, int day) {
1237        set(YEAR, year);
1238        set(MONTH, month);
1239        set(DATE, day);
1240    }
1241
1242    /**
1243     * Sets the year, month, day of the month, hour of day and minute fields.
1244     * Other fields are not changed.
1245     *
1246     * @param year
1247     *            the year.
1248     * @param month
1249     *            the month.
1250     * @param day
1251     *            the day of the month.
1252     * @param hourOfDay
1253     *            the hour of day.
1254     * @param minute
1255     *            the minute.
1256     */
1257    public final void set(int year, int month, int day, int hourOfDay,
1258            int minute) {
1259        set(year, month, day);
1260        set(HOUR_OF_DAY, hourOfDay);
1261        set(MINUTE, minute);
1262    }
1263
1264    /**
1265     * Sets the year, month, day of the month, hour of day, minute and second
1266     * fields. Other fields are not changed.
1267     *
1268     * @param year
1269     *            the year.
1270     * @param month
1271     *            the month.
1272     * @param day
1273     *            the day of the month.
1274     * @param hourOfDay
1275     *            the hour of day.
1276     * @param minute
1277     *            the minute.
1278     * @param second
1279     *            the second.
1280     */
1281    public final void set(int year, int month, int day, int hourOfDay,
1282            int minute, int second) {
1283        set(year, month, day, hourOfDay, minute);
1284        set(SECOND, second);
1285    }
1286
1287    /**
1288     * Sets the first day of the week for this {@code Calendar}.
1289     *
1290     * @param value
1291     *            a {@code Calendar} day of the week.
1292     */
1293    public void setFirstDayOfWeek(int value) {
1294        firstDayOfWeek = value;
1295    }
1296
1297    /**
1298     * Sets this {@code Calendar} to accept field values which are outside the valid
1299     * range for the field.
1300     *
1301     * @param value
1302     *            a boolean value.
1303     */
1304    public void setLenient(boolean value) {
1305        lenient = value;
1306    }
1307
1308    /**
1309     * Sets the minimal days in the first week of the year.
1310     *
1311     * @param value
1312     *            the minimal days in the first week of the year.
1313     */
1314    public void setMinimalDaysInFirstWeek(int value) {
1315        minimalDaysInFirstWeek = value;
1316    }
1317
1318    /**
1319     * Sets the time of this {@code Calendar}.
1320     *
1321     * @param date
1322     *            a {@code Date} object.
1323     */
1324    public final void setTime(Date date) {
1325        setTimeInMillis(date.getTime());
1326    }
1327
1328    /**
1329     * Sets the time of this {@code Calendar}.
1330     *
1331     * @param milliseconds
1332     *            the time as the number of milliseconds since Jan. 1, 1970.
1333     */
1334    public void setTimeInMillis(long milliseconds) {
1335        if (!isTimeSet || !areFieldsSet || time != milliseconds) {
1336            time = milliseconds;
1337            isTimeSet = true;
1338            areFieldsSet = false;
1339            complete();
1340        }
1341    }
1342
1343    /**
1344     * Sets the {@code TimeZone} used by this Calendar.
1345     *
1346     * @param timezone
1347     *            a {@code TimeZone}.
1348     */
1349    public void setTimeZone(TimeZone timezone) {
1350        zone = timezone;
1351        areFieldsSet = false;
1352    }
1353
1354    /**
1355     * Returns the string representation of this {@code Calendar}.
1356     *
1357     * @return the string representation of this {@code Calendar}.
1358     */
1359    @Override
1360    @SuppressWarnings("nls")
1361    public String toString() {
1362        StringBuilder result = new StringBuilder(getClass().getName() + "[time="
1363                + (isTimeSet ? String.valueOf(time) : "?")
1364                + ",areFieldsSet="
1365                + areFieldsSet
1366                + // ",areAllFieldsSet=" + areAllFieldsSet +
1367                ",lenient=" + lenient + ",zone=" + zone + ",firstDayOfWeek="
1368                + firstDayOfWeek + ",minimalDaysInFirstWeek="
1369                + minimalDaysInFirstWeek);
1370        for (int i = 0; i < FIELD_COUNT; i++) {
1371            result.append(',');
1372            result.append(FIELD_NAMES[i]);
1373            result.append('=');
1374            if (isSet[i]) {
1375                result.append(fields[i]);
1376            } else {
1377                result.append('?');
1378            }
1379        }
1380        result.append(']');
1381        return result.toString();
1382    }
1383
1384    /**
1385     * Compares the times of the two {@code Calendar}, which represent the milliseconds
1386     * from the January 1, 1970 00:00:00.000 GMT (Gregorian).
1387     *
1388     * @param anotherCalendar
1389     *            another calendar that this one is compared with.
1390     * @return 0 if the times of the two {@code Calendar}s are equal, -1 if the time of
1391     *         this {@code Calendar} is before the other one, 1 if the time of this
1392     *         {@code Calendar} is after the other one.
1393     * @throws NullPointerException
1394     *             if the argument is null.
1395     * @throws IllegalArgumentException
1396     *             if the argument does not include a valid time
1397     *             value.
1398     */
1399    public int compareTo(Calendar anotherCalendar) {
1400        if (null == anotherCalendar) {
1401            throw new NullPointerException();
1402        }
1403        long timeInMillis = getTimeInMillis();
1404        long anotherTimeInMillis = anotherCalendar.getTimeInMillis();
1405        if (timeInMillis > anotherTimeInMillis) {
1406            return 1;
1407        }
1408        if (timeInMillis == anotherTimeInMillis) {
1409            return 0;
1410        }
1411        return -1;
1412    }
1413
1414    /**
1415     * Returns a human-readable string for the value of {@code field}
1416     * using the given style and locale. If no string is available, returns null.
1417     * The value is retrieved by invoking {@code get(field)}.
1418     *
1419     * <p>For example, {@code getDisplayName(MONTH, SHORT, Locale.US)} will return "Jan"
1420     * while {@code getDisplayName(MONTH, LONG, Locale.US)} will return "January".
1421     *
1422     * @param field the field
1423     * @param style {@code SHORT} or {@code LONG}
1424     * @param locale the locale
1425     * @return the display name, or null
1426     * @throws NullPointerException if {@code locale == null}
1427     * @throws IllegalArgumentException if {@code field} or {@code style} is invalid
1428     * @since 1.6
1429     */
1430    public String getDisplayName(int field, int style, Locale locale) {
1431        // TODO: the RI's documentation says ALL_STYLES is invalid, but actually treats it as SHORT.
1432        if (style == ALL_STYLES) {
1433            style = SHORT;
1434        }
1435        String[] array = getDisplayNameArray(field, style, locale);
1436        int value = get(field);
1437        return (array != null) ? array[value] : null;
1438    }
1439
1440    private String[] getDisplayNameArray(int field, int style, Locale locale) {
1441        if (field < 0 || field >= FIELD_COUNT) {
1442            throw new IllegalArgumentException("bad field " + field);
1443        }
1444        checkStyle(style);
1445        DateFormatSymbols dfs = DateFormatSymbols.getInstance(locale);
1446        switch (field) {
1447        case AM_PM:
1448            return dfs.getAmPmStrings();
1449        case DAY_OF_WEEK:
1450            return (style == LONG) ? dfs.getWeekdays() : dfs.getShortWeekdays();
1451        case ERA:
1452            return dfs.getEras();
1453        case MONTH:
1454            return (style == LONG) ? dfs.getMonths() : dfs.getShortMonths();
1455        }
1456        return null;
1457    }
1458
1459    private static void checkStyle(int style) {
1460        if (style != ALL_STYLES && style != SHORT && style != LONG) {
1461            throw new IllegalArgumentException("bad style " + style);
1462        }
1463    }
1464
1465    /**
1466     * Returns a map of human-readable strings to corresponding values,
1467     * for the given field, style, and locale.
1468     * Returns null if no strings are available.
1469     *
1470     * <p>For example, {@code getDisplayNames(MONTH, ALL_STYLES, Locale.US)} would
1471     * contain mappings from "Jan" and "January" to {@link #JANUARY}, and so on.
1472     *
1473     * @param field the field
1474     * @param style {@code SHORT}, {@code LONG}, or {@code ALL_STYLES}
1475     * @param locale the locale
1476     * @return the display name, or null
1477     * @throws NullPointerException if {@code locale == null}
1478     * @throws IllegalArgumentException if {@code field} or {@code style} is invalid
1479     * @since 1.6
1480     */
1481    public Map<String, Integer> getDisplayNames(int field, int style, Locale locale) {
1482        checkStyle(style);
1483        complete();
1484        Map<String, Integer> result = new HashMap<String, Integer>();
1485        if (style == SHORT || style == ALL_STYLES) {
1486            insertValuesInMap(result, getDisplayNameArray(field, SHORT, locale));
1487        }
1488        if (style == LONG || style == ALL_STYLES) {
1489            insertValuesInMap(result, getDisplayNameArray(field, LONG, locale));
1490        }
1491        return result.isEmpty() ? null : result;
1492    }
1493
1494    private static void insertValuesInMap(Map<String, Integer> map, String[] values) {
1495        if (values == null) {
1496            return;
1497        }
1498        for (int i = 0; i < values.length; ++i) {
1499            if (values[i] != null && !values[i].isEmpty()) {
1500                map.put(values[i], i);
1501            }
1502        }
1503    }
1504
1505    @SuppressWarnings("nls")
1506    private static final ObjectStreamField[] serialPersistentFields = {
1507            new ObjectStreamField("areFieldsSet", Boolean.TYPE),
1508            new ObjectStreamField("fields", int[].class),
1509            new ObjectStreamField("firstDayOfWeek", Integer.TYPE),
1510            new ObjectStreamField("isSet", boolean[].class),
1511            new ObjectStreamField("isTimeSet", Boolean.TYPE),
1512            new ObjectStreamField("lenient", Boolean.TYPE),
1513            new ObjectStreamField("minimalDaysInFirstWeek", Integer.TYPE),
1514            new ObjectStreamField("nextStamp", Integer.TYPE),
1515            new ObjectStreamField("serialVersionOnStream", Integer.TYPE),
1516            new ObjectStreamField("time", Long.TYPE),
1517            new ObjectStreamField("zone", TimeZone.class), };
1518
1519    @SuppressWarnings("nls")
1520    private void writeObject(ObjectOutputStream stream) throws IOException {
1521        complete();
1522        ObjectOutputStream.PutField putFields = stream.putFields();
1523        putFields.put("areFieldsSet", areFieldsSet);
1524        putFields.put("fields", this.fields);
1525        putFields.put("firstDayOfWeek", firstDayOfWeek);
1526        putFields.put("isSet", isSet);
1527        putFields.put("isTimeSet", isTimeSet);
1528        putFields.put("lenient", lenient);
1529        putFields.put("minimalDaysInFirstWeek", minimalDaysInFirstWeek);
1530        putFields.put("nextStamp", 2 /* MINIMUM_USER_STAMP */);
1531        putFields.put("serialVersionOnStream", 1);
1532        putFields.put("time", time);
1533        putFields.put("zone", zone);
1534        stream.writeFields();
1535    }
1536
1537    @SuppressWarnings("nls")
1538    private void readObject(ObjectInputStream stream) throws IOException,
1539            ClassNotFoundException {
1540        ObjectInputStream.GetField readFields = stream.readFields();
1541        areFieldsSet = readFields.get("areFieldsSet", false);
1542        this.fields = (int[]) readFields.get("fields", null);
1543        firstDayOfWeek = readFields.get("firstDayOfWeek", Calendar.SUNDAY);
1544        isSet = (boolean[]) readFields.get("isSet", null);
1545        isTimeSet = readFields.get("isTimeSet", false);
1546        lenient = readFields.get("lenient", true);
1547        minimalDaysInFirstWeek = readFields.get("minimalDaysInFirstWeek", 1);
1548        time = readFields.get("time", 0L);
1549        zone = (TimeZone) readFields.get("zone", null);
1550    }
1551}
1552