jtulach@1334: /* jtulach@1334: * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. jtulach@1334: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jtulach@1334: * jtulach@1334: * This code is free software; you can redistribute it and/or modify it jtulach@1334: * under the terms of the GNU General Public License version 2 only, as jtulach@1334: * published by the Free Software Foundation. Oracle designates this jtulach@1334: * particular file as subject to the "Classpath" exception as provided jtulach@1334: * by Oracle in the LICENSE file that accompanied this code. jtulach@1334: * jtulach@1334: * This code is distributed in the hope that it will be useful, but WITHOUT jtulach@1334: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jtulach@1334: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jtulach@1334: * version 2 for more details (a copy is included in the LICENSE file that jtulach@1334: * accompanied this code). jtulach@1334: * jtulach@1334: * You should have received a copy of the GNU General Public License version jtulach@1334: * 2 along with this work; if not, write to the Free Software Foundation, jtulach@1334: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jtulach@1334: * jtulach@1334: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jtulach@1334: * or visit www.oracle.com if you need additional information or have any jtulach@1334: * questions. jtulach@1334: */ jtulach@1334: jtulach@1334: /* jtulach@1334: * (C) Copyright Taligent, Inc. 1996-1998 - All Rights Reserved jtulach@1334: * (C) Copyright IBM Corp. 1996-1998 - All Rights Reserved jtulach@1334: * jtulach@1334: * The original version of this source code and documentation is copyrighted jtulach@1334: * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These jtulach@1334: * materials are provided under terms of a License Agreement between Taligent jtulach@1334: * and Sun. This technology is protected by multiple US and International jtulach@1334: * patents. This notice and attribution to Taligent may not be removed. jtulach@1334: * Taligent is a registered trademark of Taligent, Inc. jtulach@1334: * jtulach@1334: */ jtulach@1334: jtulach@1334: package java.util; jtulach@1334: jtulach@1334: import java.io.IOException; jtulach@1334: import java.io.ObjectInputStream; jtulach@1334: import java.io.ObjectOutputStream; jtulach@1334: import java.io.OptionalDataException; jtulach@1334: import java.io.Serializable; jtulach@1334: import java.security.AccessController; jtulach@1334: import java.security.PrivilegedActionException; jtulach@1334: import java.security.PrivilegedExceptionAction; jtulach@1334: import java.text.DateFormat; jtulach@1334: import java.text.DateFormatSymbols; jtulach@1334: import java.util.concurrent.ConcurrentHashMap; jtulach@1334: import java.util.concurrent.ConcurrentMap; jtulach@1334: jtulach@1334: /** jtulach@1334: * The Calendar class is an abstract class that provides methods jtulach@1334: * for converting between a specific instant in time and a set of {@link jtulach@1334: * #fields calendar fields} such as YEAR, MONTH, jtulach@1334: * DAY_OF_MONTH, HOUR, and so on, and for jtulach@1334: * manipulating the calendar fields, such as getting the date of the next jtulach@1334: * week. An instant in time can be represented by a millisecond value that is jtulach@1334: * an offset from the Epoch, January 1, 1970 jtulach@1334: * 00:00:00.000 GMT (Gregorian). jtulach@1334: * jtulach@1334: *

The class also provides additional fields and methods for jtulach@1334: * implementing a concrete calendar system outside the package. Those jtulach@1334: * fields and methods are defined as protected. jtulach@1334: * jtulach@1334: *

jtulach@1334: * Like other locale-sensitive classes, Calendar provides a jtulach@1334: * class method, getInstance, for getting a generally useful jtulach@1334: * object of this type. Calendar's getInstance method jtulach@1334: * returns a Calendar object whose jtulach@1334: * calendar fields have been initialized with the current date and time: jtulach@1334: *

jtulach@1334: *
jtulach@1334:  *     Calendar rightNow = Calendar.getInstance();
jtulach@1334:  * 
jtulach@1334: *
jtulach@1334: * jtulach@1334: *

A Calendar object can produce all the calendar field values jtulach@1334: * needed to implement the date-time formatting for a particular language and jtulach@1334: * calendar style (for example, Japanese-Gregorian, Japanese-Traditional). jtulach@1334: * Calendar defines the range of values returned by jtulach@1334: * certain calendar fields, as well as their meaning. For example, jtulach@1334: * the first month of the calendar system has value MONTH == jtulach@1334: * JANUARY for all calendars. Other values are defined by the jtulach@1334: * concrete subclass, such as ERA. See individual field jtulach@1334: * documentation and subclass documentation for details. jtulach@1334: * jtulach@1334: *

Getting and Setting Calendar Field Values

jtulach@1334: * jtulach@1334: *

The calendar field values can be set by calling the set jtulach@1334: * methods. Any field values set in a Calendar will not be jtulach@1334: * interpreted until it needs to calculate its time value (milliseconds from jtulach@1334: * the Epoch) or values of the calendar fields. Calling the jtulach@1334: * get, getTimeInMillis, getTime, jtulach@1334: * add and roll involves such calculation. jtulach@1334: * jtulach@1334: *

Leniency

jtulach@1334: * jtulach@1334: *

Calendar has two modes for interpreting the calendar jtulach@1334: * fields, lenient and non-lenient. When a jtulach@1334: * Calendar is in lenient mode, it accepts a wider range of jtulach@1334: * calendar field values than it produces. When a Calendar jtulach@1334: * recomputes calendar field values for return by get(), all of jtulach@1334: * the calendar fields are normalized. For example, a lenient jtulach@1334: * GregorianCalendar interprets MONTH == JANUARY, jtulach@1334: * DAY_OF_MONTH == 32 as February 1. jtulach@1334: jtulach@1334: *

When a Calendar is in non-lenient mode, it throws an jtulach@1334: * exception if there is any inconsistency in its calendar fields. For jtulach@1334: * example, a GregorianCalendar always produces jtulach@1334: * DAY_OF_MONTH values between 1 and the length of the month. A jtulach@1334: * non-lenient GregorianCalendar throws an exception upon jtulach@1334: * calculating its time or calendar field values if any out-of-range field jtulach@1334: * value has been set. jtulach@1334: * jtulach@1334: *

First Week

jtulach@1334: * jtulach@1334: * Calendar defines a locale-specific seven day week using two jtulach@1334: * parameters: the first day of the week and the minimal days in first week jtulach@1334: * (from 1 to 7). These numbers are taken from the locale resource data when a jtulach@1334: * Calendar is constructed. They may also be specified explicitly jtulach@1334: * through the methods for setting their values. jtulach@1334: * jtulach@1334: *

When setting or getting the WEEK_OF_MONTH or jtulach@1334: * WEEK_OF_YEAR fields, Calendar must determine the jtulach@1334: * first week of the month or year as a reference point. The first week of a jtulach@1334: * month or year is defined as the earliest seven day period beginning on jtulach@1334: * getFirstDayOfWeek() and containing at least jtulach@1334: * getMinimalDaysInFirstWeek() days of that month or year. Weeks jtulach@1334: * numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow jtulach@1334: * it. Note that the normalized numbering returned by get() may be jtulach@1334: * different. For example, a specific Calendar subclass may jtulach@1334: * designate the week before week 1 of a year as week n of jtulach@1334: * the previous year. jtulach@1334: * jtulach@1334: *

Calendar Fields Resolution

jtulach@1334: * jtulach@1334: * When computing a date and time from the calendar fields, there jtulach@1334: * may be insufficient information for the computation (such as only jtulach@1334: * year and month with no day of month), or there may be inconsistent jtulach@1334: * information (such as Tuesday, July 15, 1996 (Gregorian) -- July 15, jtulach@1334: * 1996 is actually a Monday). Calendar will resolve jtulach@1334: * calendar field values to determine the date and time in the jtulach@1334: * following way. jtulach@1334: * jtulach@1334: *

If there is any conflict in calendar field values, jtulach@1334: * Calendar gives priorities to calendar fields that have been set jtulach@1334: * more recently. The following are the default combinations of the jtulach@1334: * calendar fields. The most recent combination, as determined by the jtulach@1334: * most recently set single field, will be used. jtulach@1334: * jtulach@1334: *

For the date fields: jtulach@1334: *

jtulach@1334: *
jtulach@1334:  * YEAR + MONTH + DAY_OF_MONTH
jtulach@1334:  * YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
jtulach@1334:  * YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
jtulach@1334:  * YEAR + DAY_OF_YEAR
jtulach@1334:  * YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
jtulach@1334:  * 
jtulach@1334: * jtulach@1334: * For the time of day fields: jtulach@1334: *
jtulach@1334: *
jtulach@1334:  * HOUR_OF_DAY
jtulach@1334:  * AM_PM + HOUR
jtulach@1334:  * 
jtulach@1334: * jtulach@1334: *

If there are any calendar fields whose values haven't been set in the selected jtulach@1334: * field combination, Calendar uses their default values. The default jtulach@1334: * value of each field may vary by concrete calendar systems. For example, in jtulach@1334: * GregorianCalendar, the default of a field is the same as that jtulach@1334: * of the start of the Epoch: i.e., YEAR = 1970, MONTH = jtulach@1334: * JANUARY, DAY_OF_MONTH = 1, etc. jtulach@1334: * jtulach@1334: *

jtulach@1334: * Note: There are certain possible ambiguities in jtulach@1334: * interpretation of certain singular times, which are resolved in the jtulach@1334: * following ways: jtulach@1334: *

    jtulach@1334: *
  1. 23:59 is the last minute of the day and 00:00 is the first jtulach@1334: * minute of the next day. Thus, 23:59 on Dec 31, 1999 < 00:00 on jtulach@1334: * Jan 1, 2000 < 00:01 on Jan 1, 2000. jtulach@1334: * jtulach@1334: *
  2. Although historically not precise, midnight also belongs to "am", jtulach@1334: * and noon belongs to "pm", so on the same day, jtulach@1334: * 12:00 am (midnight) < 12:01 am, and 12:00 pm (noon) < 12:01 pm jtulach@1334: *
jtulach@1334: * jtulach@1334: *

jtulach@1334: * The date or time format strings are not part of the definition of a jtulach@1334: * calendar, as those must be modifiable or overridable by the user at jtulach@1334: * runtime. Use {@link DateFormat} jtulach@1334: * to format dates. jtulach@1334: * jtulach@1334: *

Field Manipulation

jtulach@1334: * jtulach@1334: * The calendar fields can be changed using three methods: jtulach@1334: * set(), add(), and roll().

jtulach@1334: * jtulach@1334: *

set(f, value) changes calendar field jtulach@1334: * f to value. In addition, it sets an jtulach@1334: * internal member variable to indicate that calendar field f has jtulach@1334: * been changed. Although calendar field f is changed immediately, jtulach@1334: * the calendar's time value in milliseconds is not recomputed until the next call to jtulach@1334: * get(), getTime(), getTimeInMillis(), jtulach@1334: * add(), or roll() is made. Thus, multiple calls to jtulach@1334: * set() do not trigger multiple, unnecessary jtulach@1334: * computations. As a result of changing a calendar field using jtulach@1334: * set(), other calendar fields may also change, depending on the jtulach@1334: * calendar field, the calendar field value, and the calendar system. In addition, jtulach@1334: * get(f) will not necessarily return value set by jtulach@1334: * the call to the set method jtulach@1334: * after the calendar fields have been recomputed. The specifics are determined by jtulach@1334: * the concrete calendar class.

jtulach@1334: * jtulach@1334: *

Example: Consider a GregorianCalendar jtulach@1334: * originally set to August 31, 1999. Calling set(Calendar.MONTH, jtulach@1334: * Calendar.SEPTEMBER) sets the date to September 31, jtulach@1334: * 1999. This is a temporary internal representation that resolves to jtulach@1334: * October 1, 1999 if getTime()is then called. However, a jtulach@1334: * call to set(Calendar.DAY_OF_MONTH, 30) before the call to jtulach@1334: * getTime() sets the date to September 30, 1999, since jtulach@1334: * no recomputation occurs after set() itself.

jtulach@1334: * jtulach@1334: *

add(f, delta) adds delta jtulach@1334: * to field f. This is equivalent to calling set(f, jtulach@1334: * get(f) + delta) with two adjustments:

jtulach@1334: * jtulach@1334: *
jtulach@1334: *

Add rule 1. The value of field f jtulach@1334: * after the call minus the value of field f before the jtulach@1334: * call is delta, modulo any overflow that has occurred in jtulach@1334: * field f. Overflow occurs when a field value exceeds its jtulach@1334: * range and, as a result, the next larger field is incremented or jtulach@1334: * decremented and the field value is adjusted back into its range.

jtulach@1334: * jtulach@1334: *

Add rule 2. If a smaller field is expected to be jtulach@1334: * invariant, but it is impossible for it to be equal to its jtulach@1334: * prior value because of changes in its minimum or maximum after field jtulach@1334: * f is changed or other constraints, such as time zone jtulach@1334: * offset changes, then its value is adjusted to be as close jtulach@1334: * as possible to its expected value. A smaller field represents a jtulach@1334: * smaller unit of time. HOUR is a smaller field than jtulach@1334: * DAY_OF_MONTH. No adjustment is made to smaller fields jtulach@1334: * that are not expected to be invariant. The calendar system jtulach@1334: * determines what fields are expected to be invariant.

jtulach@1334: *
jtulach@1334: * jtulach@1334: *

In addition, unlike set(), add() forces jtulach@1334: * an immediate recomputation of the calendar's milliseconds and all jtulach@1334: * fields.

jtulach@1334: * jtulach@1334: *

Example: Consider a GregorianCalendar jtulach@1334: * originally set to August 31, 1999. Calling add(Calendar.MONTH, jtulach@1334: * 13) sets the calendar to September 30, 2000. Add rule jtulach@1334: * 1 sets the MONTH field to September, since jtulach@1334: * adding 13 months to August gives September of the next year. Since jtulach@1334: * DAY_OF_MONTH cannot be 31 in September in a jtulach@1334: * GregorianCalendar, add rule 2 sets the jtulach@1334: * DAY_OF_MONTH to 30, the closest possible value. Although jtulach@1334: * it is a smaller field, DAY_OF_WEEK is not adjusted by jtulach@1334: * rule 2, since it is expected to change when the month changes in a jtulach@1334: * GregorianCalendar.

jtulach@1334: * jtulach@1334: *

roll(f, delta) adds jtulach@1334: * delta to field f without changing larger jtulach@1334: * fields. This is equivalent to calling add(f, delta) with jtulach@1334: * the following adjustment:

jtulach@1334: * jtulach@1334: *
jtulach@1334: *

Roll rule. Larger fields are unchanged after the jtulach@1334: * call. A larger field represents a larger unit of jtulach@1334: * time. DAY_OF_MONTH is a larger field than jtulach@1334: * HOUR.

jtulach@1334: *
jtulach@1334: * jtulach@1334: *

Example: See {@link java.util.GregorianCalendar#roll(int, int)}. jtulach@1334: * jtulach@1334: *

Usage model. To motivate the behavior of jtulach@1334: * add() and roll(), consider a user interface jtulach@1334: * component with increment and decrement buttons for the month, day, and jtulach@1334: * year, and an underlying GregorianCalendar. If the jtulach@1334: * interface reads January 31, 1999 and the user presses the month jtulach@1334: * increment button, what should it read? If the underlying jtulach@1334: * implementation uses set(), it might read March 3, 1999. A jtulach@1334: * better result would be February 28, 1999. Furthermore, if the user jtulach@1334: * presses the month increment button again, it should read March 31, jtulach@1334: * 1999, not March 28, 1999. By saving the original date and using either jtulach@1334: * add() or roll(), depending on whether larger jtulach@1334: * fields should be affected, the user interface can behave as most users jtulach@1334: * will intuitively expect.

jtulach@1334: * jtulach@1334: * @see java.lang.System#currentTimeMillis() jtulach@1334: * @see Date jtulach@1334: * @see GregorianCalendar jtulach@1334: * @see TimeZone jtulach@1334: * @see java.text.DateFormat jtulach@1334: * @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu jtulach@1334: * @since JDK1.1 jtulach@1334: */ jtulach@1334: public abstract class Calendar implements Serializable, Cloneable, Comparable { jtulach@1334: jtulach@1334: // Data flow in Calendar jtulach@1334: // --------------------- jtulach@1334: jtulach@1334: // The current time is represented in two ways by Calendar: as UTC jtulach@1334: // milliseconds from the epoch (1 January 1970 0:00 UTC), and as local jtulach@1334: // fields such as MONTH, HOUR, AM_PM, etc. It is possible to compute the jtulach@1334: // millis from the fields, and vice versa. The data needed to do this jtulach@1334: // conversion is encapsulated by a TimeZone object owned by the Calendar. jtulach@1334: // The data provided by the TimeZone object may also be overridden if the jtulach@1334: // user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class jtulach@1334: // keeps track of what information was most recently set by the caller, and jtulach@1334: // uses that to compute any other information as needed. jtulach@1334: jtulach@1334: // If the user sets the fields using set(), the data flow is as follows. jtulach@1334: // This is implemented by the Calendar subclass's computeTime() method. jtulach@1334: // During this process, certain fields may be ignored. The disambiguation jtulach@1334: // algorithm for resolving which fields to pay attention to is described jtulach@1334: // in the class documentation. jtulach@1334: jtulach@1334: // local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.) jtulach@1334: // | jtulach@1334: // | Using Calendar-specific algorithm jtulach@1334: // V jtulach@1334: // local standard millis jtulach@1334: // | jtulach@1334: // | Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET jtulach@1334: // V jtulach@1334: // UTC millis (in time data member) jtulach@1334: jtulach@1334: // If the user sets the UTC millis using setTime() or setTimeInMillis(), jtulach@1334: // the data flow is as follows. This is implemented by the Calendar jtulach@1334: // subclass's computeFields() method. jtulach@1334: jtulach@1334: // UTC millis (in time data member) jtulach@1334: // | jtulach@1334: // | Using TimeZone getOffset() jtulach@1334: // V jtulach@1334: // local standard millis jtulach@1334: // | jtulach@1334: // | Using Calendar-specific algorithm jtulach@1334: // V jtulach@1334: // local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.) jtulach@1334: jtulach@1334: // In general, a round trip from fields, through local and UTC millis, and jtulach@1334: // back out to fields is made when necessary. This is implemented by the jtulach@1334: // complete() method. Resolving a partial set of fields into a UTC millis jtulach@1334: // value allows all remaining fields to be generated from that value. If jtulach@1334: // the Calendar is lenient, the fields are also renormalized to standard jtulach@1334: // ranges when they are regenerated. jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific jtulach@1334: * value; see subclass documentation. jtulach@1334: * jtulach@1334: * @see GregorianCalendar#AD jtulach@1334: * @see GregorianCalendar#BC jtulach@1334: */ jtulach@1334: public final static int ERA = 0; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * year. This is a calendar-specific value; see subclass documentation. jtulach@1334: */ jtulach@1334: public final static int YEAR = 1; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * month. This is a calendar-specific value. The first month of jtulach@1334: * the year in the Gregorian and Julian calendars is jtulach@1334: * JANUARY which is 0; the last depends on the number jtulach@1334: * of months in a year. jtulach@1334: * jtulach@1334: * @see #JANUARY jtulach@1334: * @see #FEBRUARY jtulach@1334: * @see #MARCH jtulach@1334: * @see #APRIL jtulach@1334: * @see #MAY jtulach@1334: * @see #JUNE jtulach@1334: * @see #JULY jtulach@1334: * @see #AUGUST jtulach@1334: * @see #SEPTEMBER jtulach@1334: * @see #OCTOBER jtulach@1334: * @see #NOVEMBER jtulach@1334: * @see #DECEMBER jtulach@1334: * @see #UNDECIMBER jtulach@1334: */ jtulach@1334: public final static int MONTH = 2; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * week number within the current year. The first week of the year, as jtulach@1334: * defined by getFirstDayOfWeek() and jtulach@1334: * getMinimalDaysInFirstWeek(), has value 1. Subclasses define jtulach@1334: * the value of WEEK_OF_YEAR for days before the first week of jtulach@1334: * the year. jtulach@1334: * jtulach@1334: * @see #getFirstDayOfWeek jtulach@1334: * @see #getMinimalDaysInFirstWeek jtulach@1334: */ jtulach@1334: public final static int WEEK_OF_YEAR = 3; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * week number within the current month. The first week of the month, as jtulach@1334: * defined by getFirstDayOfWeek() and jtulach@1334: * getMinimalDaysInFirstWeek(), has value 1. Subclasses define jtulach@1334: * the value of WEEK_OF_MONTH for days before the first week of jtulach@1334: * the month. jtulach@1334: * jtulach@1334: * @see #getFirstDayOfWeek jtulach@1334: * @see #getMinimalDaysInFirstWeek jtulach@1334: */ jtulach@1334: public final static int WEEK_OF_MONTH = 4; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * day of the month. This is a synonym for DAY_OF_MONTH. jtulach@1334: * The first day of the month has value 1. jtulach@1334: * jtulach@1334: * @see #DAY_OF_MONTH jtulach@1334: */ jtulach@1334: public final static int DATE = 5; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * day of the month. This is a synonym for DATE. jtulach@1334: * The first day of the month has value 1. jtulach@1334: * jtulach@1334: * @see #DATE jtulach@1334: */ jtulach@1334: public final static int DAY_OF_MONTH = 5; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the day jtulach@1334: * number within the current year. The first day of the year has value 1. jtulach@1334: */ jtulach@1334: public final static int DAY_OF_YEAR = 6; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the day jtulach@1334: * of the week. This field takes values SUNDAY, jtulach@1334: * MONDAY, TUESDAY, WEDNESDAY, jtulach@1334: * THURSDAY, FRIDAY, and SATURDAY. jtulach@1334: * jtulach@1334: * @see #SUNDAY jtulach@1334: * @see #MONDAY jtulach@1334: * @see #TUESDAY jtulach@1334: * @see #WEDNESDAY jtulach@1334: * @see #THURSDAY jtulach@1334: * @see #FRIDAY jtulach@1334: * @see #SATURDAY jtulach@1334: */ jtulach@1334: public final static int DAY_OF_WEEK = 7; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * ordinal number of the day of the week within the current month. Together jtulach@1334: * with the DAY_OF_WEEK field, this uniquely specifies a day jtulach@1334: * within a month. Unlike WEEK_OF_MONTH and jtulach@1334: * WEEK_OF_YEAR, this field's value does not depend on jtulach@1334: * getFirstDayOfWeek() or jtulach@1334: * getMinimalDaysInFirstWeek(). DAY_OF_MONTH 1 jtulach@1334: * through 7 always correspond to DAY_OF_WEEK_IN_MONTH jtulach@1334: * 1; 8 through 14 correspond to jtulach@1334: * DAY_OF_WEEK_IN_MONTH 2, and so on. jtulach@1334: * DAY_OF_WEEK_IN_MONTH 0 indicates the week before jtulach@1334: * DAY_OF_WEEK_IN_MONTH 1. Negative values count back from the jtulach@1334: * end of the month, so the last Sunday of a month is specified as jtulach@1334: * DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1. Because jtulach@1334: * negative values count backward they will usually be aligned differently jtulach@1334: * within the month than positive values. For example, if a month has 31 jtulach@1334: * days, DAY_OF_WEEK_IN_MONTH -1 will overlap jtulach@1334: * DAY_OF_WEEK_IN_MONTH 5 and the end of 4. jtulach@1334: * jtulach@1334: * @see #DAY_OF_WEEK jtulach@1334: * @see #WEEK_OF_MONTH jtulach@1334: */ jtulach@1334: public final static int DAY_OF_WEEK_IN_MONTH = 8; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating jtulach@1334: * whether the HOUR is before or after noon. jtulach@1334: * E.g., at 10:04:15.250 PM the AM_PM is PM. jtulach@1334: * jtulach@1334: * @see #AM jtulach@1334: * @see #PM jtulach@1334: * @see #HOUR jtulach@1334: */ jtulach@1334: public final static int AM_PM = 9; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * hour of the morning or afternoon. HOUR is used for the jtulach@1334: * 12-hour clock (0 - 11). Noon and midnight are represented by 0, not by 12. jtulach@1334: * E.g., at 10:04:15.250 PM the HOUR is 10. jtulach@1334: * jtulach@1334: * @see #AM_PM jtulach@1334: * @see #HOUR_OF_DAY jtulach@1334: */ jtulach@1334: public final static int HOUR = 10; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * hour of the day. HOUR_OF_DAY is used for the 24-hour clock. jtulach@1334: * E.g., at 10:04:15.250 PM the HOUR_OF_DAY is 22. jtulach@1334: * jtulach@1334: * @see #HOUR jtulach@1334: */ jtulach@1334: public final static int HOUR_OF_DAY = 11; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * minute within the hour. jtulach@1334: * E.g., at 10:04:15.250 PM the MINUTE is 4. jtulach@1334: */ jtulach@1334: public final static int MINUTE = 12; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * second within the minute. jtulach@1334: * E.g., at 10:04:15.250 PM the SECOND is 15. jtulach@1334: */ jtulach@1334: public final static int SECOND = 13; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * millisecond within the second. jtulach@1334: * E.g., at 10:04:15.250 PM the MILLISECOND is 250. jtulach@1334: */ jtulach@1334: public final static int MILLISECOND = 14; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set jtulach@1334: * indicating the raw offset from GMT in milliseconds. jtulach@1334: *

jtulach@1334: * This field reflects the correct GMT offset value of the time jtulach@1334: * zone of this Calendar if the jtulach@1334: * TimeZone implementation subclass supports jtulach@1334: * historical GMT offset changes. jtulach@1334: */ jtulach@1334: public final static int ZONE_OFFSET = 15; jtulach@1334: jtulach@1334: /** jtulach@1334: * Field number for get and set indicating the jtulach@1334: * daylight saving offset in milliseconds. jtulach@1334: *

jtulach@1334: * This field reflects the correct daylight saving offset value of jtulach@1334: * the time zone of this Calendar if the jtulach@1334: * TimeZone implementation subclass supports jtulach@1334: * historical Daylight Saving Time schedule changes. jtulach@1334: */ jtulach@1334: public final static int DST_OFFSET = 16; jtulach@1334: jtulach@1334: /** jtulach@1334: * The number of distinct fields recognized by get and set. jtulach@1334: * Field numbers range from 0..FIELD_COUNT-1. jtulach@1334: */ jtulach@1334: public final static int FIELD_COUNT = 17; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #DAY_OF_WEEK} field indicating jtulach@1334: * Sunday. jtulach@1334: */ jtulach@1334: public final static int SUNDAY = 1; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #DAY_OF_WEEK} field indicating jtulach@1334: * Monday. jtulach@1334: */ jtulach@1334: public final static int MONDAY = 2; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #DAY_OF_WEEK} field indicating jtulach@1334: * Tuesday. jtulach@1334: */ jtulach@1334: public final static int TUESDAY = 3; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #DAY_OF_WEEK} field indicating jtulach@1334: * Wednesday. jtulach@1334: */ jtulach@1334: public final static int WEDNESDAY = 4; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #DAY_OF_WEEK} field indicating jtulach@1334: * Thursday. jtulach@1334: */ jtulach@1334: public final static int THURSDAY = 5; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #DAY_OF_WEEK} field indicating jtulach@1334: * Friday. jtulach@1334: */ jtulach@1334: public final static int FRIDAY = 6; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #DAY_OF_WEEK} field indicating jtulach@1334: * Saturday. jtulach@1334: */ jtulach@1334: public final static int SATURDAY = 7; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * first month of the year in the Gregorian and Julian calendars. jtulach@1334: */ jtulach@1334: public final static int JANUARY = 0; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * second month of the year in the Gregorian and Julian calendars. jtulach@1334: */ jtulach@1334: public final static int FEBRUARY = 1; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * third month of the year in the Gregorian and Julian calendars. jtulach@1334: */ jtulach@1334: public final static int MARCH = 2; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * fourth month of the year in the Gregorian and Julian calendars. jtulach@1334: */ jtulach@1334: public final static int APRIL = 3; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * fifth month of the year in the Gregorian and Julian calendars. jtulach@1334: */ jtulach@1334: public final static int MAY = 4; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * sixth month of the year in the Gregorian and Julian calendars. jtulach@1334: */ jtulach@1334: public final static int JUNE = 5; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * seventh month of the year in the Gregorian and Julian calendars. jtulach@1334: */ jtulach@1334: public final static int JULY = 6; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * eighth month of the year in the Gregorian and Julian calendars. jtulach@1334: */ jtulach@1334: public final static int AUGUST = 7; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * ninth month of the year in the Gregorian and Julian calendars. jtulach@1334: */ jtulach@1334: public final static int SEPTEMBER = 8; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * tenth month of the year in the Gregorian and Julian calendars. jtulach@1334: */ jtulach@1334: public final static int OCTOBER = 9; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * eleventh month of the year in the Gregorian and Julian calendars. jtulach@1334: */ jtulach@1334: public final static int NOVEMBER = 10; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * twelfth month of the year in the Gregorian and Julian calendars. jtulach@1334: */ jtulach@1334: public final static int DECEMBER = 11; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #MONTH} field indicating the jtulach@1334: * thirteenth month of the year. Although GregorianCalendar jtulach@1334: * does not use this value, lunar calendars do. jtulach@1334: */ jtulach@1334: public final static int UNDECIMBER = 12; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #AM_PM} field indicating the jtulach@1334: * period of the day from midnight to just before noon. jtulach@1334: */ jtulach@1334: public final static int AM = 0; jtulach@1334: jtulach@1334: /** jtulach@1334: * Value of the {@link #AM_PM} field indicating the jtulach@1334: * period of the day from noon to just before midnight. jtulach@1334: */ jtulach@1334: public final static int PM = 1; jtulach@1334: jtulach@1334: /** jtulach@1334: * A style specifier for {@link #getDisplayNames(int, int, Locale) jtulach@1334: * getDisplayNames} indicating names in all styles, such as jtulach@1334: * "January" and "Jan". jtulach@1334: * jtulach@1334: * @see #SHORT jtulach@1334: * @see #LONG jtulach@1334: * @since 1.6 jtulach@1334: */ jtulach@1334: public static final int ALL_STYLES = 0; jtulach@1334: jtulach@1334: /** jtulach@1334: * A style specifier for {@link #getDisplayName(int, int, Locale) jtulach@1334: * getDisplayName} and {@link #getDisplayNames(int, int, Locale) jtulach@1334: * getDisplayNames} indicating a short name, such as "Jan". jtulach@1334: * jtulach@1334: * @see #LONG jtulach@1334: * @since 1.6 jtulach@1334: */ jtulach@1334: public static final int SHORT = 1; jtulach@1334: jtulach@1334: /** jtulach@1334: * A style specifier for {@link #getDisplayName(int, int, Locale) jtulach@1334: * getDisplayName} and {@link #getDisplayNames(int, int, Locale) jtulach@1334: * getDisplayNames} indicating a long name, such as "January". jtulach@1334: * jtulach@1334: * @see #SHORT jtulach@1334: * @since 1.6 jtulach@1334: */ jtulach@1334: public static final int LONG = 2; jtulach@1334: jtulach@1334: // Internal notes: jtulach@1334: // Calendar contains two kinds of time representations: current "time" in jtulach@1334: // milliseconds, and a set of calendar "fields" representing the current time. jtulach@1334: // The two representations are usually in sync, but can get out of sync jtulach@1334: // as follows. jtulach@1334: // 1. Initially, no fields are set, and the time is invalid. jtulach@1334: // 2. If the time is set, all fields are computed and in sync. jtulach@1334: // 3. If a single field is set, the time is invalid. jtulach@1334: // Recomputation of the time and fields happens when the object needs jtulach@1334: // to return a result to the user, or use a result for a computation. jtulach@1334: jtulach@1334: /** jtulach@1334: * The calendar field values for the currently set time for this calendar. jtulach@1334: * This is an array of FIELD_COUNT integers, with index values jtulach@1334: * ERA through DST_OFFSET. jtulach@1334: * @serial jtulach@1334: */ jtulach@1334: protected int fields[]; jtulach@1334: jtulach@1334: /** jtulach@1334: * The flags which tell if a specified calendar field for the calendar is set. jtulach@1334: * A new object has no fields set. After the first call to a method jtulach@1334: * which generates the fields, they all remain set after that. jtulach@1334: * This is an array of FIELD_COUNT booleans, with index values jtulach@1334: * ERA through DST_OFFSET. jtulach@1334: * @serial jtulach@1334: */ jtulach@1334: protected boolean isSet[]; jtulach@1334: jtulach@1334: /** jtulach@1334: * Pseudo-time-stamps which specify when each field was set. There jtulach@1334: * are two special values, UNSET and COMPUTED. Values from jtulach@1334: * MINIMUM_USER_SET to Integer.MAX_VALUE are legal user set values. jtulach@1334: */ jtulach@1334: transient private int stamp[]; jtulach@1334: jtulach@1334: /** jtulach@1334: * The currently set time for this calendar, expressed in milliseconds after jtulach@1334: * January 1, 1970, 0:00:00 GMT. jtulach@1334: * @see #isTimeSet jtulach@1334: * @serial jtulach@1334: */ jtulach@1334: protected long time; jtulach@1334: jtulach@1334: /** jtulach@1334: * True if then the value of time is valid. jtulach@1334: * The time is made invalid by a change to an item of field[]. jtulach@1334: * @see #time jtulach@1334: * @serial jtulach@1334: */ jtulach@1334: protected boolean isTimeSet; jtulach@1334: jtulach@1334: /** jtulach@1334: * True if fields[] are in sync with the currently set time. jtulach@1334: * If false, then the next attempt to get the value of a field will jtulach@1334: * force a recomputation of all fields from the current value of jtulach@1334: * time. jtulach@1334: * @serial jtulach@1334: */ jtulach@1334: protected boolean areFieldsSet; jtulach@1334: jtulach@1334: /** jtulach@1334: * True if all fields have been set. jtulach@1334: * @serial jtulach@1334: */ jtulach@1334: transient boolean areAllFieldsSet; jtulach@1334: jtulach@1334: /** jtulach@1334: * True if this calendar allows out-of-range field values during computation jtulach@1334: * of time from fields[]. jtulach@1334: * @see #setLenient jtulach@1334: * @see #isLenient jtulach@1334: * @serial jtulach@1334: */ jtulach@1334: private boolean lenient = true; jtulach@1334: jtulach@1334: /** jtulach@1334: * The TimeZone used by this calendar. Calendar jtulach@1334: * uses the time zone data to translate between locale and GMT time. jtulach@1334: * @serial jtulach@1334: */ jtulach@1334: private TimeZone zone; jtulach@1334: jtulach@1334: /** jtulach@1334: * True if zone references to a shared TimeZone object. jtulach@1334: */ jtulach@1334: transient private boolean sharedZone = false; jtulach@1334: jtulach@1334: /** jtulach@1334: * The first day of the week, with possible values SUNDAY, jtulach@1334: * MONDAY, etc. This is a locale-dependent value. jtulach@1334: * @serial jtulach@1334: */ jtulach@1334: private int firstDayOfWeek; jtulach@1334: jtulach@1334: /** jtulach@1334: * The number of days required for the first week in a month or year, jtulach@1334: * with possible values from 1 to 7. This is a locale-dependent value. jtulach@1334: * @serial jtulach@1334: */ jtulach@1334: private int minimalDaysInFirstWeek; jtulach@1334: jtulach@1334: /** jtulach@1334: * Cache to hold the firstDayOfWeek and minimalDaysInFirstWeek jtulach@1334: * of a Locale. jtulach@1334: */ jtulach@1334: private static final ConcurrentMap cachedLocaleData jtulach@1334: = new ConcurrentHashMap(3); jtulach@1334: jtulach@1334: // Special values of stamp[] jtulach@1334: /** jtulach@1334: * The corresponding fields[] has no value. jtulach@1334: */ jtulach@1334: private static final int UNSET = 0; jtulach@1334: jtulach@1334: /** jtulach@1334: * The value of the corresponding fields[] has been calculated internally. jtulach@1334: */ jtulach@1334: private static final int COMPUTED = 1; jtulach@1334: jtulach@1334: /** jtulach@1334: * The value of the corresponding fields[] has been set externally. Stamp jtulach@1334: * values which are greater than 1 represents the (pseudo) time when the jtulach@1334: * corresponding fields[] value was set. jtulach@1334: */ jtulach@1334: private static final int MINIMUM_USER_STAMP = 2; jtulach@1334: jtulach@1334: /** jtulach@1334: * The mask value that represents all of the fields. jtulach@1334: */ jtulach@1334: static final int ALL_FIELDS = (1 << FIELD_COUNT) - 1; jtulach@1334: jtulach@1334: /** jtulach@1334: * The next available value for stamp[], an internal array. jtulach@1334: * This actually should not be written out to the stream, and will probably jtulach@1334: * be removed from the stream in the near future. In the meantime, jtulach@1334: * a value of MINIMUM_USER_STAMP should be used. jtulach@1334: * @serial jtulach@1334: */ jtulach@1334: private int nextStamp = MINIMUM_USER_STAMP; jtulach@1334: jtulach@1334: // the internal serial version which says which version was written jtulach@1334: // - 0 (default) for version up to JDK 1.1.5 jtulach@1334: // - 1 for version from JDK 1.1.6, which writes a correct 'time' value jtulach@1334: // as well as compatible values for other fields. This is a jtulach@1334: // transitional format. jtulach@1334: // - 2 (not implemented yet) a future version, in which fields[], jtulach@1334: // areFieldsSet, and isTimeSet become transient, and isSet[] is jtulach@1334: // removed. In JDK 1.1.6 we write a format compatible with version 2. jtulach@1334: static final int currentSerialVersion = 1; jtulach@1334: jtulach@1334: /** jtulach@1334: * The version of the serialized data on the stream. Possible values: jtulach@1334: *

jtulach@1334: *
0 or not present on stream
jtulach@1334: *
jtulach@1334: * JDK 1.1.5 or earlier. jtulach@1334: *
jtulach@1334: *
1
jtulach@1334: *
jtulach@1334: * JDK 1.1.6 or later. Writes a correct 'time' value jtulach@1334: * as well as compatible values for other fields. This is a jtulach@1334: * transitional format. jtulach@1334: *
jtulach@1334: *
jtulach@1334: * When streaming out this class, the most recent format jtulach@1334: * and the highest allowable serialVersionOnStream jtulach@1334: * is written. jtulach@1334: * @serial jtulach@1334: * @since JDK1.1.6 jtulach@1334: */ jtulach@1334: private int serialVersionOnStream = currentSerialVersion; jtulach@1334: jtulach@1334: // Proclaim serialization compatibility with JDK 1.1 jtulach@1334: static final long serialVersionUID = -1807547505821590642L; jtulach@1334: jtulach@1334: // Mask values for calendar fields jtulach@1334: final static int ERA_MASK = (1 << ERA); jtulach@1334: final static int YEAR_MASK = (1 << YEAR); jtulach@1334: final static int MONTH_MASK = (1 << MONTH); jtulach@1334: final static int WEEK_OF_YEAR_MASK = (1 << WEEK_OF_YEAR); jtulach@1334: final static int WEEK_OF_MONTH_MASK = (1 << WEEK_OF_MONTH); jtulach@1334: final static int DAY_OF_MONTH_MASK = (1 << DAY_OF_MONTH); jtulach@1334: final static int DATE_MASK = DAY_OF_MONTH_MASK; jtulach@1334: final static int DAY_OF_YEAR_MASK = (1 << DAY_OF_YEAR); jtulach@1334: final static int DAY_OF_WEEK_MASK = (1 << DAY_OF_WEEK); jtulach@1334: final static int DAY_OF_WEEK_IN_MONTH_MASK = (1 << DAY_OF_WEEK_IN_MONTH); jtulach@1334: final static int AM_PM_MASK = (1 << AM_PM); jtulach@1334: final static int HOUR_MASK = (1 << HOUR); jtulach@1334: final static int HOUR_OF_DAY_MASK = (1 << HOUR_OF_DAY); jtulach@1334: final static int MINUTE_MASK = (1 << MINUTE); jtulach@1334: final static int SECOND_MASK = (1 << SECOND); jtulach@1334: final static int MILLISECOND_MASK = (1 << MILLISECOND); jtulach@1334: final static int ZONE_OFFSET_MASK = (1 << ZONE_OFFSET); jtulach@1334: final static int DST_OFFSET_MASK = (1 << DST_OFFSET); jtulach@1334: jtulach@1334: /** jtulach@1334: * Constructs a Calendar with the default time zone jtulach@1334: * and locale. jtulach@1334: * @see TimeZone#getDefault jtulach@1334: */ jtulach@1334: protected Calendar() jtulach@1334: { jtulach@1334: this(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT)); jtulach@1334: sharedZone = true; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Constructs a calendar with the specified time zone and locale. jtulach@1334: * jtulach@1334: * @param zone the time zone to use jtulach@1334: * @param aLocale the locale for the week data jtulach@1334: */ jtulach@1334: protected Calendar(TimeZone zone, Locale aLocale) jtulach@1334: { jtulach@1334: fields = new int[FIELD_COUNT]; jtulach@1334: isSet = new boolean[FIELD_COUNT]; jtulach@1334: stamp = new int[FIELD_COUNT]; jtulach@1334: jtulach@1334: this.zone = zone; jtulach@1334: setWeekCountData(aLocale); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Gets a calendar using the default time zone and locale. The jtulach@1334: * Calendar returned is based on the current time jtulach@1334: * in the default time zone with the default locale. jtulach@1334: * jtulach@1334: * @return a Calendar. jtulach@1334: */ jtulach@1334: public static Calendar getInstance() jtulach@1334: { jtulach@1334: Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT)); jtulach@1334: cal.sharedZone = true; jtulach@1334: return cal; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Gets a calendar using the specified time zone and default locale. jtulach@1334: * The Calendar returned is based on the current time jtulach@1334: * in the given time zone with the default locale. jtulach@1334: * jtulach@1334: * @param zone the time zone to use jtulach@1334: * @return a Calendar. jtulach@1334: */ jtulach@1334: public static Calendar getInstance(TimeZone zone) jtulach@1334: { jtulach@1334: return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT)); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Gets a calendar using the default time zone and specified locale. jtulach@1334: * The Calendar returned is based on the current time jtulach@1334: * in the default time zone with the given locale. jtulach@1334: * jtulach@1334: * @param aLocale the locale for the week data jtulach@1334: * @return a Calendar. jtulach@1334: */ jtulach@1334: public static Calendar getInstance(Locale aLocale) jtulach@1334: { jtulach@1334: Calendar cal = createCalendar(TimeZone.getDefaultRef(), aLocale); jtulach@1334: cal.sharedZone = true; jtulach@1334: return cal; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Gets a calendar with the specified time zone and locale. jtulach@1334: * The Calendar returned is based on the current time jtulach@1334: * in the given time zone with the given locale. jtulach@1334: * jtulach@1334: * @param zone the time zone to use jtulach@1334: * @param aLocale the locale for the week data jtulach@1334: * @return a Calendar. jtulach@1334: */ jtulach@1334: public static Calendar getInstance(TimeZone zone, jtulach@1334: Locale aLocale) jtulach@1334: { jtulach@1334: return createCalendar(zone, aLocale); jtulach@1334: } jtulach@1334: jtulach@1334: private static Calendar createCalendar(TimeZone zone, jtulach@1334: Locale aLocale) jtulach@1334: { jtulach@1334: Calendar cal = null; jtulach@1334: jtulach@1334: String caltype = aLocale.getUnicodeLocaleType("ca"); jtulach@1334: if (caltype == null) { jtulach@1334: // Calendar type is not specified. jtulach@1334: // If the specified locale is a Thai locale, jtulach@1334: // returns a BuddhistCalendar instance. jtulach@1334: if ("th".equals(aLocale.getLanguage()) jtulach@1334: && ("TH".equals(aLocale.getCountry()))) { jaroslav@1340: // cal = new BuddhistCalendar(zone, aLocale); jtulach@1334: } else { jaroslav@1340: // cal = new GregorianCalendar(zone, aLocale); jtulach@1334: } jtulach@1334: } else if (caltype.equals("japanese")) { jaroslav@1340: // cal = new JapaneseImperialCalendar(zone, aLocale); jtulach@1334: } else if (caltype.equals("buddhist")) { jaroslav@1340: // cal = new BuddhistCalendar(zone, aLocale); jtulach@1334: } else { jtulach@1334: // Unsupported calendar type. jtulach@1334: // Use Gregorian calendar as a fallback. jaroslav@1340: // cal = new GregorianCalendar(zone, aLocale); jtulach@1334: } jtulach@1334: jtulach@1334: return cal; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns an array of all locales for which the getInstance jtulach@1334: * methods of this class can return localized instances. jtulach@1334: * The array returned must contain at least a Locale jtulach@1334: * instance equal to {@link java.util.Locale#US Locale.US}. jtulach@1334: * jtulach@1334: * @return An array of locales for which localized jtulach@1334: * Calendar instances are available. jtulach@1334: */ jtulach@1334: public static synchronized Locale[] getAvailableLocales() jtulach@1334: { jtulach@1334: return DateFormat.getAvailableLocales(); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Converts the current calendar field values in {@link #fields fields[]} jtulach@1334: * to the millisecond time value jtulach@1334: * {@link #time}. jtulach@1334: * jtulach@1334: * @see #complete() jtulach@1334: * @see #computeFields() jtulach@1334: */ jtulach@1334: protected abstract void computeTime(); jtulach@1334: jtulach@1334: /** jtulach@1334: * Converts the current millisecond time value {@link #time} jtulach@1334: * to calendar field values in {@link #fields fields[]}. jtulach@1334: * This allows you to sync up the calendar field values with jtulach@1334: * a new time that is set for the calendar. The time is not jtulach@1334: * recomputed first; to recompute the time, then the fields, call the jtulach@1334: * {@link #complete()} method. jtulach@1334: * jtulach@1334: * @see #computeTime() jtulach@1334: */ jtulach@1334: protected abstract void computeFields(); jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns a Date object representing this jtulach@1334: * Calendar's time value (millisecond offset from the Epoch"). jtulach@1334: * jtulach@1334: * @return a Date representing the time value. jtulach@1334: * @see #setTime(Date) jtulach@1334: * @see #getTimeInMillis() jtulach@1334: */ jtulach@1334: public final Date getTime() { jtulach@1334: return new Date(getTimeInMillis()); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets this Calendar's time with the given Date. jtulach@1334: *

jtulach@1334: * Note: Calling setTime() with jtulach@1334: * Date(Long.MAX_VALUE) or Date(Long.MIN_VALUE) jtulach@1334: * may yield incorrect field values from get(). jtulach@1334: * jtulach@1334: * @param date the given Date. jtulach@1334: * @see #getTime() jtulach@1334: * @see #setTimeInMillis(long) jtulach@1334: */ jtulach@1334: public final void setTime(Date date) { jtulach@1334: setTimeInMillis(date.getTime()); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns this Calendar's time value in milliseconds. jtulach@1334: * jtulach@1334: * @return the current time as UTC milliseconds from the epoch. jtulach@1334: * @see #getTime() jtulach@1334: * @see #setTimeInMillis(long) jtulach@1334: */ jtulach@1334: public long getTimeInMillis() { jtulach@1334: if (!isTimeSet) { jtulach@1334: updateTime(); jtulach@1334: } jtulach@1334: return time; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets this Calendar's current time from the given long value. jtulach@1334: * jtulach@1334: * @param millis the new time in UTC milliseconds from the epoch. jtulach@1334: * @see #setTime(Date) jtulach@1334: * @see #getTimeInMillis() jtulach@1334: */ jtulach@1334: public void setTimeInMillis(long millis) { jtulach@1334: // If we don't need to recalculate the calendar field values, jtulach@1334: // do nothing. jaroslav@1340: // if (time == millis && isTimeSet && areFieldsSet && areAllFieldsSet jaroslav@1340: // && (zone instanceof ZoneInfo) && !((ZoneInfo)zone).isDirty()) { jaroslav@1340: // return; jaroslav@1340: // } jtulach@1334: time = millis; jtulach@1334: isTimeSet = true; jtulach@1334: areFieldsSet = false; jtulach@1334: computeFields(); jtulach@1334: areAllFieldsSet = areFieldsSet = true; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the value of the given calendar field. In lenient mode, jtulach@1334: * all calendar fields are normalized. In non-lenient mode, all jtulach@1334: * calendar fields are validated and this method throws an jtulach@1334: * exception if any calendar fields have out-of-range values. The jtulach@1334: * normalization and validation are handled by the jtulach@1334: * {@link #complete()} method, which process is calendar jtulach@1334: * system dependent. jtulach@1334: * jtulach@1334: * @param field the given calendar field. jtulach@1334: * @return the value for the given calendar field. jtulach@1334: * @throws ArrayIndexOutOfBoundsException if the specified field is out of range jtulach@1334: * (field < 0 || field >= FIELD_COUNT). jtulach@1334: * @see #set(int,int) jtulach@1334: * @see #complete() jtulach@1334: */ jtulach@1334: public int get(int field) jtulach@1334: { jtulach@1334: complete(); jtulach@1334: return internalGet(field); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the value of the given calendar field. This method does jtulach@1334: * not involve normalization or validation of the field value. jtulach@1334: * jtulach@1334: * @param field the given calendar field. jtulach@1334: * @return the value for the given calendar field. jtulach@1334: * @see #get(int) jtulach@1334: */ jtulach@1334: protected final int internalGet(int field) jtulach@1334: { jtulach@1334: return fields[field]; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets the value of the given calendar field. This method does jtulach@1334: * not affect any setting state of the field in this jtulach@1334: * Calendar instance. jtulach@1334: * jtulach@1334: * @throws IndexOutOfBoundsException if the specified field is out of range jtulach@1334: * (field < 0 || field >= FIELD_COUNT). jtulach@1334: * @see #areFieldsSet jtulach@1334: * @see #isTimeSet jtulach@1334: * @see #areAllFieldsSet jtulach@1334: * @see #set(int,int) jtulach@1334: */ jtulach@1334: final void internalSet(int field, int value) jtulach@1334: { jtulach@1334: fields[field] = value; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets the given calendar field to the given value. The value is not jtulach@1334: * interpreted by this method regardless of the leniency mode. jtulach@1334: * jtulach@1334: * @param field the given calendar field. jtulach@1334: * @param value the value to be set for the given calendar field. jtulach@1334: * @throws ArrayIndexOutOfBoundsException if the specified field is out of range jtulach@1334: * (field < 0 || field >= FIELD_COUNT). jtulach@1334: * in non-lenient mode. jtulach@1334: * @see #set(int,int,int) jtulach@1334: * @see #set(int,int,int,int,int) jtulach@1334: * @see #set(int,int,int,int,int,int) jtulach@1334: * @see #get(int) jtulach@1334: */ jtulach@1334: public void set(int field, int value) jtulach@1334: { jtulach@1334: // If the fields are partially normalized, calculate all the jtulach@1334: // fields before changing any fields. jtulach@1334: if (areFieldsSet && !areAllFieldsSet) { jtulach@1334: computeFields(); jtulach@1334: } jtulach@1334: internalSet(field, value); jtulach@1334: isTimeSet = false; jtulach@1334: areFieldsSet = false; jtulach@1334: isSet[field] = true; jtulach@1334: stamp[field] = nextStamp++; jtulach@1334: if (nextStamp == Integer.MAX_VALUE) { jtulach@1334: adjustStamp(); jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets the values for the calendar fields YEAR, jtulach@1334: * MONTH, and DAY_OF_MONTH. jtulach@1334: * Previous values of other calendar fields are retained. If this is not desired, jtulach@1334: * call {@link #clear()} first. jtulach@1334: * jtulach@1334: * @param year the value used to set the YEAR calendar field. jtulach@1334: * @param month the value used to set the MONTH calendar field. jtulach@1334: * Month value is 0-based. e.g., 0 for January. jtulach@1334: * @param date the value used to set the DAY_OF_MONTH calendar field. jtulach@1334: * @see #set(int,int) jtulach@1334: * @see #set(int,int,int,int,int) jtulach@1334: * @see #set(int,int,int,int,int,int) jtulach@1334: */ jtulach@1334: public final void set(int year, int month, int date) jtulach@1334: { jtulach@1334: set(YEAR, year); jtulach@1334: set(MONTH, month); jtulach@1334: set(DATE, date); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets the values for the calendar fields YEAR, jtulach@1334: * MONTH, DAY_OF_MONTH, jtulach@1334: * HOUR_OF_DAY, and MINUTE. jtulach@1334: * Previous values of other fields are retained. If this is not desired, jtulach@1334: * call {@link #clear()} first. jtulach@1334: * jtulach@1334: * @param year the value used to set the YEAR calendar field. jtulach@1334: * @param month the value used to set the MONTH calendar field. jtulach@1334: * Month value is 0-based. e.g., 0 for January. jtulach@1334: * @param date the value used to set the DAY_OF_MONTH calendar field. jtulach@1334: * @param hourOfDay the value used to set the HOUR_OF_DAY calendar field. jtulach@1334: * @param minute the value used to set the MINUTE calendar field. jtulach@1334: * @see #set(int,int) jtulach@1334: * @see #set(int,int,int) jtulach@1334: * @see #set(int,int,int,int,int,int) jtulach@1334: */ jtulach@1334: public final void set(int year, int month, int date, int hourOfDay, int minute) jtulach@1334: { jtulach@1334: set(YEAR, year); jtulach@1334: set(MONTH, month); jtulach@1334: set(DATE, date); jtulach@1334: set(HOUR_OF_DAY, hourOfDay); jtulach@1334: set(MINUTE, minute); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets the values for the fields YEAR, MONTH, jtulach@1334: * DAY_OF_MONTH, HOUR, MINUTE, and jtulach@1334: * SECOND. jtulach@1334: * Previous values of other fields are retained. If this is not desired, jtulach@1334: * call {@link #clear()} first. jtulach@1334: * jtulach@1334: * @param year the value used to set the YEAR calendar field. jtulach@1334: * @param month the value used to set the MONTH calendar field. jtulach@1334: * Month value is 0-based. e.g., 0 for January. jtulach@1334: * @param date the value used to set the DAY_OF_MONTH calendar field. jtulach@1334: * @param hourOfDay the value used to set the HOUR_OF_DAY calendar field. jtulach@1334: * @param minute the value used to set the MINUTE calendar field. jtulach@1334: * @param second the value used to set the SECOND calendar field. jtulach@1334: * @see #set(int,int) jtulach@1334: * @see #set(int,int,int) jtulach@1334: * @see #set(int,int,int,int,int) jtulach@1334: */ jtulach@1334: public final void set(int year, int month, int date, int hourOfDay, int minute, jtulach@1334: int second) jtulach@1334: { jtulach@1334: set(YEAR, year); jtulach@1334: set(MONTH, month); jtulach@1334: set(DATE, date); jtulach@1334: set(HOUR_OF_DAY, hourOfDay); jtulach@1334: set(MINUTE, minute); jtulach@1334: set(SECOND, second); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets all the calendar field values and the time value jtulach@1334: * (millisecond offset from the Epoch) of jtulach@1334: * this Calendar undefined. This means that {@link jtulach@1334: * #isSet(int) isSet()} will return false for all the jtulach@1334: * calendar fields, and the date and time calculations will treat jtulach@1334: * the fields as if they had never been set. A jtulach@1334: * Calendar implementation class may use its specific jtulach@1334: * default field values for date/time calculations. For example, jtulach@1334: * GregorianCalendar uses 1970 if the jtulach@1334: * YEAR field value is undefined. jtulach@1334: * jtulach@1334: * @see #clear(int) jtulach@1334: */ jtulach@1334: public final void clear() jtulach@1334: { jtulach@1334: for (int i = 0; i < fields.length; ) { jtulach@1334: stamp[i] = fields[i] = 0; // UNSET == 0 jtulach@1334: isSet[i++] = false; jtulach@1334: } jtulach@1334: areAllFieldsSet = areFieldsSet = false; jtulach@1334: isTimeSet = false; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets the given calendar field value and the time value jtulach@1334: * (millisecond offset from the Epoch) of jtulach@1334: * this Calendar undefined. This means that {@link jtulach@1334: * #isSet(int) isSet(field)} will return false, and jtulach@1334: * the date and time calculations will treat the field as if it jtulach@1334: * had never been set. A Calendar implementation jtulach@1334: * class may use the field's specific default value for date and jtulach@1334: * time calculations. jtulach@1334: * jtulach@1334: *

The {@link #HOUR_OF_DAY}, {@link #HOUR} and {@link #AM_PM} jtulach@1334: * fields are handled independently and the the resolution rule for the time of jtulach@1334: * day is applied. Clearing one of the fields doesn't reset jtulach@1334: * the hour of day value of this Calendar. Use {@link jtulach@1334: * #set(int,int) set(Calendar.HOUR_OF_DAY, 0)} to reset the hour jtulach@1334: * value. jtulach@1334: * jtulach@1334: * @param field the calendar field to be cleared. jtulach@1334: * @see #clear() jtulach@1334: */ jtulach@1334: public final void clear(int field) jtulach@1334: { jtulach@1334: fields[field] = 0; jtulach@1334: stamp[field] = UNSET; jtulach@1334: isSet[field] = false; jtulach@1334: jtulach@1334: areAllFieldsSet = areFieldsSet = false; jtulach@1334: isTimeSet = false; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Determines if the given calendar field has a value set, jtulach@1334: * including cases that the value has been set by internal fields jtulach@1334: * calculations triggered by a get method call. jtulach@1334: * jtulach@1334: * @return true if the given calendar field has a value set; jtulach@1334: * false otherwise. jtulach@1334: */ jtulach@1334: public final boolean isSet(int field) jtulach@1334: { jtulach@1334: return stamp[field] != UNSET; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the string representation of the calendar jtulach@1334: * field value in the given style and jtulach@1334: * locale. If no string representation is jtulach@1334: * applicable, null is returned. This method calls jtulach@1334: * {@link Calendar#get(int) get(field)} to get the calendar jtulach@1334: * field value if the string representation is jtulach@1334: * applicable to the given calendar field. jtulach@1334: * jtulach@1334: *

For example, if this Calendar is a jtulach@1334: * GregorianCalendar and its date is 2005-01-01, then jtulach@1334: * the string representation of the {@link #MONTH} field would be jtulach@1334: * "January" in the long style in an English locale or "Jan" in jtulach@1334: * the short style. However, no string representation would be jtulach@1334: * available for the {@link #DAY_OF_MONTH} field, and this method jtulach@1334: * would return null. jtulach@1334: * jtulach@1334: *

The default implementation supports the calendar fields for jtulach@1334: * which a {@link DateFormatSymbols} has names in the given jtulach@1334: * locale. jtulach@1334: * jtulach@1334: * @param field jtulach@1334: * the calendar field for which the string representation jtulach@1334: * is returned jtulach@1334: * @param style jtulach@1334: * the style applied to the string representation; one of jtulach@1334: * {@link #SHORT} or {@link #LONG}. jtulach@1334: * @param locale jtulach@1334: * the locale for the string representation jtulach@1334: * @return the string representation of the given jtulach@1334: * field in the given style, or jtulach@1334: * null if no string representation is jtulach@1334: * applicable. jtulach@1334: * @exception IllegalArgumentException jtulach@1334: * if field or style is invalid, jtulach@1334: * or if this Calendar is non-lenient and any jtulach@1334: * of the calendar fields have invalid values jtulach@1334: * @exception NullPointerException jtulach@1334: * if locale is null jtulach@1334: * @since 1.6 jtulach@1334: */ jtulach@1334: public String getDisplayName(int field, int style, Locale locale) { jtulach@1334: if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale, jtulach@1334: ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) { jtulach@1334: return null; jtulach@1334: } jtulach@1334: jtulach@1334: DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale); jtulach@1334: String[] strings = getFieldStrings(field, style, symbols); jtulach@1334: if (strings != null) { jtulach@1334: int fieldValue = get(field); jtulach@1334: if (fieldValue < strings.length) { jtulach@1334: return strings[fieldValue]; jtulach@1334: } jtulach@1334: } jtulach@1334: return null; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns a Map containing all names of the calendar jtulach@1334: * field in the given style and jtulach@1334: * locale and their corresponding field values. For jtulach@1334: * example, if this Calendar is a {@link jtulach@1334: * GregorianCalendar}, the returned map would contain "Jan" to jtulach@1334: * {@link #JANUARY}, "Feb" to {@link #FEBRUARY}, and so on, in the jtulach@1334: * {@linkplain #SHORT short} style in an English locale. jtulach@1334: * jtulach@1334: *

The values of other calendar fields may be taken into jtulach@1334: * account to determine a set of display names. For example, if jtulach@1334: * this Calendar is a lunisolar calendar system and jtulach@1334: * the year value given by the {@link #YEAR} field has a leap jtulach@1334: * month, this method would return month names containing the leap jtulach@1334: * month name, and month names are mapped to their values specific jtulach@1334: * for the year. jtulach@1334: * jtulach@1334: *

The default implementation supports display names contained in jtulach@1334: * a {@link DateFormatSymbols}. For example, if field jtulach@1334: * is {@link #MONTH} and style is {@link jtulach@1334: * #ALL_STYLES}, this method returns a Map containing jtulach@1334: * all strings returned by {@link DateFormatSymbols#getShortMonths()} jtulach@1334: * and {@link DateFormatSymbols#getMonths()}. jtulach@1334: * jtulach@1334: * @param field jtulach@1334: * the calendar field for which the display names are returned jtulach@1334: * @param style jtulach@1334: * the style applied to the display names; one of {@link jtulach@1334: * #SHORT}, {@link #LONG}, or {@link #ALL_STYLES}. jtulach@1334: * @param locale jtulach@1334: * the locale for the display names jtulach@1334: * @return a Map containing all display names in jtulach@1334: * style and locale and their jtulach@1334: * field values, or null if no display names jtulach@1334: * are defined for field jtulach@1334: * @exception IllegalArgumentException jtulach@1334: * if field or style is invalid, jtulach@1334: * or if this Calendar is non-lenient and any jtulach@1334: * of the calendar fields have invalid values jtulach@1334: * @exception NullPointerException jtulach@1334: * if locale is null jtulach@1334: * @since 1.6 jtulach@1334: */ jtulach@1334: public Map getDisplayNames(int field, int style, Locale locale) { jtulach@1334: if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale, jtulach@1334: ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) { jtulach@1334: return null; jtulach@1334: } jtulach@1334: jtulach@1334: // ALL_STYLES jtulach@1334: if (style == ALL_STYLES) { jtulach@1334: Map shortNames = getDisplayNamesImpl(field, SHORT, locale); jtulach@1334: if (field == ERA || field == AM_PM) { jtulach@1334: return shortNames; jtulach@1334: } jtulach@1334: Map longNames = getDisplayNamesImpl(field, LONG, locale); jtulach@1334: if (shortNames == null) { jtulach@1334: return longNames; jtulach@1334: } jtulach@1334: if (longNames != null) { jtulach@1334: shortNames.putAll(longNames); jtulach@1334: } jtulach@1334: return shortNames; jtulach@1334: } jtulach@1334: jtulach@1334: // SHORT or LONG jtulach@1334: return getDisplayNamesImpl(field, style, locale); jtulach@1334: } jtulach@1334: jtulach@1334: private Map getDisplayNamesImpl(int field, int style, Locale locale) { jtulach@1334: DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale); jtulach@1334: String[] strings = getFieldStrings(field, style, symbols); jtulach@1334: if (strings != null) { jtulach@1334: Map names = new HashMap(); jtulach@1334: for (int i = 0; i < strings.length; i++) { jtulach@1334: if (strings[i].length() == 0) { jtulach@1334: continue; jtulach@1334: } jtulach@1334: names.put(strings[i], i); jtulach@1334: } jtulach@1334: return names; jtulach@1334: } jtulach@1334: return null; jtulach@1334: } jtulach@1334: jtulach@1334: boolean checkDisplayNameParams(int field, int style, int minStyle, int maxStyle, jtulach@1334: Locale locale, int fieldMask) { jtulach@1334: if (field < 0 || field >= fields.length || jtulach@1334: style < minStyle || style > maxStyle) { jtulach@1334: throw new IllegalArgumentException(); jtulach@1334: } jtulach@1334: if (locale == null) { jtulach@1334: throw new NullPointerException(); jtulach@1334: } jtulach@1334: return isFieldSet(fieldMask, field); jtulach@1334: } jtulach@1334: jtulach@1334: private String[] getFieldStrings(int field, int style, DateFormatSymbols symbols) { jtulach@1334: String[] strings = null; jtulach@1334: switch (field) { jtulach@1334: case ERA: jtulach@1334: strings = symbols.getEras(); jtulach@1334: break; jtulach@1334: jtulach@1334: case MONTH: jtulach@1334: strings = (style == LONG) ? symbols.getMonths() : symbols.getShortMonths(); jtulach@1334: break; jtulach@1334: jtulach@1334: case DAY_OF_WEEK: jtulach@1334: strings = (style == LONG) ? symbols.getWeekdays() : symbols.getShortWeekdays(); jtulach@1334: break; jtulach@1334: jtulach@1334: case AM_PM: jtulach@1334: strings = symbols.getAmPmStrings(); jtulach@1334: break; jtulach@1334: } jtulach@1334: return strings; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Fills in any unset fields in the calendar fields. First, the {@link jtulach@1334: * #computeTime()} method is called if the time value (millisecond offset jtulach@1334: * from the Epoch) has not been calculated from jtulach@1334: * calendar field values. Then, the {@link #computeFields()} method is jtulach@1334: * called to calculate all calendar field values. jtulach@1334: */ jtulach@1334: protected void complete() jtulach@1334: { jtulach@1334: if (!isTimeSet) jtulach@1334: updateTime(); jtulach@1334: if (!areFieldsSet || !areAllFieldsSet) { jtulach@1334: computeFields(); // fills in unset fields jtulach@1334: areAllFieldsSet = areFieldsSet = true; jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns whether the value of the specified calendar field has been set jtulach@1334: * externally by calling one of the setter methods rather than by the jtulach@1334: * internal time calculation. jtulach@1334: * jtulach@1334: * @return true if the field has been set externally, jtulach@1334: * false otherwise. jtulach@1334: * @exception IndexOutOfBoundsException if the specified jtulach@1334: * field is out of range jtulach@1334: * (field < 0 || field >= FIELD_COUNT). jtulach@1334: * @see #selectFields() jtulach@1334: * @see #setFieldsComputed(int) jtulach@1334: */ jtulach@1334: final boolean isExternallySet(int field) { jtulach@1334: return stamp[field] >= MINIMUM_USER_STAMP; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns a field mask (bit mask) indicating all calendar fields that jtulach@1334: * have the state of externally or internally set. jtulach@1334: * jtulach@1334: * @return a bit mask indicating set state fields jtulach@1334: */ jtulach@1334: final int getSetStateFields() { jtulach@1334: int mask = 0; jtulach@1334: for (int i = 0; i < fields.length; i++) { jtulach@1334: if (stamp[i] != UNSET) { jtulach@1334: mask |= 1 << i; jtulach@1334: } jtulach@1334: } jtulach@1334: return mask; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets the state of the specified calendar fields to jtulach@1334: * computed. This state means that the specified calendar fields jtulach@1334: * have valid values that have been set by internal time calculation jtulach@1334: * rather than by calling one of the setter methods. jtulach@1334: * jtulach@1334: * @param fieldMask the field to be marked as computed. jtulach@1334: * @exception IndexOutOfBoundsException if the specified jtulach@1334: * field is out of range jtulach@1334: * (field < 0 || field >= FIELD_COUNT). jtulach@1334: * @see #isExternallySet(int) jtulach@1334: * @see #selectFields() jtulach@1334: */ jtulach@1334: final void setFieldsComputed(int fieldMask) { jtulach@1334: if (fieldMask == ALL_FIELDS) { jtulach@1334: for (int i = 0; i < fields.length; i++) { jtulach@1334: stamp[i] = COMPUTED; jtulach@1334: isSet[i] = true; jtulach@1334: } jtulach@1334: areFieldsSet = areAllFieldsSet = true; jtulach@1334: } else { jtulach@1334: for (int i = 0; i < fields.length; i++) { jtulach@1334: if ((fieldMask & 1) == 1) { jtulach@1334: stamp[i] = COMPUTED; jtulach@1334: isSet[i] = true; jtulach@1334: } else { jtulach@1334: if (areAllFieldsSet && !isSet[i]) { jtulach@1334: areAllFieldsSet = false; jtulach@1334: } jtulach@1334: } jtulach@1334: fieldMask >>>= 1; jtulach@1334: } jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets the state of the calendar fields that are not specified jtulach@1334: * by fieldMask to unset. If fieldMask jtulach@1334: * specifies all the calendar fields, then the state of this jtulach@1334: * Calendar becomes that all the calendar fields are in sync jtulach@1334: * with the time value (millisecond offset from the Epoch). jtulach@1334: * jtulach@1334: * @param fieldMask the field mask indicating which calendar fields are in jtulach@1334: * sync with the time value. jtulach@1334: * @exception IndexOutOfBoundsException if the specified jtulach@1334: * field is out of range jtulach@1334: * (field < 0 || field >= FIELD_COUNT). jtulach@1334: * @see #isExternallySet(int) jtulach@1334: * @see #selectFields() jtulach@1334: */ jtulach@1334: final void setFieldsNormalized(int fieldMask) { jtulach@1334: if (fieldMask != ALL_FIELDS) { jtulach@1334: for (int i = 0; i < fields.length; i++) { jtulach@1334: if ((fieldMask & 1) == 0) { jtulach@1334: stamp[i] = fields[i] = 0; // UNSET == 0 jtulach@1334: isSet[i] = false; jtulach@1334: } jtulach@1334: fieldMask >>= 1; jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: // Some or all of the fields are in sync with the jtulach@1334: // milliseconds, but the stamp values are not normalized yet. jtulach@1334: areFieldsSet = true; jtulach@1334: areAllFieldsSet = false; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns whether the calendar fields are partially in sync with the time jtulach@1334: * value or fully in sync but not stamp values are not normalized yet. jtulach@1334: */ jtulach@1334: final boolean isPartiallyNormalized() { jtulach@1334: return areFieldsSet && !areAllFieldsSet; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns whether the calendar fields are fully in sync with the time jtulach@1334: * value. jtulach@1334: */ jtulach@1334: final boolean isFullyNormalized() { jtulach@1334: return areFieldsSet && areAllFieldsSet; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Marks this Calendar as not sync'd. jtulach@1334: */ jtulach@1334: final void setUnnormalized() { jtulach@1334: areFieldsSet = areAllFieldsSet = false; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns whether the specified field is on in the jtulach@1334: * fieldMask. jtulach@1334: */ jtulach@1334: static final boolean isFieldSet(int fieldMask, int field) { jtulach@1334: return (fieldMask & (1 << field)) != 0; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns a field mask indicating which calendar field values jtulach@1334: * to be used to calculate the time value. The calendar fields are jtulach@1334: * returned as a bit mask, each bit of which corresponds to a field, i.e., jtulach@1334: * the mask value of field is (1 << jtulach@1334: * field). For example, 0x26 represents the YEAR, jtulach@1334: * MONTH, and DAY_OF_MONTH fields (i.e., 0x26 is jtulach@1334: * equal to jtulach@1334: * (1<<YEAR)|(1<<MONTH)|(1<<DAY_OF_MONTH)). jtulach@1334: * jtulach@1334: *

This method supports the calendar fields resolution as described in jtulach@1334: * the class description. If the bit mask for a given field is on and its jtulach@1334: * field has not been set (i.e., isSet(field) is jtulach@1334: * false), then the default value of the field has to be jtulach@1334: * used, which case means that the field has been selected because the jtulach@1334: * selected combination involves the field. jtulach@1334: * jtulach@1334: * @return a bit mask of selected fields jtulach@1334: * @see #isExternallySet(int) jtulach@1334: * @see #setInternallySetState(int) jtulach@1334: */ jtulach@1334: final int selectFields() { jtulach@1334: // This implementation has been taken from the GregorianCalendar class. jtulach@1334: jtulach@1334: // The YEAR field must always be used regardless of its SET jtulach@1334: // state because YEAR is a mandatory field to determine the date jtulach@1334: // and the default value (EPOCH_YEAR) may change through the jtulach@1334: // normalization process. jtulach@1334: int fieldMask = YEAR_MASK; jtulach@1334: jtulach@1334: if (stamp[ERA] != UNSET) { jtulach@1334: fieldMask |= ERA_MASK; jtulach@1334: } jtulach@1334: // Find the most recent group of fields specifying the day within jtulach@1334: // the year. These may be any of the following combinations: jtulach@1334: // MONTH + DAY_OF_MONTH jtulach@1334: // MONTH + WEEK_OF_MONTH + DAY_OF_WEEK jtulach@1334: // MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK jtulach@1334: // DAY_OF_YEAR jtulach@1334: // WEEK_OF_YEAR + DAY_OF_WEEK jtulach@1334: // We look for the most recent of the fields in each group to determine jtulach@1334: // the age of the group. For groups involving a week-related field such jtulach@1334: // as WEEK_OF_MONTH, DAY_OF_WEEK_IN_MONTH, or WEEK_OF_YEAR, both the jtulach@1334: // week-related field and the DAY_OF_WEEK must be set for the group as a jtulach@1334: // whole to be considered. (See bug 4153860 - liu 7/24/98.) jtulach@1334: int dowStamp = stamp[DAY_OF_WEEK]; jtulach@1334: int monthStamp = stamp[MONTH]; jtulach@1334: int domStamp = stamp[DAY_OF_MONTH]; jtulach@1334: int womStamp = aggregateStamp(stamp[WEEK_OF_MONTH], dowStamp); jtulach@1334: int dowimStamp = aggregateStamp(stamp[DAY_OF_WEEK_IN_MONTH], dowStamp); jtulach@1334: int doyStamp = stamp[DAY_OF_YEAR]; jtulach@1334: int woyStamp = aggregateStamp(stamp[WEEK_OF_YEAR], dowStamp); jtulach@1334: jtulach@1334: int bestStamp = domStamp; jtulach@1334: if (womStamp > bestStamp) { jtulach@1334: bestStamp = womStamp; jtulach@1334: } jtulach@1334: if (dowimStamp > bestStamp) { jtulach@1334: bestStamp = dowimStamp; jtulach@1334: } jtulach@1334: if (doyStamp > bestStamp) { jtulach@1334: bestStamp = doyStamp; jtulach@1334: } jtulach@1334: if (woyStamp > bestStamp) { jtulach@1334: bestStamp = woyStamp; jtulach@1334: } jtulach@1334: jtulach@1334: /* No complete combination exists. Look for WEEK_OF_MONTH, jtulach@1334: * DAY_OF_WEEK_IN_MONTH, or WEEK_OF_YEAR alone. Treat DAY_OF_WEEK alone jtulach@1334: * as DAY_OF_WEEK_IN_MONTH. jtulach@1334: */ jtulach@1334: if (bestStamp == UNSET) { jtulach@1334: womStamp = stamp[WEEK_OF_MONTH]; jtulach@1334: dowimStamp = Math.max(stamp[DAY_OF_WEEK_IN_MONTH], dowStamp); jtulach@1334: woyStamp = stamp[WEEK_OF_YEAR]; jtulach@1334: bestStamp = Math.max(Math.max(womStamp, dowimStamp), woyStamp); jtulach@1334: jtulach@1334: /* Treat MONTH alone or no fields at all as DAY_OF_MONTH. This may jtulach@1334: * result in bestStamp = domStamp = UNSET if no fields are set, jtulach@1334: * which indicates DAY_OF_MONTH. jtulach@1334: */ jtulach@1334: if (bestStamp == UNSET) { jtulach@1334: bestStamp = domStamp = monthStamp; jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: if (bestStamp == domStamp || jtulach@1334: (bestStamp == womStamp && stamp[WEEK_OF_MONTH] >= stamp[WEEK_OF_YEAR]) || jtulach@1334: (bestStamp == dowimStamp && stamp[DAY_OF_WEEK_IN_MONTH] >= stamp[WEEK_OF_YEAR])) { jtulach@1334: fieldMask |= MONTH_MASK; jtulach@1334: if (bestStamp == domStamp) { jtulach@1334: fieldMask |= DAY_OF_MONTH_MASK; jtulach@1334: } else { jtulach@1334: assert (bestStamp == womStamp || bestStamp == dowimStamp); jtulach@1334: if (dowStamp != UNSET) { jtulach@1334: fieldMask |= DAY_OF_WEEK_MASK; jtulach@1334: } jtulach@1334: if (womStamp == dowimStamp) { jtulach@1334: // When they are equal, give the priority to jtulach@1334: // WEEK_OF_MONTH for compatibility. jtulach@1334: if (stamp[WEEK_OF_MONTH] >= stamp[DAY_OF_WEEK_IN_MONTH]) { jtulach@1334: fieldMask |= WEEK_OF_MONTH_MASK; jtulach@1334: } else { jtulach@1334: fieldMask |= DAY_OF_WEEK_IN_MONTH_MASK; jtulach@1334: } jtulach@1334: } else { jtulach@1334: if (bestStamp == womStamp) { jtulach@1334: fieldMask |= WEEK_OF_MONTH_MASK; jtulach@1334: } else { jtulach@1334: assert (bestStamp == dowimStamp); jtulach@1334: if (stamp[DAY_OF_WEEK_IN_MONTH] != UNSET) { jtulach@1334: fieldMask |= DAY_OF_WEEK_IN_MONTH_MASK; jtulach@1334: } jtulach@1334: } jtulach@1334: } jtulach@1334: } jtulach@1334: } else { jtulach@1334: assert (bestStamp == doyStamp || bestStamp == woyStamp || jtulach@1334: bestStamp == UNSET); jtulach@1334: if (bestStamp == doyStamp) { jtulach@1334: fieldMask |= DAY_OF_YEAR_MASK; jtulach@1334: } else { jtulach@1334: assert (bestStamp == woyStamp); jtulach@1334: if (dowStamp != UNSET) { jtulach@1334: fieldMask |= DAY_OF_WEEK_MASK; jtulach@1334: } jtulach@1334: fieldMask |= WEEK_OF_YEAR_MASK; jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: // Find the best set of fields specifying the time of day. There jtulach@1334: // are only two possibilities here; the HOUR_OF_DAY or the jtulach@1334: // AM_PM and the HOUR. jtulach@1334: int hourOfDayStamp = stamp[HOUR_OF_DAY]; jtulach@1334: int hourStamp = aggregateStamp(stamp[HOUR], stamp[AM_PM]); jtulach@1334: bestStamp = (hourStamp > hourOfDayStamp) ? hourStamp : hourOfDayStamp; jtulach@1334: jtulach@1334: // if bestStamp is still UNSET, then take HOUR or AM_PM. (See 4846659) jtulach@1334: if (bestStamp == UNSET) { jtulach@1334: bestStamp = Math.max(stamp[HOUR], stamp[AM_PM]); jtulach@1334: } jtulach@1334: jtulach@1334: // Hours jtulach@1334: if (bestStamp != UNSET) { jtulach@1334: if (bestStamp == hourOfDayStamp) { jtulach@1334: fieldMask |= HOUR_OF_DAY_MASK; jtulach@1334: } else { jtulach@1334: fieldMask |= HOUR_MASK; jtulach@1334: if (stamp[AM_PM] != UNSET) { jtulach@1334: fieldMask |= AM_PM_MASK; jtulach@1334: } jtulach@1334: } jtulach@1334: } jtulach@1334: if (stamp[MINUTE] != UNSET) { jtulach@1334: fieldMask |= MINUTE_MASK; jtulach@1334: } jtulach@1334: if (stamp[SECOND] != UNSET) { jtulach@1334: fieldMask |= SECOND_MASK; jtulach@1334: } jtulach@1334: if (stamp[MILLISECOND] != UNSET) { jtulach@1334: fieldMask |= MILLISECOND_MASK; jtulach@1334: } jtulach@1334: if (stamp[ZONE_OFFSET] >= MINIMUM_USER_STAMP) { jtulach@1334: fieldMask |= ZONE_OFFSET_MASK; jtulach@1334: } jtulach@1334: if (stamp[DST_OFFSET] >= MINIMUM_USER_STAMP) { jtulach@1334: fieldMask |= DST_OFFSET_MASK; jtulach@1334: } jtulach@1334: jtulach@1334: return fieldMask; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the pseudo-time-stamp for two fields, given their jtulach@1334: * individual pseudo-time-stamps. If either of the fields jtulach@1334: * is unset, then the aggregate is unset. Otherwise, the jtulach@1334: * aggregate is the later of the two stamps. jtulach@1334: */ jtulach@1334: private static final int aggregateStamp(int stamp_a, int stamp_b) { jtulach@1334: if (stamp_a == UNSET || stamp_b == UNSET) { jtulach@1334: return UNSET; jtulach@1334: } jtulach@1334: return (stamp_a > stamp_b) ? stamp_a : stamp_b; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Compares this Calendar to the specified jtulach@1334: * Object. The result is true if and only if jtulach@1334: * the argument is a Calendar object of the same calendar jtulach@1334: * system that represents the same time value (millisecond offset from the jtulach@1334: * Epoch) under the same jtulach@1334: * Calendar parameters as this object. jtulach@1334: * jtulach@1334: *

The Calendar parameters are the values represented jtulach@1334: * by the isLenient, getFirstDayOfWeek, jtulach@1334: * getMinimalDaysInFirstWeek and getTimeZone jtulach@1334: * methods. If there is any difference in those parameters jtulach@1334: * between the two Calendars, this method returns jtulach@1334: * false. jtulach@1334: * jtulach@1334: *

Use the {@link #compareTo(Calendar) compareTo} method to jtulach@1334: * compare only the time values. jtulach@1334: * jtulach@1334: * @param obj the object to compare with. jtulach@1334: * @return true if this object is equal to obj; jtulach@1334: * false otherwise. jtulach@1334: */ jtulach@1334: public boolean equals(Object obj) { jtulach@1334: if (this == obj) jtulach@1334: return true; jtulach@1334: try { jtulach@1334: Calendar that = (Calendar)obj; jtulach@1334: return compareTo(getMillisOf(that)) == 0 && jtulach@1334: lenient == that.lenient && jtulach@1334: firstDayOfWeek == that.firstDayOfWeek && jtulach@1334: minimalDaysInFirstWeek == that.minimalDaysInFirstWeek && jtulach@1334: zone.equals(that.zone); jtulach@1334: } catch (Exception e) { jtulach@1334: // Note: GregorianCalendar.computeTime throws jtulach@1334: // IllegalArgumentException if the ERA value is invalid jtulach@1334: // even it's in lenient mode. jtulach@1334: } jtulach@1334: return false; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns a hash code for this calendar. jtulach@1334: * jtulach@1334: * @return a hash code value for this object. jtulach@1334: * @since 1.2 jtulach@1334: */ jtulach@1334: public int hashCode() { jtulach@1334: // 'otheritems' represents the hash code for the previous versions. jtulach@1334: int otheritems = (lenient ? 1 : 0) jtulach@1334: | (firstDayOfWeek << 1) jtulach@1334: | (minimalDaysInFirstWeek << 4) jtulach@1334: | (zone.hashCode() << 7); jtulach@1334: long t = getMillisOf(this); jtulach@1334: return (int) t ^ (int)(t >> 32) ^ otheritems; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns whether this Calendar represents a time jtulach@1334: * before the time represented by the specified jtulach@1334: * Object. This method is equivalent to: jtulach@1334: *

jtulach@1334: * compareTo(when) < 0 jtulach@1334: *
jtulach@1334: * if and only if when is a Calendar jtulach@1334: * instance. Otherwise, the method returns false. jtulach@1334: * jtulach@1334: * @param when the Object to be compared jtulach@1334: * @return true if the time of this jtulach@1334: * Calendar is before the time represented by jtulach@1334: * when; false otherwise. jtulach@1334: * @see #compareTo(Calendar) jtulach@1334: */ jtulach@1334: public boolean before(Object when) { jtulach@1334: return when instanceof Calendar jtulach@1334: && compareTo((Calendar)when) < 0; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns whether this Calendar represents a time jtulach@1334: * after the time represented by the specified jtulach@1334: * Object. This method is equivalent to: jtulach@1334: *
jtulach@1334: * compareTo(when) > 0 jtulach@1334: *
jtulach@1334: * if and only if when is a Calendar jtulach@1334: * instance. Otherwise, the method returns false. jtulach@1334: * jtulach@1334: * @param when the Object to be compared jtulach@1334: * @return true if the time of this Calendar is jtulach@1334: * after the time represented by when; false jtulach@1334: * otherwise. jtulach@1334: * @see #compareTo(Calendar) jtulach@1334: */ jtulach@1334: public boolean after(Object when) { jtulach@1334: return when instanceof Calendar jtulach@1334: && compareTo((Calendar)when) > 0; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Compares the time values (millisecond offsets from the Epoch) represented by two jtulach@1334: * Calendar objects. jtulach@1334: * jtulach@1334: * @param anotherCalendar the Calendar to be compared. jtulach@1334: * @return the value 0 if the time represented by the argument jtulach@1334: * is equal to the time represented by this Calendar; a value jtulach@1334: * less than 0 if the time of this Calendar is jtulach@1334: * before the time represented by the argument; and a value greater than jtulach@1334: * 0 if the time of this Calendar is after the jtulach@1334: * time represented by the argument. jtulach@1334: * @exception NullPointerException if the specified Calendar is jtulach@1334: * null. jtulach@1334: * @exception IllegalArgumentException if the time value of the jtulach@1334: * specified Calendar object can't be obtained due to jtulach@1334: * any invalid calendar values. jtulach@1334: * @since 1.5 jtulach@1334: */ jtulach@1334: public int compareTo(Calendar anotherCalendar) { jtulach@1334: return compareTo(getMillisOf(anotherCalendar)); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Adds or subtracts the specified amount of time to the given calendar field, jtulach@1334: * based on the calendar's rules. For example, to subtract 5 days from jtulach@1334: * the current time of the calendar, you can achieve it by calling: jtulach@1334: *

add(Calendar.DAY_OF_MONTH, -5). jtulach@1334: * jtulach@1334: * @param field the calendar field. jtulach@1334: * @param amount the amount of date or time to be added to the field. jtulach@1334: * @see #roll(int,int) jtulach@1334: * @see #set(int,int) jtulach@1334: */ jtulach@1334: abstract public void add(int field, int amount); jtulach@1334: jtulach@1334: /** jtulach@1334: * Adds or subtracts (up/down) a single unit of time on the given time jtulach@1334: * field without changing larger fields. For example, to roll the current jtulach@1334: * date up by one day, you can achieve it by calling: jtulach@1334: *

roll(Calendar.DATE, true). jtulach@1334: * When rolling on the year or Calendar.YEAR field, it will roll the year jtulach@1334: * value in the range between 1 and the value returned by calling jtulach@1334: * getMaximum(Calendar.YEAR). jtulach@1334: * When rolling on the month or Calendar.MONTH field, other fields like jtulach@1334: * date might conflict and, need to be changed. For instance, jtulach@1334: * rolling the month on the date 01/31/96 will result in 02/29/96. jtulach@1334: * When rolling on the hour-in-day or Calendar.HOUR_OF_DAY field, it will jtulach@1334: * roll the hour value in the range between 0 and 23, which is zero-based. jtulach@1334: * jtulach@1334: * @param field the time field. jtulach@1334: * @param up indicates if the value of the specified time field is to be jtulach@1334: * rolled up or rolled down. Use true if rolling up, false otherwise. jtulach@1334: * @see Calendar#add(int,int) jtulach@1334: * @see Calendar#set(int,int) jtulach@1334: */ jtulach@1334: abstract public void roll(int field, boolean up); jtulach@1334: jtulach@1334: /** jtulach@1334: * Adds the specified (signed) amount to the specified calendar field jtulach@1334: * without changing larger fields. A negative amount means to roll jtulach@1334: * down. jtulach@1334: * jtulach@1334: *

NOTE: This default implementation on Calendar just repeatedly calls the jtulach@1334: * version of {@link #roll(int,boolean) roll()} that rolls by one unit. This may not jtulach@1334: * always do the right thing. For example, if the DAY_OF_MONTH field is 31, jtulach@1334: * rolling through February will leave it set to 28. The GregorianCalendar jtulach@1334: * version of this function takes care of this problem. Other subclasses jtulach@1334: * should also provide overrides of this function that do the right thing. jtulach@1334: * jtulach@1334: * @param field the calendar field. jtulach@1334: * @param amount the signed amount to add to the calendar field. jtulach@1334: * @since 1.2 jtulach@1334: * @see #roll(int,boolean) jtulach@1334: * @see #add(int,int) jtulach@1334: * @see #set(int,int) jtulach@1334: */ jtulach@1334: public void roll(int field, int amount) jtulach@1334: { jtulach@1334: while (amount > 0) { jtulach@1334: roll(field, true); jtulach@1334: amount--; jtulach@1334: } jtulach@1334: while (amount < 0) { jtulach@1334: roll(field, false); jtulach@1334: amount++; jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets the time zone with the given time zone value. jtulach@1334: * jtulach@1334: * @param value the given time zone. jtulach@1334: */ jtulach@1334: public void setTimeZone(TimeZone value) jtulach@1334: { jtulach@1334: zone = value; jtulach@1334: sharedZone = false; jtulach@1334: /* Recompute the fields from the time using the new zone. This also jtulach@1334: * works if isTimeSet is false (after a call to set()). In that case jtulach@1334: * the time will be computed from the fields using the new zone, then jtulach@1334: * the fields will get recomputed from that. Consider the sequence of jtulach@1334: * calls: cal.setTimeZone(EST); cal.set(HOUR, 1); cal.setTimeZone(PST). jtulach@1334: * Is cal set to 1 o'clock EST or 1 o'clock PST? Answer: PST. More jtulach@1334: * generally, a call to setTimeZone() affects calls to set() BEFORE AND jtulach@1334: * AFTER it up to the next call to complete(). jtulach@1334: */ jtulach@1334: areAllFieldsSet = areFieldsSet = false; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Gets the time zone. jtulach@1334: * jtulach@1334: * @return the time zone object associated with this calendar. jtulach@1334: */ jtulach@1334: public TimeZone getTimeZone() jtulach@1334: { jtulach@1334: // If the TimeZone object is shared by other Calendar instances, then jtulach@1334: // create a clone. jtulach@1334: if (sharedZone) { jtulach@1334: zone = (TimeZone) zone.clone(); jtulach@1334: sharedZone = false; jtulach@1334: } jtulach@1334: return zone; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the time zone (without cloning). jtulach@1334: */ jtulach@1334: TimeZone getZone() { jtulach@1334: return zone; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets the sharedZone flag to shared. jtulach@1334: */ jtulach@1334: void setZoneShared(boolean shared) { jtulach@1334: sharedZone = shared; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Specifies whether or not date/time interpretation is to be lenient. With jtulach@1334: * lenient interpretation, a date such as "February 942, 1996" will be jtulach@1334: * treated as being equivalent to the 941st day after February 1, 1996. jtulach@1334: * With strict (non-lenient) interpretation, such dates will cause an exception to be jtulach@1334: * thrown. The default is lenient. jtulach@1334: * jtulach@1334: * @param lenient true if the lenient mode is to be turned jtulach@1334: * on; false if it is to be turned off. jtulach@1334: * @see #isLenient() jtulach@1334: * @see java.text.DateFormat#setLenient jtulach@1334: */ jtulach@1334: public void setLenient(boolean lenient) jtulach@1334: { jtulach@1334: this.lenient = lenient; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Tells whether date/time interpretation is to be lenient. jtulach@1334: * jtulach@1334: * @return true if the interpretation mode of this calendar is lenient; jtulach@1334: * false otherwise. jtulach@1334: * @see #setLenient(boolean) jtulach@1334: */ jtulach@1334: public boolean isLenient() jtulach@1334: { jtulach@1334: return lenient; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets what the first day of the week is; e.g., SUNDAY in the U.S., jtulach@1334: * MONDAY in France. jtulach@1334: * jtulach@1334: * @param value the given first day of the week. jtulach@1334: * @see #getFirstDayOfWeek() jtulach@1334: * @see #getMinimalDaysInFirstWeek() jtulach@1334: */ jtulach@1334: public void setFirstDayOfWeek(int value) jtulach@1334: { jtulach@1334: if (firstDayOfWeek == value) { jtulach@1334: return; jtulach@1334: } jtulach@1334: firstDayOfWeek = value; jtulach@1334: invalidateWeekFields(); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Gets what the first day of the week is; e.g., SUNDAY in the U.S., jtulach@1334: * MONDAY in France. jtulach@1334: * jtulach@1334: * @return the first day of the week. jtulach@1334: * @see #setFirstDayOfWeek(int) jtulach@1334: * @see #getMinimalDaysInFirstWeek() jtulach@1334: */ jtulach@1334: public int getFirstDayOfWeek() jtulach@1334: { jtulach@1334: return firstDayOfWeek; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets what the minimal days required in the first week of the year are; jtulach@1334: * For example, if the first week is defined as one that contains the first jtulach@1334: * day of the first month of a year, call this method with value 1. If it jtulach@1334: * must be a full week, use value 7. jtulach@1334: * jtulach@1334: * @param value the given minimal days required in the first week jtulach@1334: * of the year. jtulach@1334: * @see #getMinimalDaysInFirstWeek() jtulach@1334: */ jtulach@1334: public void setMinimalDaysInFirstWeek(int value) jtulach@1334: { jtulach@1334: if (minimalDaysInFirstWeek == value) { jtulach@1334: return; jtulach@1334: } jtulach@1334: minimalDaysInFirstWeek = value; jtulach@1334: invalidateWeekFields(); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Gets what the minimal days required in the first week of the year are; jtulach@1334: * e.g., if the first week is defined as one that contains the first day jtulach@1334: * of the first month of a year, this method returns 1. If jtulach@1334: * the minimal days required must be a full week, this method jtulach@1334: * returns 7. jtulach@1334: * jtulach@1334: * @return the minimal days required in the first week of the year. jtulach@1334: * @see #setMinimalDaysInFirstWeek(int) jtulach@1334: */ jtulach@1334: public int getMinimalDaysInFirstWeek() jtulach@1334: { jtulach@1334: return minimalDaysInFirstWeek; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns whether this {@code Calendar} supports week dates. jtulach@1334: * jtulach@1334: *

The default implementation of this method returns {@code false}. jtulach@1334: * jtulach@1334: * @return {@code true} if this {@code Calendar} supports week dates; jtulach@1334: * {@code false} otherwise. jtulach@1334: * @see #getWeekYear() jtulach@1334: * @see #setWeekDate(int,int,int) jtulach@1334: * @see #getWeeksInWeekYear() jtulach@1334: * @since 1.7 jtulach@1334: */ jtulach@1334: public boolean isWeekDateSupported() { jtulach@1334: return false; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the week year represented by this {@code Calendar}. The jtulach@1334: * week year is in sync with the week cycle. The {@linkplain jtulach@1334: * #getFirstDayOfWeek() first day of the first week} is the first jtulach@1334: * day of the week year. jtulach@1334: * jtulach@1334: *

The default implementation of this method throws an jtulach@1334: * {@link UnsupportedOperationException}. jtulach@1334: * jtulach@1334: * @return the week year of this {@code Calendar} jtulach@1334: * @exception UnsupportedOperationException jtulach@1334: * if any week year numbering isn't supported jtulach@1334: * in this {@code Calendar}. jtulach@1334: * @see #isWeekDateSupported() jtulach@1334: * @see #getFirstDayOfWeek() jtulach@1334: * @see #getMinimalDaysInFirstWeek() jtulach@1334: * @since 1.7 jtulach@1334: */ jtulach@1334: public int getWeekYear() { jtulach@1334: throw new UnsupportedOperationException(); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets the date of this {@code Calendar} with the the given date jtulach@1334: * specifiers - week year, week of year, and day of week. jtulach@1334: * jtulach@1334: *

Unlike the {@code set} method, all of the calendar fields jtulach@1334: * and {@code time} values are calculated upon return. jtulach@1334: * jtulach@1334: *

If {@code weekOfYear} is out of the valid week-of-year range jtulach@1334: * in {@code weekYear}, the {@code weekYear} and {@code jtulach@1334: * weekOfYear} values are adjusted in lenient mode, or an {@code jtulach@1334: * IllegalArgumentException} is thrown in non-lenient mode. jtulach@1334: * jtulach@1334: *

The default implementation of this method throws an jtulach@1334: * {@code UnsupportedOperationException}. jtulach@1334: * jtulach@1334: * @param weekYear the week year jtulach@1334: * @param weekOfYear the week number based on {@code weekYear} jtulach@1334: * @param dayOfWeek the day of week value: one of the constants jtulach@1334: * for the {@link #DAY_OF_WEEK} field: {@link jtulach@1334: * #SUNDAY}, ..., {@link #SATURDAY}. jtulach@1334: * @exception IllegalArgumentException jtulach@1334: * if any of the given date specifiers is invalid jtulach@1334: * or any of the calendar fields are inconsistent jtulach@1334: * with the given date specifiers in non-lenient mode jtulach@1334: * @exception UnsupportedOperationException jtulach@1334: * if any week year numbering isn't supported in this jtulach@1334: * {@code Calendar}. jtulach@1334: * @see #isWeekDateSupported() jtulach@1334: * @see #getFirstDayOfWeek() jtulach@1334: * @see #getMinimalDaysInFirstWeek() jtulach@1334: * @since 1.7 jtulach@1334: */ jtulach@1334: public void setWeekDate(int weekYear, int weekOfYear, int dayOfWeek) { jtulach@1334: throw new UnsupportedOperationException(); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the number of weeks in the week year represented by this jtulach@1334: * {@code Calendar}. jtulach@1334: * jtulach@1334: *

The default implementation of this method throws an jtulach@1334: * {@code UnsupportedOperationException}. jtulach@1334: * jtulach@1334: * @return the number of weeks in the week year. jtulach@1334: * @exception UnsupportedOperationException jtulach@1334: * if any week year numbering isn't supported in this jtulach@1334: * {@code Calendar}. jtulach@1334: * @see #WEEK_OF_YEAR jtulach@1334: * @see #isWeekDateSupported() jtulach@1334: * @see #getWeekYear() jtulach@1334: * @see #getActualMaximum(int) jtulach@1334: * @since 1.7 jtulach@1334: */ jtulach@1334: public int getWeeksInWeekYear() { jtulach@1334: throw new UnsupportedOperationException(); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the minimum value for the given calendar field of this jtulach@1334: * Calendar instance. The minimum value is defined as jtulach@1334: * the smallest value returned by the {@link #get(int) get} method jtulach@1334: * for any possible time value. The minimum value depends on jtulach@1334: * calendar system specific parameters of the instance. jtulach@1334: * jtulach@1334: * @param field the calendar field. jtulach@1334: * @return the minimum value for the given calendar field. jtulach@1334: * @see #getMaximum(int) jtulach@1334: * @see #getGreatestMinimum(int) jtulach@1334: * @see #getLeastMaximum(int) jtulach@1334: * @see #getActualMinimum(int) jtulach@1334: * @see #getActualMaximum(int) jtulach@1334: */ jtulach@1334: abstract public int getMinimum(int field); jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the maximum value for the given calendar field of this jtulach@1334: * Calendar instance. The maximum value is defined as jtulach@1334: * the largest value returned by the {@link #get(int) get} method jtulach@1334: * for any possible time value. The maximum value depends on jtulach@1334: * calendar system specific parameters of the instance. jtulach@1334: * jtulach@1334: * @param field the calendar field. jtulach@1334: * @return the maximum value for the given calendar field. jtulach@1334: * @see #getMinimum(int) jtulach@1334: * @see #getGreatestMinimum(int) jtulach@1334: * @see #getLeastMaximum(int) jtulach@1334: * @see #getActualMinimum(int) jtulach@1334: * @see #getActualMaximum(int) jtulach@1334: */ jtulach@1334: abstract public int getMaximum(int field); jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the highest minimum value for the given calendar field jtulach@1334: * of this Calendar instance. The highest minimum jtulach@1334: * value is defined as the largest value returned by {@link jtulach@1334: * #getActualMinimum(int)} for any possible time value. The jtulach@1334: * greatest minimum value depends on calendar system specific jtulach@1334: * parameters of the instance. jtulach@1334: * jtulach@1334: * @param field the calendar field. jtulach@1334: * @return the highest minimum value for the given calendar field. jtulach@1334: * @see #getMinimum(int) jtulach@1334: * @see #getMaximum(int) jtulach@1334: * @see #getLeastMaximum(int) jtulach@1334: * @see #getActualMinimum(int) jtulach@1334: * @see #getActualMaximum(int) jtulach@1334: */ jtulach@1334: abstract public int getGreatestMinimum(int field); jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the lowest maximum value for the given calendar field jtulach@1334: * of this Calendar instance. The lowest maximum jtulach@1334: * value is defined as the smallest value returned by {@link jtulach@1334: * #getActualMaximum(int)} for any possible time value. The least jtulach@1334: * maximum value depends on calendar system specific parameters of jtulach@1334: * the instance. For example, a Calendar for the jtulach@1334: * Gregorian calendar system returns 28 for the jtulach@1334: * DAY_OF_MONTH field, because the 28th is the last jtulach@1334: * day of the shortest month of this calendar, February in a jtulach@1334: * common year. jtulach@1334: * jtulach@1334: * @param field the calendar field. jtulach@1334: * @return the lowest maximum value for the given calendar field. jtulach@1334: * @see #getMinimum(int) jtulach@1334: * @see #getMaximum(int) jtulach@1334: * @see #getGreatestMinimum(int) jtulach@1334: * @see #getActualMinimum(int) jtulach@1334: * @see #getActualMaximum(int) jtulach@1334: */ jtulach@1334: abstract public int getLeastMaximum(int field); jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the minimum value that the specified calendar field jtulach@1334: * could have, given the time value of this Calendar. jtulach@1334: * jtulach@1334: *

The default implementation of this method uses an iterative jtulach@1334: * algorithm to determine the actual minimum value for the jtulach@1334: * calendar field. Subclasses should, if possible, override this jtulach@1334: * with a more efficient implementation - in many cases, they can jtulach@1334: * simply return getMinimum(). jtulach@1334: * jtulach@1334: * @param field the calendar field jtulach@1334: * @return the minimum of the given calendar field for the time jtulach@1334: * value of this Calendar jtulach@1334: * @see #getMinimum(int) jtulach@1334: * @see #getMaximum(int) jtulach@1334: * @see #getGreatestMinimum(int) jtulach@1334: * @see #getLeastMaximum(int) jtulach@1334: * @see #getActualMaximum(int) jtulach@1334: * @since 1.2 jtulach@1334: */ jtulach@1334: public int getActualMinimum(int field) { jtulach@1334: int fieldValue = getGreatestMinimum(field); jtulach@1334: int endValue = getMinimum(field); jtulach@1334: jtulach@1334: // if we know that the minimum value is always the same, just return it jtulach@1334: if (fieldValue == endValue) { jtulach@1334: return fieldValue; jtulach@1334: } jtulach@1334: jtulach@1334: // clone the calendar so we don't mess with the real one, and set it to jtulach@1334: // accept anything for the field values jtulach@1334: Calendar work = (Calendar)this.clone(); jtulach@1334: work.setLenient(true); jtulach@1334: jtulach@1334: // now try each value from getLeastMaximum() to getMaximum() one by one until jtulach@1334: // we get a value that normalizes to another value. The last value that jtulach@1334: // normalizes to itself is the actual minimum for the current date jtulach@1334: int result = fieldValue; jtulach@1334: jtulach@1334: do { jtulach@1334: work.set(field, fieldValue); jtulach@1334: if (work.get(field) != fieldValue) { jtulach@1334: break; jtulach@1334: } else { jtulach@1334: result = fieldValue; jtulach@1334: fieldValue--; jtulach@1334: } jtulach@1334: } while (fieldValue >= endValue); jtulach@1334: jtulach@1334: return result; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the maximum value that the specified calendar field jtulach@1334: * could have, given the time value of this jtulach@1334: * Calendar. For example, the actual maximum value of jtulach@1334: * the MONTH field is 12 in some years, and 13 in jtulach@1334: * other years in the Hebrew calendar system. jtulach@1334: * jtulach@1334: *

The default implementation of this method uses an iterative jtulach@1334: * algorithm to determine the actual maximum value for the jtulach@1334: * calendar field. Subclasses should, if possible, override this jtulach@1334: * with a more efficient implementation. jtulach@1334: * jtulach@1334: * @param field the calendar field jtulach@1334: * @return the maximum of the given calendar field for the time jtulach@1334: * value of this Calendar jtulach@1334: * @see #getMinimum(int) jtulach@1334: * @see #getMaximum(int) jtulach@1334: * @see #getGreatestMinimum(int) jtulach@1334: * @see #getLeastMaximum(int) jtulach@1334: * @see #getActualMinimum(int) jtulach@1334: * @since 1.2 jtulach@1334: */ jtulach@1334: public int getActualMaximum(int field) { jtulach@1334: int fieldValue = getLeastMaximum(field); jtulach@1334: int endValue = getMaximum(field); jtulach@1334: jtulach@1334: // if we know that the maximum value is always the same, just return it. jtulach@1334: if (fieldValue == endValue) { jtulach@1334: return fieldValue; jtulach@1334: } jtulach@1334: jtulach@1334: // clone the calendar so we don't mess with the real one, and set it to jtulach@1334: // accept anything for the field values. jtulach@1334: Calendar work = (Calendar)this.clone(); jtulach@1334: work.setLenient(true); jtulach@1334: jtulach@1334: // if we're counting weeks, set the day of the week to Sunday. We know the jtulach@1334: // last week of a month or year will contain the first day of the week. jtulach@1334: if (field == WEEK_OF_YEAR || field == WEEK_OF_MONTH) jtulach@1334: work.set(DAY_OF_WEEK, firstDayOfWeek); jtulach@1334: jtulach@1334: // now try each value from getLeastMaximum() to getMaximum() one by one until jtulach@1334: // we get a value that normalizes to another value. The last value that jtulach@1334: // normalizes to itself is the actual maximum for the current date jtulach@1334: int result = fieldValue; jtulach@1334: jtulach@1334: do { jtulach@1334: work.set(field, fieldValue); jtulach@1334: if (work.get(field) != fieldValue) { jtulach@1334: break; jtulach@1334: } else { jtulach@1334: result = fieldValue; jtulach@1334: fieldValue++; jtulach@1334: } jtulach@1334: } while (fieldValue <= endValue); jtulach@1334: jtulach@1334: return result; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Creates and returns a copy of this object. jtulach@1334: * jtulach@1334: * @return a copy of this object. jtulach@1334: */ jtulach@1334: public Object clone() jtulach@1334: { jtulach@1334: try { jtulach@1334: Calendar other = (Calendar) super.clone(); jtulach@1334: jtulach@1334: other.fields = new int[FIELD_COUNT]; jtulach@1334: other.isSet = new boolean[FIELD_COUNT]; jtulach@1334: other.stamp = new int[FIELD_COUNT]; jtulach@1334: for (int i = 0; i < FIELD_COUNT; i++) { jtulach@1334: other.fields[i] = fields[i]; jtulach@1334: other.stamp[i] = stamp[i]; jtulach@1334: other.isSet[i] = isSet[i]; jtulach@1334: } jtulach@1334: other.zone = (TimeZone) zone.clone(); jtulach@1334: return other; jtulach@1334: } jtulach@1334: catch (CloneNotSupportedException e) { jtulach@1334: // this shouldn't happen, since we are Cloneable jtulach@1334: throw new InternalError(); jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: private static final String[] FIELD_NAME = { jtulach@1334: "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH", jtulach@1334: "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR", jtulach@1334: "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET", jtulach@1334: "DST_OFFSET" jtulach@1334: }; jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the name of the specified calendar field. jtulach@1334: * jtulach@1334: * @param field the calendar field jtulach@1334: * @return the calendar field name jtulach@1334: * @exception IndexOutOfBoundsException if field is negative, jtulach@1334: * equal to or greater then FIELD_COUNT. jtulach@1334: */ jtulach@1334: static final String getFieldName(int field) { jtulach@1334: return FIELD_NAME[field]; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Return a string representation of this calendar. This method jtulach@1334: * is intended to be used only for debugging purposes, and the jtulach@1334: * format of the returned string may vary between implementations. jtulach@1334: * The returned string may be empty but may not be null. jtulach@1334: * jtulach@1334: * @return a string representation of this calendar. jtulach@1334: */ jtulach@1334: public String toString() { jtulach@1334: // NOTE: BuddhistCalendar.toString() interprets the string jtulach@1334: // produced by this method so that the Gregorian year number jtulach@1334: // is substituted by its B.E. year value. It relies on jtulach@1334: // "...,YEAR=,..." or "...,YEAR=?,...". jtulach@1334: StringBuilder buffer = new StringBuilder(800); jtulach@1334: buffer.append(getClass().getName()).append('['); jtulach@1334: appendValue(buffer, "time", isTimeSet, time); jtulach@1334: buffer.append(",areFieldsSet=").append(areFieldsSet); jtulach@1334: buffer.append(",areAllFieldsSet=").append(areAllFieldsSet); jtulach@1334: buffer.append(",lenient=").append(lenient); jtulach@1334: buffer.append(",zone=").append(zone); jtulach@1334: appendValue(buffer, ",firstDayOfWeek", true, (long) firstDayOfWeek); jtulach@1334: appendValue(buffer, ",minimalDaysInFirstWeek", true, (long) minimalDaysInFirstWeek); jtulach@1334: for (int i = 0; i < FIELD_COUNT; ++i) { jtulach@1334: buffer.append(','); jtulach@1334: appendValue(buffer, FIELD_NAME[i], isSet(i), (long) fields[i]); jtulach@1334: } jtulach@1334: buffer.append(']'); jtulach@1334: return buffer.toString(); jtulach@1334: } jtulach@1334: jtulach@1334: // =======================privates=============================== jtulach@1334: jtulach@1334: private static final void appendValue(StringBuilder sb, String item, boolean valid, long value) { jtulach@1334: sb.append(item).append('='); jtulach@1334: if (valid) { jtulach@1334: sb.append(value); jtulach@1334: } else { jtulach@1334: sb.append('?'); jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Both firstDayOfWeek and minimalDaysInFirstWeek are locale-dependent. jtulach@1334: * They are used to figure out the week count for a specific date for jtulach@1334: * a given locale. These must be set when a Calendar is constructed. jtulach@1334: * @param desiredLocale the given locale. jtulach@1334: */ jtulach@1334: private void setWeekCountData(Locale desiredLocale) jtulach@1334: { jtulach@1334: /* try to get the Locale data from the cache */ jtulach@1334: int[] data = cachedLocaleData.get(desiredLocale); jtulach@1334: if (data == null) { /* cache miss */ jaroslav@1340: // ResourceBundle bundle = LocaleData.getCalendarData(desiredLocale); jtulach@1334: data = new int[2]; jaroslav@1340: // data[0] = Integer.parseInt(bundle.getString("firstDayOfWeek")); jaroslav@1340: // data[1] = Integer.parseInt(bundle.getString("minimalDaysInFirstWeek")); jtulach@1334: cachedLocaleData.putIfAbsent(desiredLocale, data); jtulach@1334: } jtulach@1334: firstDayOfWeek = data[0]; jtulach@1334: minimalDaysInFirstWeek = data[1]; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Recomputes the time and updates the status fields isTimeSet jtulach@1334: * and areFieldsSet. Callers should check isTimeSet and only jtulach@1334: * call this method if isTimeSet is false. jtulach@1334: */ jtulach@1334: private void updateTime() { jtulach@1334: computeTime(); jtulach@1334: // The areFieldsSet and areAllFieldsSet values are no longer jtulach@1334: // controlled here (as of 1.5). jtulach@1334: isTimeSet = true; jtulach@1334: } jtulach@1334: jtulach@1334: private int compareTo(long t) { jtulach@1334: long thisTime = getMillisOf(this); jtulach@1334: return (thisTime > t) ? 1 : (thisTime == t) ? 0 : -1; jtulach@1334: } jtulach@1334: jtulach@1334: private static final long getMillisOf(Calendar calendar) { jtulach@1334: if (calendar.isTimeSet) { jtulach@1334: return calendar.time; jtulach@1334: } jtulach@1334: Calendar cal = (Calendar) calendar.clone(); jtulach@1334: cal.setLenient(true); jtulach@1334: return cal.getTimeInMillis(); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Adjusts the stamp[] values before nextStamp overflow. nextStamp jtulach@1334: * is set to the next stamp value upon the return. jtulach@1334: */ jtulach@1334: private final void adjustStamp() { jtulach@1334: int max = MINIMUM_USER_STAMP; jtulach@1334: int newStamp = MINIMUM_USER_STAMP; jtulach@1334: jtulach@1334: for (;;) { jtulach@1334: int min = Integer.MAX_VALUE; jtulach@1334: for (int i = 0; i < stamp.length; i++) { jtulach@1334: int v = stamp[i]; jtulach@1334: if (v >= newStamp && min > v) { jtulach@1334: min = v; jtulach@1334: } jtulach@1334: if (max < v) { jtulach@1334: max = v; jtulach@1334: } jtulach@1334: } jtulach@1334: if (max != min && min == Integer.MAX_VALUE) { jtulach@1334: break; jtulach@1334: } jtulach@1334: for (int i = 0; i < stamp.length; i++) { jtulach@1334: if (stamp[i] == min) { jtulach@1334: stamp[i] = newStamp; jtulach@1334: } jtulach@1334: } jtulach@1334: newStamp++; jtulach@1334: if (min == max) { jtulach@1334: break; jtulach@1334: } jtulach@1334: } jtulach@1334: nextStamp = newStamp; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Sets the WEEK_OF_MONTH and WEEK_OF_YEAR fields to new values with the jtulach@1334: * new parameter value if they have been calculated internally. jtulach@1334: */ jtulach@1334: private void invalidateWeekFields() jtulach@1334: { jtulach@1334: if (stamp[WEEK_OF_MONTH] != COMPUTED && jtulach@1334: stamp[WEEK_OF_YEAR] != COMPUTED) { jtulach@1334: return; jtulach@1334: } jtulach@1334: jtulach@1334: // We have to check the new values of these fields after changing jtulach@1334: // firstDayOfWeek and/or minimalDaysInFirstWeek. If the field values jtulach@1334: // have been changed, then set the new values. (4822110) jtulach@1334: Calendar cal = (Calendar) clone(); jtulach@1334: cal.setLenient(true); jtulach@1334: cal.clear(WEEK_OF_MONTH); jtulach@1334: cal.clear(WEEK_OF_YEAR); jtulach@1334: jtulach@1334: if (stamp[WEEK_OF_MONTH] == COMPUTED) { jtulach@1334: int weekOfMonth = cal.get(WEEK_OF_MONTH); jtulach@1334: if (fields[WEEK_OF_MONTH] != weekOfMonth) { jtulach@1334: fields[WEEK_OF_MONTH] = weekOfMonth; jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: if (stamp[WEEK_OF_YEAR] == COMPUTED) { jtulach@1334: int weekOfYear = cal.get(WEEK_OF_YEAR); jtulach@1334: if (fields[WEEK_OF_YEAR] != weekOfYear) { jtulach@1334: fields[WEEK_OF_YEAR] = weekOfYear; jtulach@1334: } jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Save the state of this object to a stream (i.e., serialize it). jtulach@1334: * jtulach@1334: * Ideally, Calendar would only write out its state data and jtulach@1334: * the current time, and not write any field data out, such as jtulach@1334: * fields[], isTimeSet, areFieldsSet, jtulach@1334: * and isSet[]. nextStamp also should not be part jtulach@1334: * of the persistent state. Unfortunately, this didn't happen before JDK 1.1 jtulach@1334: * shipped. To be compatible with JDK 1.1, we will always have to write out jtulach@1334: * the field values and state flags. However, nextStamp can be jtulach@1334: * removed from the serialization stream; this will probably happen in the jtulach@1334: * near future. jtulach@1334: */ jtulach@1334: private void writeObject(ObjectOutputStream stream) jtulach@1334: throws IOException jtulach@1334: { jtulach@1334: // Try to compute the time correctly, for the future (stream jtulach@1334: // version 2) in which we don't write out fields[] or isSet[]. jtulach@1334: if (!isTimeSet) { jtulach@1334: try { jtulach@1334: updateTime(); jtulach@1334: } jtulach@1334: catch (IllegalArgumentException e) {} jtulach@1334: } jtulach@1334: jtulach@1334: // If this Calendar has a ZoneInfo, save it and set a jtulach@1334: // SimpleTimeZone equivalent (as a single DST schedule) for jtulach@1334: // backward compatibility. jtulach@1334: TimeZone savedZone = null; jaroslav@1340: // if (zone instanceof ZoneInfo) { jaroslav@1340: // SimpleTimeZone stz = ((ZoneInfo)zone).getLastRuleInstance(); jaroslav@1340: // if (stz == null) { jaroslav@1340: // stz = new SimpleTimeZone(zone.getRawOffset(), zone.getID()); jaroslav@1340: // } jaroslav@1340: // savedZone = zone; jaroslav@1340: // zone = stz; jaroslav@1340: // } jtulach@1334: jtulach@1334: // Write out the 1.1 FCS object. jtulach@1334: stream.defaultWriteObject(); jtulach@1334: jtulach@1334: // Write out the ZoneInfo object jtulach@1334: // 4802409: we write out even if it is null, a temporary workaround jtulach@1334: // the real fix for bug 4844924 in corba-iiop jtulach@1334: stream.writeObject(savedZone); jtulach@1334: if (savedZone != null) { jtulach@1334: zone = savedZone; jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Reconstitutes this object from a stream (i.e., deserialize it). jtulach@1334: */ jtulach@1334: private void readObject(ObjectInputStream stream) jtulach@1334: throws IOException, ClassNotFoundException jtulach@1334: { jtulach@1334: final ObjectInputStream input = stream; jtulach@1334: input.defaultReadObject(); jtulach@1334: jtulach@1334: stamp = new int[FIELD_COUNT]; jtulach@1334: jtulach@1334: // Starting with version 2 (not implemented yet), we expect that jtulach@1334: // fields[], isSet[], isTimeSet, and areFieldsSet may not be jtulach@1334: // streamed out anymore. We expect 'time' to be correct. jtulach@1334: if (serialVersionOnStream >= 2) jtulach@1334: { jtulach@1334: isTimeSet = true; jtulach@1334: if (fields == null) fields = new int[FIELD_COUNT]; jtulach@1334: if (isSet == null) isSet = new boolean[FIELD_COUNT]; jtulach@1334: } jtulach@1334: else if (serialVersionOnStream >= 0) jtulach@1334: { jtulach@1334: for (int i=0; i() { jaroslav@1340: // public ZoneInfo run() throws Exception { jaroslav@1340: // return (ZoneInfo) input.readObject(); jaroslav@1340: // } jaroslav@1340: // }, jaroslav@1340: // CalendarAccessControlContext.INSTANCE); jaroslav@1340: // } catch (PrivilegedActionException pae) { jaroslav@1340: // Exception e = pae.getException(); jaroslav@1340: // if (!(e instanceof OptionalDataException)) { jaroslav@1340: // if (e instanceof RuntimeException) { jaroslav@1340: // throw (RuntimeException) e; jaroslav@1340: // } else if (e instanceof IOException) { jaroslav@1340: // throw (IOException) e; jaroslav@1340: // } else if (e instanceof ClassNotFoundException) { jaroslav@1340: // throw (ClassNotFoundException) e; jaroslav@1340: // } jaroslav@1340: // throw new RuntimeException(e); jaroslav@1340: // } jaroslav@1340: // } jtulach@1334: if (zi != null) { jtulach@1334: zone = zi; jtulach@1334: } jtulach@1334: jtulach@1334: // If the deserialized object has a SimpleTimeZone, try to jtulach@1334: // replace it with a ZoneInfo equivalent (as of 1.4) in order jtulach@1334: // to be compatible with the SimpleTimeZone-based jtulach@1334: // implementation as much as possible. jtulach@1334: if (zone instanceof SimpleTimeZone) { jtulach@1334: String id = zone.getID(); jtulach@1334: TimeZone tz = TimeZone.getTimeZone(id); jtulach@1334: if (tz != null && tz.hasSameRules(zone) && tz.getID().equals(id)) { jtulach@1334: zone = tz; jtulach@1334: } jtulach@1334: } jtulach@1334: } jtulach@1334: }