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