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: * jtulach@1334: *jtulach@1334: * Calendar rightNow = Calendar.getInstance(); 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: *
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: *
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: *
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
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: * jtulach@1334: * For the time of day fields: 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: * jtulach@1334: *jtulach@1334: * HOUR_OF_DAY jtulach@1334: * AM_PM + HOUR 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: * 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: *
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.
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.
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
jtulach@1334: * jtulach@1334: *f
jtulach@1334: * after the call minus the value of fieldf
before the jtulach@1334: * call isdelta
, modulo any overflow that has occurred in jtulach@1334: * fieldf
. 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.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: *
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.
In addition, unlike set()
, add()
forces
jtulach@1334: * an immediate recomputation of the calendar's milliseconds and all
jtulach@1334: * fields.
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
.
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.
jtulach@1334: *DAY_OF_MONTH
is a larger field than jtulach@1334: *HOUR
.
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.
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
jtulach@1334: * Note: Calling 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 For example, if this The default implementation supports the calendar fields for
jtulach@1334: * which a {@link DateFormatSymbols} has names in the given
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 The default implementation supports display names contained in
jtulach@1334: * a {@link DateFormatSymbols}. For example, if 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., The 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 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: * NOTE: This default implementation on 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: * 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 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
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 ConcurrentMapstamp[]
, 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: *
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: * 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: * 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: * 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: * 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: * 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: * 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 Maptrue
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: * 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: * 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 Calendar
s, this method returns
jtulach@1334: * false
.
jtulach@1334: *
jtulach@1334: * 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: * if and only if
jtulach@1334: * compareTo(when) < 0
jtulach@1334: *
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: * if and only if
jtulach@1334: * compareTo(when) > 0
jtulach@1334: *
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: * 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: * 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: * 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: * 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: * 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=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