Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / classpath / java / util / Calendar.java
blobf94bed40dade8d839a00f68e4dec62808dfcd74b
1 /* Calendar.java --
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.util;
41 import java.io.IOException;
42 import java.io.ObjectInputStream;
43 import java.io.ObjectOutputStream;
44 import java.io.Serializable;
45 import java.lang.reflect.Constructor;
46 import java.lang.reflect.InvocationTargetException;
48 /**
49 * This class is an abstract base class for Calendars, which can be
50 * used to convert between <code>Date</code> objects and a set of
51 * integer fields which represent <code>YEAR</code>,
52 * <code>MONTH</code>, <code>DAY</code>, etc. The <code>Date</code>
53 * object represents a time in milliseconds since the Epoch. <br>
55 * This class is locale sensitive. To get the Object matching the
56 * current locale you can use <code>getInstance</code>. You can even provide
57 * a locale or a timezone. <code>getInstance</code> returns currently
58 * a <code>GregorianCalendar</code> for the current date. <br>
60 * If you want to convert a date from the Year, Month, Day, DayOfWeek,
61 * etc. Representation to a <code>Date</code>-Object, you can create
62 * a new Calendar with <code>getInstance()</code>,
63 * <code>clear()</code> all fields, <code>set(int,int)</code> the
64 * fields you need and convert it with <code>getTime()</code>. <br>
66 * If you want to convert a <code>Date</code>-object to the Calendar
67 * representation, create a new Calendar, assign the
68 * <code>Date</code>-Object with <code>setTime()</code>, and read the
69 * fields with <code>get(int)</code>. <br>
71 * When computing the date from time fields, it may happen, that there
72 * are either two few fields set, or some fields are inconsistent. This
73 * cases will handled in a calendar specific way. Missing fields are
74 * replaced by the fields of the epoch: 1970 January 1 00:00. <br>
76 * To understand, how the day of year is computed out of the fields
77 * look at the following table. It is traversed from top to bottom,
78 * and for the first line all fields are set, that line is used to
79 * compute the day. <br>
82 <pre>month + day_of_month
83 month + week_of_month + day_of_week
84 month + day_of_week_of_month + day_of_week
85 day_of_year
86 day_of_week + week_of_year</pre>
88 * The hour_of_day-field takes precedence over the ampm and
89 * hour_of_ampm fields. <br>
91 * <STRONG>Note:</STRONG> This can differ for non-Gregorian calendar. <br>
93 * To convert a calendar to a human readable form and vice versa, use
94 * the <code>java.text.DateFormat</code> class. <br>
96 * Other useful things you can do with an calendar, is
97 * <code>roll</code>ing fields (that means increase/decrease a
98 * specific field by one, propagating overflows), or
99 * <code>add</code>ing/substracting a fixed amount to a field.
101 * @see Date
102 * @see GregorianCalendar
103 * @see TimeZone
104 * @see java.text.DateFormat
106 public abstract class Calendar implements Serializable, Cloneable
109 * Constant representing the era time field.
111 public static final int ERA = 0;
114 * Constant representing the year time field.
116 public static final int YEAR = 1;
119 * Constant representing the month time field. This field
120 * should contain one of the JANUARY,...,DECEMBER constants below.
122 public static final int MONTH = 2;
125 * Constant representing the week of the year field.
126 * @see #setFirstDayOfWeek(int)
128 public static final int WEEK_OF_YEAR = 3;
131 * Constant representing the week of the month time field.
132 * @see #setFirstDayOfWeek(int)
134 public static final int WEEK_OF_MONTH = 4;
137 * Constant representing the day time field, synonym for DAY_OF_MONTH.
139 public static final int DATE = 5;
142 * Constant representing the day time field.
144 public static final int DAY_OF_MONTH = 5;
147 * Constant representing the day of year time field. This is
148 * 1 for the first day in month.
150 public static final int DAY_OF_YEAR = 6;
153 * Constant representing the day of week time field. This field
154 * should contain one of the SUNDAY,...,SATURDAY constants below.
156 public static final int DAY_OF_WEEK = 7;
159 * Constant representing the day-of-week-in-month field. For
160 * instance this field contains 2 for the second thursday in a
161 * month. If you give a negative number here, the day will count
162 * from the end of the month.
164 public static final int DAY_OF_WEEK_IN_MONTH = 8;
167 * Constant representing the part of the day for 12-hour clock. This
168 * should be one of AM or PM.
170 public static final int AM_PM = 9;
173 * Constant representing the hour time field for 12-hour clock.
175 public static final int HOUR = 10;
178 * Constant representing the hour of day time field for 24-hour clock.
180 public static final int HOUR_OF_DAY = 11;
183 * Constant representing the minute of hour time field.
185 public static final int MINUTE = 12;
188 * Constant representing the second time field.
190 public static final int SECOND = 13;
193 * Constant representing the millisecond time field.
195 public static final int MILLISECOND = 14;
198 * Constant representing the time zone offset time field for the
199 * time given in the other fields. It is measured in
200 * milliseconds. The default is the offset of the time zone.
202 public static final int ZONE_OFFSET = 15;
205 * Constant representing the daylight saving time offset in
206 * milliseconds. The default is the value given by the time zone.
208 public static final int DST_OFFSET = 16;
211 * Number of time fields.
213 public static final int FIELD_COUNT = 17;
216 * Constant representing Sunday.
218 public static final int SUNDAY = 1;
221 * Constant representing Monday.
223 public static final int MONDAY = 2;
226 * Constant representing Tuesday.
228 public static final int TUESDAY = 3;
231 * Constant representing Wednesday.
233 public static final int WEDNESDAY = 4;
236 * Constant representing Thursday.
238 public static final int THURSDAY = 5;
241 * Constant representing Friday.
243 public static final int FRIDAY = 6;
246 * Constant representing Saturday.
248 public static final int SATURDAY = 7;
251 * Constant representing January.
253 public static final int JANUARY = 0;
256 * Constant representing February.
258 public static final int FEBRUARY = 1;
261 * Constant representing March.
263 public static final int MARCH = 2;
266 * Constant representing April.
268 public static final int APRIL = 3;
271 * Constant representing May.
273 public static final int MAY = 4;
276 * Constant representing June.
278 public static final int JUNE = 5;
281 * Constant representing July.
283 public static final int JULY = 6;
286 * Constant representing August.
288 public static final int AUGUST = 7;
291 * Constant representing September.
293 public static final int SEPTEMBER = 8;
296 * Constant representing October.
298 public static final int OCTOBER = 9;
301 * Constant representing November.
303 public static final int NOVEMBER = 10;
306 * Constant representing December.
308 public static final int DECEMBER = 11;
311 * Constant representing Undecimber. This is an artificial name useful
312 * for lunar calendars.
314 public static final int UNDECIMBER = 12;
317 * Useful constant for 12-hour clock.
319 public static final int AM = 0;
322 * Useful constant for 12-hour clock.
324 public static final int PM = 1;
327 * The time fields. The array is indexed by the constants YEAR to
328 * DST_OFFSET.
329 * @serial
331 protected int[] fields = new int[FIELD_COUNT];
334 * The flags which tell if the fields above have a value.
335 * @serial
337 protected boolean[] isSet = new boolean[FIELD_COUNT];
340 * The time in milliseconds since the epoch.
341 * @serial
343 protected long time;
346 * Tells if the above field has a valid value.
347 * @serial
349 protected boolean isTimeSet;
352 * Tells if the fields have a valid value. This superseeds the isSet
353 * array.
354 * @serial
356 protected boolean areFieldsSet;
359 * The time zone of this calendar. Used by sub classes to do UTC / local
360 * time conversion. Sub classes can access this field with getTimeZone().
361 * @serial
363 private TimeZone zone;
366 * This is the default calendar class, that is returned on
367 * java.util.Calendar.getInstance().
368 * XXX - this isn't localized anywhere, is it?
369 * @see java.util.Calendar#getInstance()
371 private static final String calendarClassName = "java.util.GregorianCalendar";
374 * Specifies if the date/time interpretation should be lenient.
375 * If the flag is set, a date such as "February 30, 1996" will be
376 * treated as the 29th day after the February 1. If this flag
377 * is false, such dates will cause an exception.
378 * @serial
380 private boolean lenient;
383 * Sets what the first day of week is. This is used for
384 * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
385 * @serial
387 private int firstDayOfWeek;
390 * Sets how many days are required in the first week of the year.
391 * If the first day of the year should be the first week you should
392 * set this value to 1. If the first week must be a full week, set
393 * it to 7.
394 * @serial
396 private int minimalDaysInFirstWeek;
399 * Is set to true if DST_OFFSET is explicitly set. In that case
400 * it's value overrides the value computed from the current
401 * time and the timezone.
403 private boolean explicitDSTOffset = false;
406 * The version of the serialized data on the stream.
407 * <dl><dt>0 or not present</dt>
408 * <dd> JDK 1.1.5 or later.</dd>
409 * <dt>1</dt>
410 * <dd>JDK 1.1.6 or later. This always writes a correct `time' value
411 * on the stream, as well as the other fields, to be compatible with
412 * earlier versions</dd></dl>
413 * @since JDK1.1.6
414 * @serial
416 private int serialVersionOnStream = 1;
419 * XXX - I have not checked the compatibility. The documentation of
420 * the serialized-form is quite hairy...
422 static final long serialVersionUID = -1807547505821590642L;
425 * The name of the resource bundle. Used only by getBundle()
427 private static final String bundleName = "gnu.java.locale.LocaleInformation";
430 * get resource bundle:
431 * The resources should be loaded via this method only. Iff an application
432 * uses this method, the resourcebundle is required.
434 private static ResourceBundle getBundle(Locale locale)
436 return ResourceBundle.getBundle(bundleName, locale,
437 ClassLoader.getSystemClassLoader());
441 * Constructs a new Calendar with the default time zone and the default
442 * locale.
444 protected Calendar()
446 this(TimeZone.getDefault(), Locale.getDefault());
450 * Constructs a new Calendar with the given time zone and the given
451 * locale.
452 * @param zone a time zone.
453 * @param locale a locale.
455 protected Calendar(TimeZone zone, Locale locale)
457 this.zone = zone;
458 lenient = true;
459 String[] days = { "", "sun", "mon", "tue", "wed", "thu", "fri", "sat" };
461 ResourceBundle rb = getBundle(locale);
462 String min = (String) rb.getObject("minNumberOfDaysInFirstWeek");
463 String first = (String) rb.getObject("firstDayOfWeek");
466 if (min != null)
467 minimalDaysInFirstWeek = Integer.parseInt(min);
469 catch (NumberFormatException ex)
471 minimalDaysInFirstWeek = 1;
474 firstDayOfWeek = 1;
475 if (first != null)
476 for (int i = 0; i < 8; i++)
477 if (days[i].equals(first))
478 firstDayOfWeek = i;
480 clear();
484 * Creates a calendar representing the actual time, using the default
485 * time zone and locale.
487 public static synchronized Calendar getInstance()
489 return getInstance(TimeZone.getDefault(), Locale.getDefault());
493 * Creates a calendar representing the actual time, using the given
494 * time zone and the default locale.
495 * @param zone a time zone.
497 public static synchronized Calendar getInstance(TimeZone zone)
499 return getInstance(zone, Locale.getDefault());
503 * Creates a calendar representing the actual time, using the default
504 * time zone and the given locale.
505 * @param locale a locale.
507 public static synchronized Calendar getInstance(Locale locale)
509 return getInstance(TimeZone.getDefault(), locale);
513 * Cache of locale->calendar-class mappings. This avoids having to do a ResourceBundle
514 * lookup for every getInstance call.
516 private static HashMap cache = new HashMap();
518 /** Preset argument types for calendar-class constructor lookup. */
519 private static Class[] ctorArgTypes = new Class[]
521 TimeZone.class, Locale.class
525 * Creates a calendar representing the actual time, using the given
526 * time zone and locale.
527 * @param zone a time zone.
528 * @param locale a locale.
530 public static synchronized Calendar getInstance(TimeZone zone, Locale locale)
532 Class calendarClass = (Class) cache.get(locale);
533 Throwable exception = null;
537 if (calendarClass == null)
539 calendarClass = Class.forName(calendarClassName);
540 if (Calendar.class.isAssignableFrom(calendarClass))
541 cache.put(locale, calendarClass);
544 // GregorianCalendar is by far the most common case. Optimize by
545 // avoiding reflection.
546 if (calendarClass == GregorianCalendar.class)
547 return new GregorianCalendar(zone, locale);
549 if (Calendar.class.isAssignableFrom(calendarClass))
551 Constructor ctor = calendarClass.getConstructor(ctorArgTypes);
552 return (Calendar) ctor.newInstance(new Object[] { zone, locale });
555 catch (ClassNotFoundException ex)
557 exception = ex;
559 catch (IllegalAccessException ex)
561 exception = ex;
563 catch (NoSuchMethodException ex)
565 exception = ex;
567 catch (InstantiationException ex)
569 exception = ex;
571 catch (InvocationTargetException ex)
573 exception = ex;
576 throw new RuntimeException("Error instantiating calendar for locale "
577 + locale, exception);
581 * Gets the set of locales for which a Calendar is available.
582 * @exception MissingResourceException if locale data couldn't be found.
583 * @return the set of locales.
585 public static synchronized Locale[] getAvailableLocales()
587 ResourceBundle rb = getBundle(new Locale("", ""));
588 return (Locale[]) rb.getObject("availableLocales");
592 * Converts the time field values (<code>fields</code>) to
593 * milliseconds since the epoch UTC (<code>time</code>). Override
594 * this method if you write your own Calendar. */
595 protected abstract void computeTime();
598 * Converts the milliseconds since the epoch UTC
599 * (<code>time</code>) to time fields
600 * (<code>fields</code>). Override this method if you write your
601 * own Calendar.
603 protected abstract void computeFields();
606 * Converts the time represented by this object to a
607 * <code>Date</code>-Object.
608 * @return the Date.
610 public final Date getTime()
612 if (! isTimeSet)
613 computeTime();
614 return new Date(time);
618 * Sets this Calendar's time to the given Date. All time fields
619 * are invalidated by this method.
621 public final void setTime(Date date)
623 setTimeInMillis(date.getTime());
627 * Returns the time represented by this Calendar.
628 * @return the time in milliseconds since the epoch.
629 * @specnote This was made public in 1.4.
631 public long getTimeInMillis()
633 if (! isTimeSet)
634 computeTime();
635 return time;
639 * Sets this Calendar's time to the given Time. All time fields
640 * are invalidated by this method.
641 * @param time the time in milliseconds since the epoch
642 * @specnote This was made public in 1.4.
644 public void setTimeInMillis(long time)
646 clear();
647 this.time = time;
648 isTimeSet = true;
649 computeFields();
653 * Gets the value of the specified field. They are recomputed
654 * if they are invalid.
655 * @param field the time field. One of the time field constants.
656 * @return the value of the specified field
657 * @throws ArrayIndexOutOfBoundsException if the field is outside
658 * the valid range. The value of field must be >= 0 and
659 * <= <code>FIELD_COUNT</code>.
660 * @specnote Not final since JDK 1.4
662 public int get(int field)
664 // If the requested field is invalid, force all fields to be recomputed.
665 if (! isSet[field])
666 areFieldsSet = false;
667 complete();
668 return fields[field];
672 * Gets the value of the specified field. This method doesn't
673 * recompute the fields, if they are invalid.
674 * @param field the time field. One of the time field constants.
675 * @return the value of the specified field, undefined if
676 * <code>areFieldsSet</code> or <code>isSet[field]</code> is false.
677 * @throws ArrayIndexOutOfBoundsException if the field is outside
678 * the valid range. The value of field must be >= 0 and
679 * <= <code>FIELD_COUNT</code>.
681 protected final int internalGet(int field)
683 return fields[field];
687 * Sets the time field with the given value. This does invalidate
688 * the time in milliseconds.
689 * @param field the time field. One of the time field constants
690 * @param value the value to be set.
691 * @throws ArrayIndexOutOfBoundsException if field is outside
692 * the valid range. The value of field must be >= 0 and
693 * <= <code>FIELD_COUNT</code>.
694 * @specnote Not final since JDK 1.4
696 public void set(int field, int value)
698 if (isTimeSet)
699 for (int i = 0; i < FIELD_COUNT; i++)
700 isSet[i] = false;
701 isTimeSet = false;
702 fields[field] = value;
703 isSet[field] = true;
705 // The five valid date patterns, in order of priority
706 // 1 YEAR + MONTH + DAY_OF_MONTH
707 // 2 YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
708 // 3 YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
709 // 4 YEAR + DAY_OF_YEAR
710 // 5 YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
711 switch (field)
713 case MONTH: // pattern 1,2 or 3
714 isSet[DAY_OF_YEAR] = false;
715 isSet[WEEK_OF_YEAR] = false;
716 break;
717 case DAY_OF_MONTH: // pattern 1
718 isSet[YEAR] = true;
719 isSet[MONTH] = true;
720 isSet[WEEK_OF_MONTH] = true;
721 isSet[DAY_OF_WEEK] = false;
722 isSet[DAY_OF_WEEK_IN_MONTH] = false;
723 isSet[DAY_OF_YEAR] = false;
724 isSet[WEEK_OF_YEAR] = false;
725 break;
726 case WEEK_OF_MONTH: // pattern 2
727 if (! isSet[DAY_OF_WEEK])
728 fields[DAY_OF_WEEK] = getFirstDayOfWeek();
729 isSet[YEAR] = true;
730 isSet[MONTH] = true;
731 isSet[DAY_OF_WEEK] = true;
732 isSet[DAY_OF_MONTH] = false;
733 isSet[DAY_OF_WEEK_IN_MONTH] = false;
734 isSet[DAY_OF_YEAR] = false;
735 isSet[WEEK_OF_YEAR] = false;
736 break;
737 case DAY_OF_WEEK_IN_MONTH: // pattern 3
738 if (! isSet[DAY_OF_WEEK])
739 fields[DAY_OF_WEEK] = getFirstDayOfWeek();
740 isSet[YEAR] = true;
741 isSet[MONTH] = true;
742 isSet[DAY_OF_WEEK] = true;
743 isSet[DAY_OF_YEAR] = false;
744 isSet[DAY_OF_MONTH] = false;
745 isSet[WEEK_OF_MONTH] = false;
746 isSet[WEEK_OF_YEAR] = false;
747 break;
748 case DAY_OF_YEAR: // pattern 4
749 isSet[YEAR] = true;
750 isSet[MONTH] = false;
751 isSet[WEEK_OF_MONTH] = false;
752 isSet[DAY_OF_MONTH] = false;
753 isSet[DAY_OF_WEEK] = false;
754 isSet[WEEK_OF_YEAR] = false;
755 isSet[DAY_OF_WEEK_IN_MONTH] = false;
756 break;
757 case WEEK_OF_YEAR: // pattern 5
758 if (! isSet[DAY_OF_WEEK])
759 fields[DAY_OF_WEEK] = getFirstDayOfWeek();
760 isSet[YEAR] = true;
761 isSet[DAY_OF_WEEK] = true;
762 isSet[MONTH] = false;
763 isSet[DAY_OF_MONTH] = false;
764 isSet[WEEK_OF_MONTH] = false;
765 isSet[DAY_OF_YEAR] = false;
766 isSet[DAY_OF_WEEK_IN_MONTH] = false;
767 break;
768 case AM_PM:
769 isSet[HOUR] = true;
770 isSet[HOUR_OF_DAY] = false;
771 break;
772 case HOUR_OF_DAY:
773 isSet[AM_PM] = false;
774 isSet[HOUR] = false;
775 break;
776 case HOUR:
777 isSet[AM_PM] = true;
778 isSet[HOUR_OF_DAY] = false;
779 break;
780 case DST_OFFSET:
781 explicitDSTOffset = true;
784 // May have crossed over a DST boundary.
785 if (! explicitDSTOffset && (field != DST_OFFSET && field != ZONE_OFFSET))
786 isSet[DST_OFFSET] = false;
790 * Sets the fields for year, month, and date
791 * @param year the year.
792 * @param month the month, one of the constants JANUARY..UNDICEMBER.
793 * @param date the day of the month
795 public final void set(int year, int month, int date)
797 isTimeSet = false;
798 fields[YEAR] = year;
799 fields[MONTH] = month;
800 fields[DATE] = date;
801 isSet[YEAR] = isSet[MONTH] = isSet[DATE] = true;
802 isSet[WEEK_OF_YEAR] = false;
803 isSet[DAY_OF_YEAR] = false;
804 isSet[WEEK_OF_MONTH] = false;
805 isSet[DAY_OF_WEEK] = false;
806 isSet[DAY_OF_WEEK_IN_MONTH] = false;
807 isSet[ERA] = false;
809 if (! explicitDSTOffset)
810 isSet[DST_OFFSET] = false; // May have crossed a DST boundary.
814 * Sets the fields for year, month, date, hour, and minute
815 * @param year the year.
816 * @param month the month, one of the constants JANUARY..UNDICEMBER.
817 * @param date the day of the month
818 * @param hour the hour of day.
819 * @param minute the minute.
821 public final void set(int year, int month, int date, int hour, int minute)
823 set(year, month, date);
824 fields[HOUR_OF_DAY] = hour;
825 fields[MINUTE] = minute;
826 isSet[HOUR_OF_DAY] = isSet[MINUTE] = true;
827 isSet[AM_PM] = false;
828 isSet[HOUR] = false;
832 * Sets the fields for year, month, date, hour, and minute
833 * @param year the year.
834 * @param month the month, one of the constants JANUARY..UNDICEMBER.
835 * @param date the day of the month
836 * @param hour the hour of day.
837 * @param minute the minute.
838 * @param second the second.
840 public final void set(int year, int month, int date, int hour, int minute,
841 int second)
843 set(year, month, date, hour, minute);
844 fields[SECOND] = second;
845 isSet[SECOND] = true;
849 * Clears the values of all the time fields.
851 public final void clear()
853 isTimeSet = false;
854 areFieldsSet = false;
855 int zoneOffs = zone.getRawOffset();
856 int[] tempFields =
858 1, 1970, JANUARY, 1, 1, 1, 1, THURSDAY, 1, AM, 0, 0, 0,
859 0, 0, zoneOffs, 0
861 fields = tempFields;
862 for (int i = 0; i < FIELD_COUNT; i++)
863 isSet[i] = false;
867 * Clears the values of the specified time field.
868 * @param field the time field. One of the time field constants.
869 * @throws ArrayIndexOutOfBoundsException if field is outside
870 * the valid range. The value of field must be >= 0 and
871 * <= <code>FIELD_COUNT</code>.
873 public final void clear(int field)
875 int[] tempFields =
877 1, 1970, JANUARY, 1, 1, 1, 1, THURSDAY, 1, AM, 0, 0, 0,
878 0, 0, zone.getRawOffset(), 0
880 isTimeSet = false;
881 areFieldsSet = false;
882 isSet[field] = false;
883 fields[field] = tempFields[field];
887 * Determines if the specified field has a valid value.
888 * @return true if the specified field has a value.
889 * @throws ArrayIndexOutOfBoundsException if the field is outside
890 * the valid range. The value of field must be >= 0 and
891 * <= <code>FIELD_COUNT</code>.
893 public final boolean isSet(int field)
895 return isSet[field];
899 * Fills any unset fields in the time field list
901 protected void complete()
903 if (! isTimeSet)
904 computeTime();
905 if (! areFieldsSet)
906 computeFields();
910 * Compares the given calendar with this.
911 * @param o the object to that we should compare.
912 * @return true, if the given object is a calendar, that represents
913 * the same time (but doesn't necessary have the same fields).
915 public boolean equals(Object o)
917 if (! (o instanceof Calendar))
918 return false;
919 Calendar cal = (Calendar) o;
920 if (getTimeInMillis() == ((Calendar) o).getTimeInMillis()
921 && cal.getFirstDayOfWeek() == getFirstDayOfWeek()
922 && cal.isLenient() == isLenient()
923 && cal.getMinimalDaysInFirstWeek() == getMinimalDaysInFirstWeek())
925 TimeZone self = getTimeZone();
926 TimeZone oth = cal.getTimeZone();
927 return self == null ? oth == null : self.equals(oth);
929 return false;
933 * Returns a hash code for this calendar.
934 * @return a hash code, which fullfits the general contract of
935 * <code>hashCode()</code>
937 public int hashCode()
939 long time = getTimeInMillis();
940 int val = (int) ((time & 0xffffffffL) ^ (time >> 32));
941 val += (getFirstDayOfWeek() + (isLenient() ? 1230 : 1237)
942 + getMinimalDaysInFirstWeek());
943 TimeZone self = getTimeZone();
944 if (self != null)
945 val ^= self.hashCode();
946 return val;
950 * Compares the given calendar with this.
951 * @param o the object to that we should compare.
952 * @return true, if the given object is a calendar, and this calendar
953 * represents a smaller time than the calendar o.
954 * @exception ClassCastException if o is not an calendar.
955 * @since JDK1.2 you don't need to override this method
957 public boolean before(Object o)
959 return getTimeInMillis() < ((Calendar) o).getTimeInMillis();
963 * Compares the given calendar with this.
964 * @param o the object to that we should compare.
965 * @return true, if the given object is a calendar, and this calendar
966 * represents a bigger time than the calendar o.
967 * @exception ClassCastException if o is not an calendar.
968 * @since JDK1.2 you don't need to override this method
970 public boolean after(Object o)
972 return getTimeInMillis() > ((Calendar) o).getTimeInMillis();
976 * Adds the specified amount of time to the given time field. The
977 * amount may be negative to subtract the time. If the field overflows
978 * it does what you expect: Jan, 25 + 10 Days is Feb, 4.
979 * @param field the time field. One of the time field constants.
980 * @param amount the amount of time.
981 * @throws ArrayIndexOutOfBoundsException if the field is outside
982 * the valid range. The value of field must be >= 0 and
983 * <= <code>FIELD_COUNT</code>.
985 public abstract void add(int field, int amount);
988 * Rolls the specified time field up or down. This means add one
989 * to the specified field, but don't change the other fields. If
990 * the maximum for this field is reached, start over with the
991 * minimum value. <br>
993 * <strong>Note:</strong> There may be situation, where the other
994 * fields must be changed, e.g rolling the month on May, 31.
995 * The date June, 31 is automatically converted to July, 1.
996 * @param field the time field. One of the time field constants.
997 * @param up the direction, true for up, false for down.
998 * @throws ArrayIndexOutOfBoundsException if the field is outside
999 * the valid range. The value of field must be >= 0 and
1000 * <= <code>FIELD_COUNT</code>.
1002 public abstract void roll(int field, boolean up);
1005 * Rolls up or down the specified time field by the given amount.
1006 * A negative amount rolls down. The default implementation is
1007 * call <code>roll(int, boolean)</code> for the specified amount.
1009 * Subclasses should override this method to do more intuitiv things.
1011 * @param field the time field. One of the time field constants.
1012 * @param amount the amount to roll by, positive for rolling up,
1013 * negative for rolling down.
1014 * @throws ArrayIndexOutOfBoundsException if the field is outside
1015 * the valid range. The value of field must be >= 0 and
1016 * <= <code>FIELD_COUNT</code>.
1017 * @since JDK1.2
1019 public void roll(int field, int amount)
1021 while (amount > 0)
1023 roll(field, true);
1024 amount--;
1026 while (amount < 0)
1028 roll(field, false);
1029 amount++;
1034 * Sets the time zone to the specified value.
1035 * @param zone the new time zone
1037 public void setTimeZone(TimeZone zone)
1039 this.zone = zone;
1043 * Gets the time zone of this calendar
1044 * @return the current time zone.
1046 public TimeZone getTimeZone()
1048 return zone;
1052 * Specifies if the date/time interpretation should be lenient.
1053 * If the flag is set, a date such as "February 30, 1996" will be
1054 * treated as the 29th day after the February 1. If this flag
1055 * is false, such dates will cause an exception.
1056 * @param lenient true, if the date should be interpreted linient,
1057 * false if it should be interpreted strict.
1059 public void setLenient(boolean lenient)
1061 this.lenient = lenient;
1065 * Tells if the date/time interpretation is lenient.
1066 * @return true, if the date should be interpreted linient,
1067 * false if it should be interpreted strict.
1069 public boolean isLenient()
1071 return lenient;
1075 * Sets what the first day of week is. This is used for
1076 * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
1077 * @param value the first day of week. One of SUNDAY to SATURDAY.
1079 public void setFirstDayOfWeek(int value)
1081 firstDayOfWeek = value;
1085 * Gets what the first day of week is. This is used for
1086 * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
1087 * @return the first day of week. One of SUNDAY to SATURDAY.
1089 public int getFirstDayOfWeek()
1091 return firstDayOfWeek;
1095 * Sets how many days are required in the first week of the year.
1096 * If the first day of the year should be the first week you should
1097 * set this value to 1. If the first week must be a full week, set
1098 * it to 7.
1099 * @param value the minimal days required in the first week.
1101 public void setMinimalDaysInFirstWeek(int value)
1103 minimalDaysInFirstWeek = value;
1107 * Gets how many days are required in the first week of the year.
1108 * @return the minimal days required in the first week.
1109 * @see #setMinimalDaysInFirstWeek
1111 public int getMinimalDaysInFirstWeek()
1113 return minimalDaysInFirstWeek;
1117 * Gets the smallest value that is allowed for the specified field.
1118 * @param field the time field. One of the time field constants.
1119 * @return the smallest value.
1121 public abstract int getMinimum(int field);
1124 * Gets the biggest value that is allowed for the specified field.
1125 * @param field the time field. One of the time field constants.
1126 * @return the biggest value.
1128 public abstract int getMaximum(int field);
1131 * Gets the greatest minimum value that is allowed for the specified field.
1132 * @param field the time field. One of the time field constants.
1133 * @return the greatest minimum value.
1135 public abstract int getGreatestMinimum(int field);
1138 * Gets the smallest maximum value that is allowed for the
1139 * specified field. For example this is 28 for DAY_OF_MONTH.
1140 * @param field the time field. One of the time field constants.
1141 * @return the least maximum value.
1143 public abstract int getLeastMaximum(int field);
1146 * Gets the actual minimum value that is allowed for the specified field.
1147 * This value is dependent on the values of the other fields.
1148 * @param field the time field. One of the time field constants.
1149 * @return the actual minimum value.
1150 * @throws ArrayIndexOutOfBoundsException if the field is outside
1151 * the valid range. The value of field must be >= 0 and
1152 * <= <code>FIELD_COUNT</code>.
1153 * @since jdk1.2
1155 public int getActualMinimum(int field)
1157 Calendar tmp = (Calendar) clone(); // To avoid restoring state
1158 int min = tmp.getGreatestMinimum(field);
1159 int end = tmp.getMinimum(field);
1160 tmp.set(field, min);
1161 for (; min > end; min--)
1163 tmp.add(field, -1); // Try to get smaller
1164 if (tmp.get(field) != min - 1)
1165 break; // Done if not successful
1167 return min;
1171 * Gets the actual maximum value that is allowed for the specified field.
1172 * This value is dependent on the values of the other fields.
1173 * @param field the time field. One of the time field constants.
1174 * @return the actual maximum value.
1175 * @throws ArrayIndexOutOfBoundsException if the field is outside
1176 * the valid range. The value of field must be >= 0 and
1177 * <= <code>FIELD_COUNT</code>.
1178 * @since jdk1.2
1180 public int getActualMaximum(int field)
1182 Calendar tmp = (Calendar) clone(); // To avoid restoring state
1183 int max = tmp.getLeastMaximum(field);
1184 int end = tmp.getMaximum(field);
1185 tmp.set(field, max);
1186 for (; max < end; max++)
1188 tmp.add(field, 1);
1189 if (tmp.get(field) != max + 1)
1190 break;
1192 return max;
1196 * Return a clone of this object.
1198 public Object clone()
1202 Calendar cal = (Calendar) super.clone();
1203 cal.fields = (int[]) fields.clone();
1204 cal.isSet = (boolean[]) isSet.clone();
1205 return cal;
1207 catch (CloneNotSupportedException ex)
1209 return null;
1213 private static final String[] fieldNames =
1215 ",ERA=", ",YEAR=", ",MONTH=",
1216 ",WEEK_OF_YEAR=",
1217 ",WEEK_OF_MONTH=",
1218 ",DAY_OF_MONTH=",
1219 ",DAY_OF_YEAR=", ",DAY_OF_WEEK=",
1220 ",DAY_OF_WEEK_IN_MONTH=",
1221 ",AM_PM=", ",HOUR=",
1222 ",HOUR_OF_DAY=", ",MINUTE=",
1223 ",SECOND=", ",MILLISECOND=",
1224 ",ZONE_OFFSET=", ",DST_OFFSET="
1228 * Returns a string representation of this object. It is mainly
1229 * for debugging purposes and its content is implementation
1230 * specific.
1232 public String toString()
1234 StringBuffer sb = new StringBuffer();
1235 sb.append(getClass().getName()).append('[');
1236 sb.append("time=");
1237 if (isTimeSet)
1238 sb.append(time);
1239 else
1240 sb.append("?");
1241 sb.append(",zone=" + zone);
1242 sb.append(",areFieldsSet=" + areFieldsSet);
1243 for (int i = 0; i < FIELD_COUNT; i++)
1245 sb.append(fieldNames[i]);
1246 if (isSet[i])
1247 sb.append(fields[i]);
1248 else
1249 sb.append("?");
1251 sb.append(",lenient=").append(lenient);
1252 sb.append(",firstDayOfWeek=").append(firstDayOfWeek);
1253 sb.append(",minimalDaysInFirstWeek=").append(minimalDaysInFirstWeek);
1254 sb.append("]");
1255 return sb.toString();
1259 * Saves the state of the object to the stream. Ideally we would
1260 * only write the time field, but we need to be compatible with
1261 * earlier versions. <br>
1263 * This doesn't write the JDK1.1 field nextStamp to the stream, as
1264 * I don't know what it is good for, and because the documentation
1265 * says, that it could be omitted. */
1266 private void writeObject(ObjectOutputStream stream) throws IOException
1268 if (! isTimeSet)
1269 computeTime();
1270 stream.defaultWriteObject();
1274 * Reads the object back from stream (deserialization).
1276 private void readObject(ObjectInputStream stream)
1277 throws IOException, ClassNotFoundException
1279 stream.defaultReadObject();
1280 if (! isTimeSet)
1281 computeTime();
1283 if (serialVersionOnStream > 1)
1285 // This is my interpretation of the serial number:
1286 // Sun wants to remove all fields from the stream someday
1287 // and will then increase the serialVersion number again.
1288 // We prepare to be compatible.
1289 fields = new int[FIELD_COUNT];
1290 isSet = new boolean[FIELD_COUNT];
1291 areFieldsSet = false;