/* * Copyright (C) 1996-2012, International Business Machines * Corporation and others. All Rights Reserved. */ package com.ibm.icu.util; import java.io.Serializable; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; import com.ibm.icu.text.DateFormat; import com.ibm.icu.util.ULocale.Category; /** * {@icuenhanced java.util.Calendar}.{@icu _usage_} * *

Calendar is an abstract base class for converting between * a Date object and a set of integer fields such as * YEAR, MONTH, DAY, HOUR, * and so on. (A Date object represents a specific instant in * time with millisecond precision. See * {@link Date} * for information about the Date class.) * *

Subclasses of Calendar interpret a Date * according to the rules of a specific calendar system. ICU4J contains * several subclasses implementing different international calendar systems. * *

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

*
Calendar rightNow = Calendar.getInstance()
*
* *

When a ULocale is used by getInstance, its * 'calendar' tag and value are retrieved if present. If a recognized * value is supplied, a calendar is provided and configured as appropriate. * Currently recognized tags are "buddhist", "chinese", "coptic", "ethiopic", * "gregorian", "hebrew", "islamic", "islamic-civil", "japanese", and "roc". For * example:

*
Calendar cal = Calendar.getInstance(new ULocale("en_US@calendar=japanese"));
*
will return an instance of JapaneseCalendar (using en_US conventions for * minimum days in first week, start day of week, et cetera). * *

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

When a Calendar is lenient, it accepts a wider range * of field values than it produces. For example, a lenient * GregorianCalendar interprets MONTH == * JANUARY, DAY_OF_MONTH == 32 as February 1. A * non-lenient GregorianCalendar throws an exception when given * out-of-range field settings. When calendars recompute field values for * return by get(), they normalize them. For example, a * GregorianCalendar always produces DAY_OF_MONTH * values between 1 and the length of the month. * *

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

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

When computing a Date from time fields, two special * circumstances may arise: there may be insufficient information to compute the * Date (such as only year and month but no day in the month), or * there may be inconsistent information (such as "Tuesday, July 15, 1996" -- * July 15, 1996 is actually a Monday). * *

Insufficient information. The calendar will use default * information to specify the missing fields. This may vary by calendar; for * the Gregorian calendar, the default for a field is the same as that of the * start of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc. * *

Inconsistent information. If fields conflict, the calendar * will give preference to fields set more recently. For example, when * determining the day, the calendar will look for one of the following * combinations of fields. The most recent combination, as determined by the * most recently set single field, will be used. * *

*
 * MONTH + DAY_OF_MONTH
 * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
 * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
 * DAY_OF_YEAR
 * DAY_OF_WEEK + WEEK_OF_YEAR
*
* * For the time of day: * *
*
 * HOUR_OF_DAY
 * AM_PM + HOUR
*
* *

Note: for some non-Gregorian calendars, different * fields may be necessary for complete disambiguation. For example, a full * specification of the historial Arabic astronomical calendar requires year, * month, day-of-month and day-of-week in some cases. * *

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

    *
  1. 24:00:00 "belongs" to the following day. That is, * 23:59 on Dec 31, 1969 < 24:00 on Jan 1, 1970 < 24:01:00 on Jan 1, 1970 * *
  2. Although historically not precise, midnight also belongs to "am", * and noon belongs to "pm", so on the same day, * 12:00 am (midnight) < 12:01 am, and 12:00 pm (noon) < 12:01 pm *
* *

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

Field manipulation methods

* *

Calendar fields can be changed using three methods: * set(), add(), and roll().

* *

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

* *

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

* *

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

* *
*

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

* *

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

*
* *

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

* *

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

* *

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

* *
*

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

*
* *

Example: Consider a GregorianCalendar * originally set to August 31, 1999. Calling roll(Calendar.MONTH, * 8) sets the calendar to April 30, 1999. Add * rule 1 sets the MONTH field to April. Using a * GregorianCalendar, the DAY_OF_MONTH cannot * be 31 in the month April. Add rule 2 sets it to the closest possible * value, 30. Finally, the roll rule maintains the * YEAR field value of 1999.

* *

Example: Consider a GregorianCalendar * originally set to Sunday June 6, 1999. Calling * roll(Calendar.WEEK_OF_MONTH, -1) sets the calendar to * Tuesday June 1, 1999, whereas calling * add(Calendar.WEEK_OF_MONTH, -1) sets the calendar to * Sunday May 30, 1999. This is because the roll rule imposes an * additional constraint: The MONTH must not change when the * WEEK_OF_MONTH is rolled. Taken together with add rule 1, * the resultant date must be between Tuesday June 1 and Saturday June * 5. According to add rule 2, the DAY_OF_WEEK, an invariant * when changing the WEEK_OF_MONTH, is set to Tuesday, the * closest possible value to Sunday (where Sunday is the first day of the * week).

* *

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

* *

Note: You should always use {@link #roll roll} and {@link #add add} rather * than attempting to perform arithmetic operations directly on the fields * of a Calendar. It is quite possible for Calendar subclasses * to have fields with non-linear behavior, for example missing months * or days during non-leap years. The subclasses' add and roll * methods will take this into account, while simple arithmetic manipulations * may give invalid results. * *

Calendar Architecture in ICU4J

* *

Recently the implementation of Calendar has changed * significantly in order to better support subclassing. The original * Calendar class was designed to support subclassing, but * it had only one implemented subclass, GregorianCalendar. * With the implementation of several new calendar subclasses, including * the BuddhistCalendar, ChineseCalendar, * HebrewCalendar, IslamicCalendar, and * JapaneseCalendar, the subclassing API has been reworked * thoroughly. This section details the new subclassing API and other * ways in which com.ibm.icu.util.Calendar differs from * java.util.Calendar. *

* *

Changes

* *

Overview of changes between the classic Calendar * architecture and the new architecture. * *

* *

Subclass API

* *

The original Calendar API was based on the experience * of implementing a only a single subclass, * GregorianCalendar. As a result, all of the subclassing * kinks had not been worked out. The new subclassing API has been * refined based on several implemented subclasses. This includes methods * that must be overridden and methods for subclasses to call. Subclasses * no longer have direct access to fields and * stamp. Instead, they have new API to access * these. Subclasses are able to allocate the fields array * through a protected framework method; this allows subclasses to * specify additional fields.

* *

More functionality has been moved into the base class. The base * class now contains much of the computational machinery to support the * Gregorian calendar. This is based on two things: (1) Many calendars * are based on the Gregorian calendar (such as the Buddhist and Japanese * imperial calendars). (2) All calendars require basic * Gregorian support in order to handle timezone computations.

* *

Common computations have been moved into * Calendar. Subclasses no longer compute the week related * fields and the time related fields. These are commonly handled for all * calendars by the base class.

* *

Subclass computation of time => fields * *

The {@link #ERA}, {@link #YEAR}, * {@link #EXTENDED_YEAR}, {@link #MONTH}, * {@link #DAY_OF_MONTH}, and {@link #DAY_OF_YEAR} fields are * computed by the subclass, based on the Julian day. All other fields * are computed by Calendar. * *

* *

Subclass computation of fields => time * *

The interpretation of most field values is handled entirely by * Calendar. Calendar determines which fields * are set, which are not, which are set more recently, and so on. In * addition, Calendar handles the computation of the time * from the time fields and handles the week-related fields. The only * thing the subclass must do is determine the extended year, based on * the year fields, and then, given an extended year and a month, it must * return a Julian day number. * *

* *

Other methods * *

* *

Normalized behavior * *

The behavior of certain fields has been made consistent across all * calendar systems and implemented in Calendar. * *

* *

Supported range * *

The allowable range of Calendar has been * narrowed. GregorianCalendar used to attempt to support * the range of dates with millisecond values from * Long.MIN_VALUE to Long.MAX_VALUE. This * introduced awkward constructions (hacks) which slowed down * performance. It also introduced non-uniform behavior at the * boundaries. The new Calendar protocol specifies the * maximum range of supportable dates as those having Julian day numbers * of -0x7F000000 to +0x7F000000. This * corresponds to years from ~5,000,000 BCE to ~5,000,000 CE. Programmers * should use the protected constants in Calendar to * specify an extremely early or extremely late date.

* *

General notes * *

* * @see Date * @see GregorianCalendar * @see TimeZone * @see DateFormat * @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu, Laura Werner * @stable ICU 2.0 */ public class Calendar implements Serializable, Cloneable, Comparable { private static final long serialVersionUID = 1L; /** * @internal */ public final java.util.Calendar calendar; /** * @internal * @param delegate the Calendar to which to delegate */ public Calendar(java.util.Calendar delegate) { this.calendar = delegate; } // Data flow in Calendar // --------------------- // The current time is represented in two ways by Calendar: as UTC // milliseconds from the epoch start (1 January 1970 0:00 UTC), and as local // fields such as MONTH, HOUR, AM_PM, etc. It is possible to compute the // millis from the fields, and vice versa. The data needed to do this // conversion is encapsulated by a TimeZone object owned by the Calendar. // The data provided by the TimeZone object may also be overridden if the // user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class // keeps track of what information was most recently set by the caller, and // uses that to compute any other information as needed. // If the user sets the fields using set(), the data flow is as follows. // This is implemented by the Calendar subclass's computeTime() method. // During this process, certain fields may be ignored. The disambiguation // algorithm for resolving which fields to pay attention to is described // above. // local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.) // | // | Using Calendar-specific algorithm // V // local standard millis // | // | Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET // V // UTC millis (in time data member) // If the user sets the UTC millis using setTime(), the data flow is as // follows. This is implemented by the Calendar subclass's computeFields() // method. // UTC millis (in time data member) // | // | Using TimeZone getOffset() // V // local standard millis // | // | Using Calendar-specific algorithm // V // local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.) // In general, a round trip from fields, through local and UTC millis, and // back out to fields is made when necessary. This is implemented by the // complete() method. Resolving a partial set of fields into a UTC millis // value allows all remaining fields to be generated from that value. If // the Calendar is lenient, the fields are also renormalized to standard // ranges when they are regenerated. /** * Field number for get and set indicating the * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific * value; see subclass documentation. * @see GregorianCalendar#AD * @see GregorianCalendar#BC * @stable ICU 2.0 */ public final static int ERA = 0; /** * Field number for get and set indicating the * year. This is a calendar-specific value; see subclass documentation. * @stable ICU 2.0 */ public final static int YEAR = 1; /** * Field number for get and set indicating the * month. This is a calendar-specific value. The first month of the year is * JANUARY; the last depends on the number of months in a year. * @see #JANUARY * @see #FEBRUARY * @see #MARCH * @see #APRIL * @see #MAY * @see #JUNE * @see #JULY * @see #AUGUST * @see #SEPTEMBER * @see #OCTOBER * @see #NOVEMBER * @see #DECEMBER * @see #UNDECIMBER * @stable ICU 2.0 */ public final static int MONTH = 2; /** * Field number for get and set indicating the * week number within the current year. The first week of the year, as * defined by {@link #getFirstDayOfWeek()} and * {@link #getMinimalDaysInFirstWeek()}, has value 1. Subclasses define * the value of {@link #WEEK_OF_YEAR} for days before the first week of * the year. * @see #getFirstDayOfWeek * @see #getMinimalDaysInFirstWeek * @stable ICU 2.0 */ public final static int WEEK_OF_YEAR = 3; /** * Field number for get and set indicating the * week number within the current month. The first week of the month, as * defined by {@link #getFirstDayOfWeek()} and * {@link #getMinimalDaysInFirstWeek()}, has value 1. Subclasses define * the value of {@link #WEEK_OF_MONTH} for days before the first week of * the month. * @see #getFirstDayOfWeek * @see #getMinimalDaysInFirstWeek * @stable ICU 2.0 */ public final static int WEEK_OF_MONTH = 4; /** * Field number for get and set indicating the * day of the month. This is a synonym for {@link #DAY_OF_MONTH}. * The first day of the month has value 1. * @see #DAY_OF_MONTH * @stable ICU 2.0 */ public final static int DATE = 5; /** * Field number for get and set indicating the * day of the month. This is a synonym for {@link #DATE}. * The first day of the month has value 1. * @see #DATE * @stable ICU 2.0 */ public final static int DAY_OF_MONTH = 5; /** * Field number for get and set indicating the day * number within the current year. The first day of the year has value 1. * @stable ICU 2.0 */ public final static int DAY_OF_YEAR = 6; /** * Field number for get and set indicating the day * of the week. This field takes values {@link #SUNDAY}, * {@link #MONDAY}, {@link #TUESDAY}, {@link #WEDNESDAY}, * {@link #THURSDAY}, {@link #FRIDAY}, and {@link #SATURDAY}. * @see #SUNDAY * @see #MONDAY * @see #TUESDAY * @see #WEDNESDAY * @see #THURSDAY * @see #FRIDAY * @see #SATURDAY * @stable ICU 2.0 */ public final static int DAY_OF_WEEK = 7; /** * Field number for get and set indicating the * ordinal number of the day of the week within the current month. Together * with the {@link #DAY_OF_WEEK} field, this uniquely specifies a day * within a month. Unlike {@link #WEEK_OF_MONTH} and * {@link #WEEK_OF_YEAR}, this field's value does not depend on * {@link #getFirstDayOfWeek()} or * {@link #getMinimalDaysInFirstWeek()}. DAY_OF_MONTH 1 * through 7 always correspond to DAY_OF_WEEK_IN_MONTH * 1; 8 through 15 correspond to * DAY_OF_WEEK_IN_MONTH 2, and so on. * DAY_OF_WEEK_IN_MONTH 0 indicates the week before * DAY_OF_WEEK_IN_MONTH 1. Negative values count back from the * end of the month, so the last Sunday of a month is specified as * DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1. Because * negative values count backward they will usually be aligned differently * within the month than positive values. For example, if a month has 31 * days, DAY_OF_WEEK_IN_MONTH -1 will overlap * DAY_OF_WEEK_IN_MONTH 5 and the end of 4. * @see #DAY_OF_WEEK * @see #WEEK_OF_MONTH * @stable ICU 2.0 */ public final static int DAY_OF_WEEK_IN_MONTH = 8; /** * Field number for get and set indicating * whether the HOUR is before or after noon. * E.g., at 10:04:15.250 PM the AM_PM is PM. * @see #AM * @see #PM * @see #HOUR * @stable ICU 2.0 */ public final static int AM_PM = 9; /** * Field number for get and set indicating the * hour of the morning or afternoon. HOUR is used for the 12-hour * clock. * E.g., at 10:04:15.250 PM the HOUR is 10. * @see #AM_PM * @see #HOUR_OF_DAY * @stable ICU 2.0 */ public final static int HOUR = 10; /** * Field number for get and set indicating the * hour of the day. HOUR_OF_DAY is used for the 24-hour clock. * E.g., at 10:04:15.250 PM the HOUR_OF_DAY is 22. * @see #HOUR * @stable ICU 2.0 */ public final static int HOUR_OF_DAY = 11; /** * Field number for get and set indicating the * minute within the hour. * E.g., at 10:04:15.250 PM the MINUTE is 4. * @stable ICU 2.0 */ public final static int MINUTE = 12; /** * Field number for get and set indicating the * second within the minute. * E.g., at 10:04:15.250 PM the SECOND is 15. * @stable ICU 2.0 */ public final static int SECOND = 13; /** * Field number for get and set indicating the * millisecond within the second. * E.g., at 10:04:15.250 PM the MILLISECOND is 250. * @stable ICU 2.0 */ public final static int MILLISECOND = 14; /** * Field number for get and set indicating the * raw offset from GMT in milliseconds. * @stable ICU 2.0 */ public final static int ZONE_OFFSET = 15; /** * Field number for get and set indicating the * daylight savings offset in milliseconds. * @stable ICU 2.0 */ public final static int DST_OFFSET = 16; // /** // * {@icu} Field number for get() and set() // * indicating the extended year corresponding to the // * {@link #WEEK_OF_YEAR} field. This may be one greater or less // * than the value of {@link #EXTENDED_YEAR}. // * @stable ICU 2.0 // */ // public static final int YEAR_WOY = 17; // // /** // * {@icu} Field number for get() and set() // * indicating the localized day of week. This will be a value from 1 // * to 7 inclusive, with 1 being the localized first day of the week. // * @stable ICU 2.0 // */ // public static final int DOW_LOCAL = 18; // // /** // * {@icu} Field number for get() and set() // * indicating the extended year. This is a single number designating // * the year of this calendar system, encompassing all supra-year // * fields. For example, for the Julian calendar system, year numbers // * are positive, with an era of BCE or CE. An extended year value for // * the Julian calendar system assigns positive values to CE years and // * negative values to BCE years, with 1 BCE being year 0. // * @stable ICU 2.0 // */ // public static final int EXTENDED_YEAR = 19; // // /** // * {@icu} Field number for get() and set() // * indicating the modified Julian day number. This is different from // * the conventional Julian day number in two regards. First, it // * demarcates days at local zone midnight, rather than noon GMT. // * Second, it is a local number; that is, it depends on the local time // * zone. It can be thought of as a single number that encompasses all // * the date-related fields. // * @stable ICU 2.0 // */ // public static final int JULIAN_DAY = 20; // // /** // * {@icu} Field number for get() and set() // * indicating the milliseconds in the day. This ranges from 0 to // * 23:59:59.999 (regardless of DST). This field behaves // * exactly like a composite of all time-related fields, not // * including the zone fields. As such, it also reflects // * discontinuities of those fields on DST transition days. On a day of // * DST onset, it will jump forward. On a day of DST cessation, it will // * jump backward. This reflects the fact that is must be combined with // * the DST_OFFSET field to obtain a unique local time value. // * @stable ICU 2.0 // */ // public static final int MILLISECONDS_IN_DAY = 21; // // /** // * {@icu} Field indicating whether or not the current month is a leap month. // * Should have a value of 0 for non-leap months, and 1 for leap months. // * @draft ICU 4.4 // * @provisional This API might change or be removed in a future release. // */ // public static final int IS_LEAP_MONTH = 22; /** * Value of the DAY_OF_WEEK field indicating * Sunday. * @stable ICU 2.0 */ public final static int SUNDAY = 1; /** * Value of the DAY_OF_WEEK field indicating * Monday. * @stable ICU 2.0 */ public final static int MONDAY = 2; /** * Value of the DAY_OF_WEEK field indicating * Tuesday. * @stable ICU 2.0 */ public final static int TUESDAY = 3; /** * Value of the DAY_OF_WEEK field indicating * Wednesday. * @stable ICU 2.0 */ public final static int WEDNESDAY = 4; /** * Value of the DAY_OF_WEEK field indicating * Thursday. * @stable ICU 2.0 */ public final static int THURSDAY = 5; /** * Value of the DAY_OF_WEEK field indicating * Friday. * @stable ICU 2.0 */ public final static int FRIDAY = 6; /** * Value of the DAY_OF_WEEK field indicating * Saturday. * @stable ICU 2.0 */ public final static int SATURDAY = 7; /** * Value of the MONTH field indicating the * first month of the year. * @stable ICU 2.0 */ public final static int JANUARY = 0; /** * Value of the MONTH field indicating the * second month of the year. * @stable ICU 2.0 */ public final static int FEBRUARY = 1; /** * Value of the MONTH field indicating the * third month of the year. * @stable ICU 2.0 */ public final static int MARCH = 2; /** * Value of the MONTH field indicating the * fourth month of the year. * @stable ICU 2.0 */ public final static int APRIL = 3; /** * Value of the MONTH field indicating the * fifth month of the year. * @stable ICU 2.0 */ public final static int MAY = 4; /** * Value of the MONTH field indicating the * sixth month of the year. * @stable ICU 2.0 */ public final static int JUNE = 5; /** * Value of the MONTH field indicating the * seventh month of the year. * @stable ICU 2.0 */ public final static int JULY = 6; /** * Value of the MONTH field indicating the * eighth month of the year. * @stable ICU 2.0 */ public final static int AUGUST = 7; /** * Value of the MONTH field indicating the * ninth month of the year. * @stable ICU 2.0 */ public final static int SEPTEMBER = 8; /** * Value of the MONTH field indicating the * tenth month of the year. * @stable ICU 2.0 */ public final static int OCTOBER = 9; /** * Value of the MONTH field indicating the * eleventh month of the year. * @stable ICU 2.0 */ public final static int NOVEMBER = 10; /** * Value of the MONTH field indicating the * twelfth month of the year. * @stable ICU 2.0 */ public final static int DECEMBER = 11; /** * Value of the MONTH field indicating the * thirteenth month of the year. Although {@link GregorianCalendar} * does not use this value, lunar calendars do. * @stable ICU 2.0 */ public final static int UNDECIMBER = 12; /** * Value of the AM_PM field indicating the * period of the day from midnight to just before noon. * @stable ICU 2.0 */ public final static int AM = 0; /** * Value of the AM_PM field indicating the * period of the day from noon to just before midnight. * @stable ICU 2.0 */ public final static int PM = 1; /** * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a * weekday. * @see #WEEKEND * @see #WEEKEND_ONSET * @see #WEEKEND_CEASE * @see #getDayOfWeekType * @stable ICU 2.0 */ public static final int WEEKDAY = 0; /** * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a * weekend day. * @see #WEEKDAY * @see #WEEKEND_ONSET * @see #WEEKEND_CEASE * @see #getDayOfWeekType * @stable ICU 2.0 */ public static final int WEEKEND = 1; /** * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a * day that starts as a weekday and transitions to the weekend. * Call getWeekendTransition() to get the point of transition. * @see #WEEKDAY * @see #WEEKEND * @see #WEEKEND_CEASE * @see #getDayOfWeekType * @stable ICU 2.0 */ public static final int WEEKEND_ONSET = 2; /** * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a * day that starts as the weekend and transitions to a weekday. * Call getWeekendTransition() to get the point of transition. * @see #WEEKDAY * @see #WEEKEND * @see #WEEKEND_ONSET * @see #getDayOfWeekType * @stable ICU 2.0 */ public static final int WEEKEND_CEASE = 3; /** * {@icu}Option used by {@link #setRepeatedWallTimeOption(int)} and * {@link #setSkippedWallTimeOption(int)} specifying an ambiguous wall time * to be interpreted as the latest. * @see #setRepeatedWallTimeOption(int) * @see #getRepeatedWallTimeOption() * @see #setSkippedWallTimeOption(int) * @see #getSkippedWallTimeOption() * @draft ICU 49 * @provisional This API might change or be removed in a future release. */ public static final int WALLTIME_LAST = 0; /** * {@icu}Option used by {@link #setRepeatedWallTimeOption(int)} and * {@link #setSkippedWallTimeOption(int)} specifying an ambiguous wall time * to be interpreted as the earliest. * @see #setRepeatedWallTimeOption(int) * @see #getRepeatedWallTimeOption() * @see #setSkippedWallTimeOption(int) * @see #getSkippedWallTimeOption() * @draft ICU 49 * @provisional This API might change or be removed in a future release. */ public static final int WALLTIME_FIRST = 1; /** * {@icu}Option used by {@link #setSkippedWallTimeOption(int)} specifying an * ambiguous wall time to be interpreted as the next valid wall time. * @see #setSkippedWallTimeOption(int) * @see #getSkippedWallTimeOption() * @draft ICU 49 * @provisional This API might change or be removed in a future release. */ public static final int WALLTIME_NEXT_VALID = 2; /** * Constructs a Calendar with the default time zone * and locale. * @see TimeZone#getDefault * @stable ICU 2.0 */ protected Calendar() { this(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT)); } /** * Constructs a calendar with the specified time zone and locale. * @param zone the time zone to use * @param aLocale the locale for the week data * @stable ICU 2.0 */ protected Calendar(TimeZone zone, Locale aLocale) { this(zone, ULocale.forLocale(aLocale)); } /** * Constructs a calendar with the specified time zone and locale. * @param zone the time zone to use * @param locale the ulocale for the week data * @stable ICU 3.2 */ protected Calendar(TimeZone zone, ULocale locale) { calendar = java.util.Calendar.getInstance(zone.timeZone, locale.toLocale()); } /** * Returns a calendar using the default time zone and locale. * @return a Calendar. * @stable ICU 2.0 */ public static synchronized Calendar getInstance() { return new Calendar(java.util.Calendar.getInstance(ULocale.getDefault(Category.FORMAT).toLocale())); } /** * Returns a calendar using the specified time zone and default locale. * @param zone the time zone to use * @return a Calendar. * @stable ICU 2.0 */ public static synchronized Calendar getInstance(TimeZone zone) { return new Calendar(java.util.Calendar.getInstance(zone.timeZone, ULocale.getDefault(Category.FORMAT).toLocale())); } /** * Returns a calendar using the default time zone and specified locale. * @param aLocale the locale for the week data * @return a Calendar. * @stable ICU 2.0 */ public static synchronized Calendar getInstance(Locale aLocale) { return new Calendar(java.util.Calendar.getInstance(aLocale)); } /** * Returns a calendar using the default time zone and specified locale. * @param locale the ulocale for the week data * @return a Calendar. * @stable ICU 3.2 */ public static synchronized Calendar getInstance(ULocale locale) { return new Calendar(java.util.Calendar.getInstance(locale.toLocale())); } /** * Returns a calendar with the specified time zone and locale. * @param zone the time zone to use * @param aLocale the locale for the week data * @return a Calendar. * @stable ICU 2.0 */ public static synchronized Calendar getInstance(TimeZone zone, Locale aLocale) { return new Calendar(java.util.Calendar.getInstance(zone.timeZone, aLocale)); } /** * Returns a calendar with the specified time zone and locale. * @param zone the time zone to use * @param locale the ulocale for the week data * @return a Calendar. * @stable ICU 3.2 */ public static synchronized Calendar getInstance(TimeZone zone, ULocale locale) { return new Calendar(java.util.Calendar.getInstance(zone.timeZone, locale.toLocale())); } /** * Returns the list of locales for which Calendars are installed. * @return the list of locales for which Calendars are installed. * @stable ICU 2.0 */ public static Locale[] getAvailableLocales() { return java.util.Calendar.getAvailableLocales(); } /** * {@icu} Returns the list of locales for which Calendars are installed. * @return the list of locales for which Calendars are installed. * @draft ICU 3.2 (retain) * @provisional This API might change or be removed in a future release. */ public static ULocale[] getAvailableULocales() { if (availableLocales == null) { synchronized (Calendar.class) { if (availableLocales == null) { Locale[] locales = Locale.getAvailableLocales(); availableLocales = new ULocale[locales.length]; for (int i = 0; i < locales.length; i++) { availableLocales[i] = ULocale.forLocale(locales[i]); } } } } return availableLocales.clone(); } private static volatile ULocale[] availableLocales; // /** // * {@icu} Given a key and a locale, returns an array of string values in a preferred // * order that would make a difference. These are all and only those values where // * the open (creation) of the service with the locale formed from the input locale // * plus input keyword and that value has different behavior than creation with the // * input locale alone. // * @param key one of the keys supported by this service. For now, only // * "calendar" is supported. // * @param locale the locale // * @param commonlyUsed if set to true it will return only commonly used values // * with the given locale in preferred order. Otherwise, // * it will return all the available values for the locale. // * @return an array of string values for the given key and the locale. // * @stable ICU 4.2 // */ // public static final String[] getKeywordValuesForLocale(String key, ULocale locale, // boolean commonlyUsed) { // throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base"); // } /** * Returns this Calendar's current time. * @return the current time. * @stable ICU 2.0 */ public final Date getTime() { return calendar.getTime(); } /** * Sets this Calendar's current time with the given Date. * *

Note: Calling setTime with * Date(Long.MAX_VALUE) or Date(Long.MIN_VALUE) * may yield incorrect field values from {@link #get(int)}. * @param date the given Date. * @stable ICU 2.0 */ public final void setTime(Date date) { calendar.setTime(date); } /** * Returns this Calendar's current time as a long. * @return the current time as UTC milliseconds from the epoch. * @stable ICU 2.0 */ public long getTimeInMillis() { return calendar.getTimeInMillis(); } /** * Sets this Calendar's current time from the given long value. * @param millis the new time in UTC milliseconds from the epoch. * @stable ICU 2.0 */ public void setTimeInMillis( long millis ) { calendar.setTimeInMillis(millis); } /** * Returns the value for a given time field. * @param field the given time field. * @return the value for the given time field. * @stable ICU 2.0 */ public final int get(int field) { return calendar.get(getJDKField(field)); } /** * Sets the time field with the given value. * @param field the given time field. * @param value the value to be set for the given time field. * @stable ICU 2.0 */ public final void set(int field, int value) { calendar.set(getJDKField(field), value); } /** * Sets the values for the fields year, month, and date. * Previous values of other fields are retained. If this is not desired, * call {@link #clear()} first. * @param year the value used to set the YEAR time field. * @param month the value used to set the MONTH time field. * Month value is 0-based. e.g., 0 for January. * @param date the value used to set the DATE time field. * @stable ICU 2.0 */ public final void set(int year, int month, int date) { calendar.set(getJDKField(YEAR), year); calendar.set(getJDKField(MONTH), month); calendar.set(getJDKField(DATE), date); } /** * Sets the values for the fields year, month, date, hour, and minute. * Previous values of other fields are retained. If this is not desired, * call {@link #clear()} first. * @param year the value used to set the YEAR time field. * @param month the value used to set the MONTH time field. * Month value is 0-based. e.g., 0 for January. * @param date the value used to set the DATE time field. * @param hour the value used to set the HOUR_OF_DAY time field. * @param minute the value used to set the MINUTE time field. * @stable ICU 2.0 */ public final void set(int year, int month, int date, int hour, int minute) { calendar.set(getJDKField(YEAR), year); calendar.set(getJDKField(MONTH), month); calendar.set(getJDKField(DATE), date); calendar.set(getJDKField(HOUR_OF_DAY), hour); calendar.set(getJDKField(MINUTE), minute); } /** * Sets the values for the fields year, month, date, hour, minute, and second. * Previous values of other fields are retained. If this is not desired, * call {@link #clear} first. * @param year the value used to set the YEAR time field. * @param month the value used to set the MONTH time field. * Month value is 0-based. e.g., 0 for January. * @param date the value used to set the DATE time field. * @param hour the value used to set the HOUR_OF_DAY time field. * @param minute the value used to set the MINUTE time field. * @param second the value used to set the SECOND time field. * @stable ICU 2.0 */ public final void set(int year, int month, int date, int hour, int minute, int second) { calendar.set(getJDKField(YEAR), year); calendar.set(getJDKField(MONTH), month); calendar.set(getJDKField(DATE), date); calendar.set(getJDKField(HOUR_OF_DAY), hour); calendar.set(getJDKField(MINUTE), minute); calendar.set(getJDKField(SECOND), second); } /** * Clears the values of all the time fields. * @stable ICU 2.0 */ public final void clear() { calendar.clear(); } /** * Clears the value in the given time field. * @param field the time field to be cleared. * @stable ICU 2.0 */ public final void clear(int field) { calendar.clear(getJDKField(field)); } /** * Determines if the given time field has a value set. * @return true if the given time field has a value set; false otherwise. * @stable ICU 2.0 */ public final boolean isSet(int field) { return calendar.isSet(getJDKField(field)); } /** * Compares this calendar to the specified object. * The result is true if and only if the argument is * not null and is a Calendar object that * represents the same calendar as this object. * @param obj the object to compare with. * @return true if the objects are the same; * false otherwise. * @stable ICU 2.0 */ public boolean equals(Object obj) { try { return calendar.equals(((Calendar)obj).calendar); } catch (Exception e) { return false; } } /** * {@icu} Returns true if the given Calendar object is equivalent to this * one. An equivalent Calendar will behave exactly as this one * does, but it may be set to a different time. By contrast, for * the equals() method to return true, the other Calendar must * be set to the same time. * * @param other the Calendar to be compared with this Calendar * @stable ICU 2.4 */ public boolean isEquivalentTo(Calendar other) { return calendar.getClass() == other.calendar.getClass() && calendar.isLenient() == other.calendar.isLenient() && calendar.getFirstDayOfWeek() == other.calendar.getFirstDayOfWeek() && calendar.getMinimalDaysInFirstWeek() == other.calendar.getMinimalDaysInFirstWeek() && calendar.getTimeZone().equals(other.calendar.getTimeZone()); } /** * Returns a hash code for this calendar. * @return a hash code value for this object. * @stable ICU 2.0 */ public int hashCode() { return calendar.hashCode(); } /** * Returns the difference in milliseconds between the moment this * calendar is set to and the moment the given calendar or Date object * is set to. */ private long compare(Object that) { long thatMs; if (that instanceof Calendar) { thatMs = ((Calendar)that).getTimeInMillis(); } else if (that instanceof Date) { thatMs = ((Date)that).getTime(); } else { throw new IllegalArgumentException(that + "is not a Calendar or Date"); } return getTimeInMillis() - thatMs; } /** * Compares the time field records. * Equivalent to comparing result of conversion to UTC. * @param when the Calendar to be compared with this Calendar. * @return true if the current time of this Calendar is before * the time of Calendar when; false otherwise. * @stable ICU 2.0 */ public boolean before(Object when) { return compare(when) < 0; } /** * Compares the time field records. * Equivalent to comparing result of conversion to UTC. * @param when the Calendar to be compared with this Calendar. * @return true if the current time of this Calendar is after * the time of Calendar when; false otherwise. * @stable ICU 2.0 */ public boolean after(Object when) { return compare(when) > 0; } /** * Returns the maximum value that this field could have, given the * current date. For example, with the Gregorian date February 3, 1997 * and the {@link #DAY_OF_MONTH DAY_OF_MONTH} field, the actual maximum * is 28; for February 3, 1996 it is 29. * *

The actual maximum computation ignores smaller fields and the * current value of like-sized fields. For example, the actual maximum * of the DAY_OF_YEAR or MONTH depends only on the year and supra-year * fields. The actual maximum of the DAY_OF_MONTH depends, in * addition, on the MONTH field and any other fields at that * granularity (such as IS_LEAP_MONTH). The * DAY_OF_WEEK_IN_MONTH field does not depend on the current * DAY_OF_WEEK; it returns the maximum for any day of week in the * current month. Likewise for the WEEK_OF_MONTH and WEEK_OF_YEAR * fields. * * @param field the field whose maximum is desired * @return the maximum of the given field for the current date of this calendar * @see #getMaximum * @see #getLeastMaximum * @stable ICU 2.0 */ public int getActualMaximum(int field) { return calendar.getActualMaximum(getJDKField(field)); } /** * Returns the minimum value that this field could have, given the current date. * For most fields, this is the same as {@link #getMinimum getMinimum} * and {@link #getGreatestMinimum getGreatestMinimum}. However, some fields, * especially those related to week number, are more complicated. *

* For example, assume {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} * returns 4 and {@link #getFirstDayOfWeek getFirstDayOfWeek} returns SUNDAY. * If the first day of the month is Sunday, Monday, Tuesday, or Wednesday * there will be four or more days in the first week, so it will be week number 1, * and getActualMinimum(WEEK_OF_MONTH) will return 1. However, * if the first of the month is a Thursday, Friday, or Saturday, there are * not four days in that week, so it is week number 0, and * getActualMinimum(WEEK_OF_MONTH) will return 0. *

* @param field the field whose actual minimum value is desired. * @return the minimum of the given field for the current date of this calendar * * @see #getMinimum * @see #getGreatestMinimum * @stable ICU 2.0 */ public int getActualMinimum(int field) { return calendar.getActualMinimum(getJDKField(field)); } /** * Rolls (up/down) a single unit of time on the given field. If the * field is rolled past its maximum allowable value, it will "wrap" back * to its minimum and continue rolling. For * example, to roll the current date up by one day, you can call: *

* roll({@link #DATE}, true) *

* When rolling on the {@link #YEAR} field, it will roll the year * value in the range between 1 and the value returned by calling * {@link #getMaximum getMaximum}({@link #YEAR}). *

* When rolling on certain fields, the values of other fields may conflict and * need to be changed. For example, when rolling the MONTH field * for the Gregorian date 1/31/96 upward, the DAY_OF_MONTH field * must be adjusted so that the result is 2/29/96 rather than the invalid * 2/31/96. *

* Note: Calling roll(field, true) N times is not * necessarily equivalent to calling roll(field, N). For example, * imagine that you start with the date Gregorian date January 31, 1995. If you call * roll(Calendar.MONTH, 2), the result will be March 31, 1995. * But if you call roll(Calendar.MONTH, true), the result will be * February 28, 1995. Calling it one more time will give March 28, 1995, which * is usually not the desired result. *

* Note: You should always use roll and add rather * than attempting to perform arithmetic operations directly on the fields * of a Calendar. It is quite possible for Calendar subclasses * to have fields with non-linear behavior, for example missing months * or days during non-leap years. The subclasses' add and roll * methods will take this into account, while simple arithmetic manipulations * may give invalid results. *

* @param field the calendar field to roll. * * @param up indicates if the value of the specified time field is to be * rolled up or rolled down. Use true if rolling up, * false otherwise. * * @exception IllegalArgumentException if the field is invalid or refers * to a field that cannot be handled by this method. * @see #roll(int, int) * @see #add * @stable ICU 2.0 */ public final void roll(int field, boolean up) { calendar.roll(getJDKField(field), up); } /** * Rolls (up/down) a specified amount time on the given field. For * example, to roll the current date up by three days, you can call * roll(Calendar.DATE, 3). If the * field is rolled past its maximum allowable value, it will "wrap" back * to its minimum and continue rolling. * For example, calling roll(Calendar.DATE, 10) * on a Gregorian calendar set to 4/25/96 will result in the date 4/5/96. *

* When rolling on certain fields, the values of other fields may conflict and * need to be changed. For example, when rolling the {@link #MONTH MONTH} field * for the Gregorian date 1/31/96 by +1, the {@link #DAY_OF_MONTH DAY_OF_MONTH} field * must be adjusted so that the result is 2/29/96 rather than the invalid * 2/31/96. *

* {@icunote} the ICU implementation of this method is able to roll * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET}, * and {@link #ZONE_OFFSET ZONE_OFFSET}. Subclasses may, of course, add support for * additional fields in their overrides of roll. *

* Note: You should always use roll and add rather * than attempting to perform arithmetic operations directly on the fields * of a Calendar. It is quite possible for Calendar subclasses * to have fields with non-linear behavior, for example missing months * or days during non-leap years. The subclasses' add and roll * methods will take this into account, while simple arithmetic manipulations * may give invalid results. *

* Subclassing:
* This implementation of roll assumes that the behavior of the * field is continuous between its minimum and maximum, which are found by * calling {@link #getActualMinimum getActualMinimum} and {@link #getActualMaximum getActualMaximum}. * For most such fields, simple addition, subtraction, and modulus operations * are sufficient to perform the roll. For week-related fields, * the results of {@link #getFirstDayOfWeek getFirstDayOfWeek} and * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} are also necessary. * Subclasses can override these two methods if their values differ from the defaults. *

* Subclasses that have fields for which the assumption of continuity breaks * down must overide roll to handle those fields specially. * For example, in the Hebrew calendar the month "Adar I" * only occurs in leap years; in other years the calendar jumps from * Shevat (month #4) to Adar (month #6). The * {@link HebrewCalendar#roll HebrewCalendar.roll} method takes this into account, * so that rolling the month of Shevat by one gives the proper result (Adar) in a * non-leap year. *

* @param field the calendar field to roll. * @param amount the amount by which the field should be rolled. * * @exception IllegalArgumentException if the field is invalid or refers * to a field that cannot be handled by this method. * @see #roll(int, boolean) * @see #add * @stable ICU 2.0 */ public void roll(int field, int amount) { calendar.roll(getJDKField(field), amount); } /** * Add a signed amount to a specified field, using this calendar's rules. * For example, to add three days to the current date, you can call * add(Calendar.DATE, 3). *

* When adding to certain fields, the values of other fields may conflict and * need to be changed. For example, when adding one to the {@link #MONTH MONTH} field * for the Gregorian date 1/31/96, the {@link #DAY_OF_MONTH DAY_OF_MONTH} field * must be adjusted so that the result is 2/29/96 rather than the invalid * 2/31/96. *

* {@icunote} The ICU implementation of this method is able to add to * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET}, * and {@link #ZONE_OFFSET ZONE_OFFSET}. Subclasses may, of course, add support for * additional fields in their overrides of add. *

* Note: You should always use roll and add rather * than attempting to perform arithmetic operations directly on the fields * of a Calendar. It is quite possible for Calendar subclasses * to have fields with non-linear behavior, for example missing months * or days during non-leap years. The subclasses' add and roll * methods will take this into account, while simple arithmetic manipulations * may give invalid results. *

* Subclassing:
* This implementation of add assumes that the behavior of the * field is continuous between its minimum and maximum, which are found by * calling {@link #getActualMinimum getActualMinimum} and * {@link #getActualMaximum getActualMaximum}. * For such fields, simple arithmetic operations are sufficient to * perform the add. *

* Subclasses that have fields for which this assumption of continuity breaks * down must overide add to handle those fields specially. * For example, in the Hebrew calendar the month "Adar I" * only occurs in leap years; in other years the calendar jumps from * Shevat (month #4) to Adar (month #6). The * {@link HebrewCalendar#add HebrewCalendar.add} method takes this into account, * so that adding one month * to a date in Shevat gives the proper result (Adar) in a non-leap year. *

* @param field the time field. * @param amount the amount to add to the field. * * @exception IllegalArgumentException if the field is invalid or refers * to a field that cannot be handled by this method. * @see #roll(int, int) * @stable ICU 2.0 */ public void add(int field, int amount) { calendar.add(getJDKField(field), amount); } private static String _getDisplayName(Calendar cal) { String type = cal.getType(); if (type.equals("japanese")) { return "Japanese Calendar"; } else if (type.equals("buddhist")) { return "Buddhist Calendar"; } return "Gregorian Calendar"; } /** * Returns the name of this calendar in the language of the given locale. * @stable ICU 2.0 */ public String getDisplayName(Locale loc) { return _getDisplayName(this); } /** * Returns the name of this calendar in the language of the given locale. * @stable ICU 3.2 */ public String getDisplayName(ULocale loc) { return _getDisplayName(this); } /** * Compares the times (in millis) represented by two * Calendar objects. * * @param that the Calendar to compare to this. * @return 0 if the time represented by * this Calendar is equal to the time represented * by that Calendar, a value less than * 0 if the time represented by this is before * the time represented by that, and a value greater than * 0 if the time represented by this * is after the time represented by that. * @throws NullPointerException if that * Calendar is null. * @throws IllegalArgumentException if the time of that * Calendar can't be obtained because of invalid * calendar values. * @stable ICU 3.4 */ public int compareTo(Calendar that) { return calendar.compareTo(that.calendar); } //------------------------------------------------------------------------- // Interface for creating custon DateFormats for different types of Calendars //------------------------------------------------------------------------- /** * {@icu} Returns a DateFormat appropriate to this calendar. * Subclasses wishing to specialize this behavior should override * {@link #handleGetDateFormat}. * @stable ICU 2.0 */ public DateFormat getDateTimeFormat(int dateStyle, int timeStyle, Locale loc) { if (dateStyle != DateFormat.NONE) { if (timeStyle == DateFormat.NONE) { return DateFormat.getDateInstance((Calendar)this.clone(), dateStyle, loc); } else { return DateFormat.getDateTimeInstance((Calendar)this.clone(), dateStyle, timeStyle, loc); } } else if (timeStyle != DateFormat.NONE) { return DateFormat.getTimeInstance((Calendar)this.clone(), timeStyle, loc); } else { return null; } } /** * {@icu} Returns a DateFormat appropriate to this calendar. * Subclasses wishing to specialize this behavior should override * {@link #handleGetDateFormat}. * @stable ICU 3.2 */ public DateFormat getDateTimeFormat(int dateStyle, int timeStyle, ULocale loc) { return getDateTimeFormat(dateStyle, timeStyle, loc.toLocale()); } //------------------------------------------------------------------------- // Constants //------------------------------------------------------------------------- /** * {@icu} Returns the difference between the given time and the time this * calendar object is set to. If this calendar is set * before the given time, the returned value will be * positive. If this calendar is set after the given * time, the returned value will be negative. The * field parameter specifies the units of the return * value. For example, if fieldDifference(when, * Calendar.MONTH) returns 3, then this calendar is set to * 3 months before when, and possibly some additional * time less than one month. * *

As a side effect of this call, this calendar is advanced * toward when by the given amount. That is, calling * this method has the side effect of calling add(field, * n), where n is the return value. * *

Usage: To use this method, call it first with the largest * field of interest, then with progressively smaller fields. For * example: * *

     * int y = cal.fieldDifference(when, Calendar.YEAR);
     * int m = cal.fieldDifference(when, Calendar.MONTH);
     * int d = cal.fieldDifference(when, Calendar.DATE);
* * computes the difference between cal and * when in years, months, and days. * *

Note: fieldDifference() is * asymmetrical. That is, in the following code: * *

     * cal.setTime(date1);
     * int m1 = cal.fieldDifference(date2, Calendar.MONTH);
     * int d1 = cal.fieldDifference(date2, Calendar.DATE);
     * cal.setTime(date2);
     * int m2 = cal.fieldDifference(date1, Calendar.MONTH);
     * int d2 = cal.fieldDifference(date1, Calendar.DATE);
* * one might expect that m1 == -m2 && d1 == -d2. * However, this is not generally the case, because of * irregularities in the underlying calendar system (e.g., the * Gregorian calendar has a varying number of days per month). * * @param when the date to compare this calendar's time to * @param field the field in which to compute the result * @return the difference, either positive or negative, between * this calendar's time and when, in terms of * field. * @stable ICU 2.0 */ public int fieldDifference(Date when, int field) { int min = 0; long startMs = getTimeInMillis(); long targetMs = when.getTime(); // Always add from the start millis. This accomodates // operations like adding years from February 29, 2000 up to // February 29, 2004. If 1, 1, 1, 1 is added to the year // field, the DOM gets pinned to 28 and stays there, giving an // incorrect DOM difference of 1. We have to add 1, reset, 2, // reset, 3, reset, 4. if (startMs < targetMs) { int max = 1; // Find a value that is too large for (;;) { setTimeInMillis(startMs); add(field, max); long ms = getTimeInMillis(); if (ms == targetMs) { return max; } else if (ms > targetMs) { break; } else { max <<= 1; if (max < 0) { // Field difference too large to fit into int throw new RuntimeException(); } } } // Do a binary search while ((max - min) > 1) { int t = (min + max) / 2; setTimeInMillis(startMs); add(field, t); long ms = getTimeInMillis(); if (ms == targetMs) { return t; } else if (ms > targetMs) { max = t; } else { min = t; } } } else if (startMs > targetMs) { //Eclipse stated the following is "dead code" /*if (false) { // This works, and makes the code smaller, but costs // an extra object creation and an extra couple cycles // of calendar computation. setTimeInMillis(targetMs); min = -fieldDifference(new Date(startMs), field); }*/ int max = -1; // Find a value that is too small for (;;) { setTimeInMillis(startMs); add(field, max); long ms = getTimeInMillis(); if (ms == targetMs) { return max; } else if (ms < targetMs) { break; } else { max <<= 1; if (max == 0) { // Field difference too large to fit into int throw new RuntimeException(); } } } // Do a binary search while ((min - max) > 1) { int t = (min + max) / 2; setTimeInMillis(startMs); add(field, t); long ms = getTimeInMillis(); if (ms == targetMs) { return t; } else if (ms < targetMs) { max = t; } else { min = t; } } } // Set calendar to end point setTimeInMillis(startMs); add(field, min); return min; } /** * Sets the time zone with the given time zone value. * @param value the given time zone. * @stable ICU 2.0 */ public void setTimeZone(TimeZone value) { calendar.setTimeZone(value.timeZone); } /** * Returns the time zone. * @return the time zone object associated with this calendar. * @stable ICU 2.0 */ public TimeZone getTimeZone() { return new TimeZone(calendar.getTimeZone()); } /** * Specify whether or not date/time interpretation is to be lenient. With * lenient interpretation, a date such as "February 942, 1996" will be * treated as being equivalent to the 941st day after February 1, 1996. * With strict interpretation, such dates will cause an exception to be * thrown. * * @see DateFormat#setLenient * @stable ICU 2.0 */ public void setLenient(boolean lenient) { calendar.setLenient(lenient); } /** * Tell whether date/time interpretation is to be lenient. * @stable ICU 2.0 */ public boolean isLenient() { return calendar.isLenient(); } // /** // * {@icu}Sets the behavior for handling wall time repeating multiple times // * at negative time zone offset transitions. For example, 1:30 AM on // * November 6, 2011 in US Eastern time (Ameirca/New_York) occurs twice; // * 1:30 AM EDT, then 1:30 AM EST one hour later. When WALLTIME_FIRST // * is used, the wall time 1:30AM in this example will be interpreted as 1:30 AM EDT // * (first occurrence). When WALLTIME_LAST is used, it will be // * interpreted as 1:30 AM EST (last occurrence). The default value is // * WALLTIME_LAST. // * // * @param option the behavior for handling repeating wall time, either // * WALLTIME_FIRST or WALLTIME_LAST. // * @throws IllegalArgumentException when option is neither // * WALLTIME_FIRST nor WALLTIME_LAST. // * // * @see #getRepeatedWallTimeOption() // * @see #WALLTIME_FIRST // * @see #WALLTIME_LAST // * // * @draft ICU 49 // * @provisional This API might change or be removed in a future release. // */ // public void setRepeatedWallTimeOption(int option) { // if (option != WALLTIME_LAST) { // throw new UnsupportedOperationException("The option not supported by com.ibm.icu.base"); // } // } /** * {@icu}Gets the behavior for handling wall time repeating multiple times * at negative time zone offset transitions. * * @return the behavior for handling repeating wall time, either * WALLTIME_FIRST or WALLTIME_LAST. * * @see #setRepeatedWallTimeOption(int) * @see #WALLTIME_FIRST * @see #WALLTIME_LAST * * @draft ICU 49 * @provisional This API might change or be removed in a future release. */ public int getRepeatedWallTimeOption() { return WALLTIME_LAST; } // /** // * {@icu}Sets the behavior for handling skipped wall time at positive time zone offset // * transitions. For example, 2:30 AM on March 13, 2011 in US Eastern time (America/New_York) // * does not exist because the wall time jump from 1:59 AM EST to 3:00 AM EDT. When // * WALLTIME_FIRST is used, 2:30 AM is interpreted as 30 minutes before 3:00 AM // * EDT, therefore, it will be resolved as 1:30 AM EST. When WALLTIME_LAST // * is used, 2:30 AM is interpreted as 31 minutes after 1:59 AM EST, therefore, it will be // * resolved as 3:30 AM EDT. When WALLTIME_NEXT_VALID is used, 2:30 AM will // * be resolved as next valid wall time, that is 3:00 AM EDT. The default value is // * WALLTIME_LAST. // *

// * Note:This option is effective only when this calendar is {@link #isLenient() lenient}. // * When the calendar is strict, such non-existing wall time will cause an exception. // * // * @param option the behavior for handling skipped wall time at positive time zone // * offset transitions, one of WALLTIME_FIRST, WALLTIME_LAST and // * WALLTIME_NEXT_VALID. // * @throws IllegalArgumentException when option is not any of // * WALLTIME_FIRST, WALLTIME_LAST and WALLTIME_NEXT_VALID. // * // * @see #getSkippedWallTimeOption() // * @see #WALLTIME_FIRST // * @see #WALLTIME_LAST // * @see #WALLTIME_NEXT_VALID // * // * @draft ICU 49 // * @provisional This API might change or be removed in a future release. // */ // public void setSkippedWallTimeOption(int option) { // if (option != WALLTIME_LAST) { // throw new UnsupportedOperationException("The option not supported by com.ibm.icu.base"); // } // } /** * {@icu}Gets the behavior for handling skipped wall time at positive time zone offset * transitions. * * @return the behavior for handling skipped wall time, one of * WALLTIME_FIRST, WALLTIME_LAST and WALLTIME_NEXT_VALID. * * @see #setSkippedWallTimeOption(int) * @see #WALLTIME_FIRST * @see #WALLTIME_LAST * @see #WALLTIME_NEXT_VALID * * @draft ICU 49 * @provisional This API might change or be removed in a future release. */ public int getSkippedWallTimeOption() { return WALLTIME_LAST; } /** * Sets what the first day of the week is; e.g., Sunday in US, * Monday in France. * @param value the given first day of the week. * @stable ICU 2.0 */ public void setFirstDayOfWeek(int value) { calendar.setFirstDayOfWeek(value); } /** * Returns what the first day of the week is; e.g., Sunday in US, * Monday in France. * @return the first day of the week. * @stable ICU 2.0 */ public int getFirstDayOfWeek() { return calendar.getFirstDayOfWeek(); } /** * Sets what the minimal days required in the first week of the year are. * For example, if the first week is defined as one that contains the first * day of the first month of a year, call the method with value 1. If it * must be a full week, use value 7. * @param value the given minimal days required in the first week * of the year. * @stable ICU 2.0 */ public void setMinimalDaysInFirstWeek(int value) { calendar.setMinimalDaysInFirstWeek(value); } /** * Returns what the minimal days required in the first week of the year are; * e.g., if the first week is defined as one that contains the first day * of the first month of a year, getMinimalDaysInFirstWeek returns 1. If * the minimal days required must be a full week, getMinimalDaysInFirstWeek * returns 7. * @return the minimal days required in the first week of the year. * @stable ICU 2.0 */ public int getMinimalDaysInFirstWeek() { return calendar.getMinimalDaysInFirstWeek(); } /** * Returns the minimum value for the given time field. * e.g., for Gregorian DAY_OF_MONTH, 1. * @param field the given time field. * @return the minimum value for the given time field. * @stable ICU 2.0 */ public final int getMinimum(int field) { return calendar.getMinimum(getJDKField(field)); } /** * Returns the maximum value for the given time field. * e.g. for Gregorian DAY_OF_MONTH, 31. * @param field the given time field. * @return the maximum value for the given time field. * @stable ICU 2.0 */ public final int getMaximum(int field) { return calendar.getMaximum(getJDKField(field)); } /** * Returns the highest minimum value for the given field if varies. * Otherwise same as getMinimum(). For Gregorian, no difference. * @param field the given time field. * @return the highest minimum value for the given time field. * @stable ICU 2.0 */ public final int getGreatestMinimum(int field) { return calendar.getGreatestMinimum(getJDKField(field)); } /** * Returns the lowest maximum value for the given field if varies. * Otherwise same as getMaximum(). e.g., for Gregorian DAY_OF_MONTH, 28. * @param field the given time field. * @return the lowest maximum value for the given time field. * @stable ICU 2.0 */ public final int getLeastMaximum(int field) { return calendar.getLeastMaximum(getJDKField(field)); } //------------------------------------------------------------------------- // Weekend support -- determining which days of the week are the weekend // in a given locale //------------------------------------------------------------------------- /** * {@icu} Returns whether the given day of the week is a weekday, a * weekend day, or a day that transitions from one to the other, * in this calendar system. If a transition occurs at midnight, * then the days before and after the transition will have the * type WEEKDAY or WEEKEND. If a transition occurs at a time * other than midnight, then the day of the transition will have * the type WEEKEND_ONSET or WEEKEND_CEASE. In this case, the * method getWeekendTransition() will return the point of * transition. * @param dayOfWeek either SUNDAY, MONDAY, TUESDAY, WEDNESDAY, * THURSDAY, FRIDAY, or SATURDAY * @return either WEEKDAY, WEEKEND, WEEKEND_ONSET, or * WEEKEND_CEASE * @exception IllegalArgumentException if dayOfWeek is not * between SUNDAY and SATURDAY, inclusive * @see #WEEKDAY * @see #WEEKEND * @see #WEEKEND_ONSET * @see #WEEKEND_CEASE * @see #getWeekendTransition * @see #isWeekend(Date) * @see #isWeekend() * @stable ICU 2.0 */ public int getDayOfWeekType(int dayOfWeek) { // weekend always full saturday and sunday with com.ibm.icu.base if (dayOfWeek < SUNDAY || dayOfWeek > 7) { throw new IllegalArgumentException("illegal day of week: " + dayOfWeek); } else if (dayOfWeek == SATURDAY || dayOfWeek == SUNDAY) { return WEEKEND; } return WEEKDAY;} // /** // * {@icu} Returns the time during the day at which the weekend begins or end in this // * calendar system. If getDayOfWeekType(dayOfWeek) == WEEKEND_ONSET return the time // * at which the weekend begins. If getDayOfWeekType(dayOfWeek) == WEEKEND_CEASE // * return the time at which the weekend ends. If getDayOfWeekType(dayOfWeek) has some // * other value, then throw an exception. // * @param dayOfWeek either SUNDAY, MONDAY, TUESDAY, WEDNESDAY, // * THURSDAY, FRIDAY, or SATURDAY // * @return the milliseconds after midnight at which the // * weekend begins or ends // * @exception IllegalArgumentException if dayOfWeek is not // * WEEKEND_ONSET or WEEKEND_CEASE // * @see #getDayOfWeekType // * @see #isWeekend(Date) // * @see #isWeekend() // * @stable ICU 2.0 // */ // public int getWeekendTransition(int dayOfWeek) { // throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base"); // } /** * {@icu} Returns true if the given date and time is in the weekend in this calendar * system. Equivalent to calling setTime() followed by isWeekend(). Note: This * method changes the time this calendar is set to. * @param date the date and time * @return true if the given date and time is part of the * weekend * @see #getDayOfWeekType * @see #getWeekendTransition * @see #isWeekend() * @stable ICU 2.0 */ public boolean isWeekend(Date date) { calendar.setTime(date); return isWeekend(); } /** * {@icu} Returns true if this Calendar's current date and time is in the weekend in * this calendar system. * @return true if the given date and time is part of the * weekend * @see #getDayOfWeekType * @see #getWeekendTransition * @see #isWeekend(Date) * @stable ICU 2.0 */ public boolean isWeekend() { // weekend always full saturday and sunday with com.ibm.icu.base int dow = calendar.get(Calendar.DAY_OF_WEEK); if (dow == SATURDAY || dow == SUNDAY) { return true; } return false; } //------------------------------------------------------------------------- // End of weekend support //------------------------------------------------------------------------- /** * Overrides Cloneable * @stable ICU 2.0 */ public Object clone() { return new Calendar((java.util.Calendar)calendar.clone()); } /** * Returns a string representation of this calendar. This method * is intended to be used only for debugging purposes, and the * format of the returned string may vary between implementations. * The returned string may be empty but may not be null. * * @return a string representation of this calendar. * @stable ICU 2.0 */ public String toString() { return calendar.toString(); } /** * {@icu} Returns the number of fields defined by this calendar. Valid field * arguments to set() and get() are * 0..getFieldCount()-1. * @stable ICU 2.0 */ public final int getFieldCount() { return FIELD_COUNT; } private static final int FIELD_COUNT = /* IS_LEAP_MONTH */ DST_OFFSET + 1; /** * {@icu} Returns the current Calendar type. Note, in 3.0 this function will return * 'gregorian' in Calendar to emulate legacy behavior * @return type of calendar (gregorian, etc) * @stable ICU 3.8 */ public String getType() { // JDK supports Gregorian, Japanese and Buddhist String name = calendar.getClass().getSimpleName().toLowerCase(Locale.US); if (name.contains("japanese")) { return "japanese"; } else if (name.contains("buddhist")) { return "buddhist"; } return "gregorian"; } // -------- BEGIN ULocale boilerplate -------- // /** // * {@icu} Returns the locale that was used to create this object, or null. // * This may may differ from the locale requested at the time of // * this object's creation. For example, if an object is created // * for locale en_US_CALIFORNIA, the actual data may be // * drawn from en (the actual locale), and // * en_US may be the most specific locale that exists (the // * valid locale). // * // *

Note: This method will be implemented in ICU 3.0; ICU 2.8 // * contains a partial preview implementation. The * actual // * locale is returned correctly, but the valid locale is // * not, in most cases. // * @param type type of information requested, either {@link // * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link // * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}. // * @return the information specified by type, or null if // * this object was not constructed from locale data. // * @see com.ibm.icu.util.ULocale // * @see com.ibm.icu.util.ULocale#VALID_LOCALE // * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE // * @draft ICU 2.8 (retain) // * @provisional This API might change or be removed in a future release. // */ // public final ULocale getLocale(ULocale.Type type) { // throw new UnsupportedOperationException("Method not supported by com.ibm.icu.base"); // } // -------- END ULocale boilerplate -------- private static int getJDKField(int icuField) { switch (icuField) { case ERA: return java.util.Calendar.ERA; case YEAR: return java.util.Calendar.YEAR; case MONTH: return java.util.Calendar.MONTH; case WEEK_OF_YEAR: return java.util.Calendar.WEEK_OF_YEAR; case WEEK_OF_MONTH: return java.util.Calendar.WEEK_OF_MONTH; case DATE: return java.util.Calendar.DATE; // case DAY_OF_MONTH: // return java.util.Calendar.DAY_OF_MONTH; case DAY_OF_YEAR: return java.util.Calendar.DAY_OF_YEAR; case DAY_OF_WEEK: return java.util.Calendar.DAY_OF_WEEK; case DAY_OF_WEEK_IN_MONTH: return java.util.Calendar.DAY_OF_WEEK_IN_MONTH; case AM_PM: return java.util.Calendar.AM_PM; case HOUR: return java.util.Calendar.HOUR; case HOUR_OF_DAY: return java.util.Calendar.HOUR_OF_DAY; case MINUTE: return java.util.Calendar.MINUTE; case SECOND: return java.util.Calendar.SECOND; case MILLISECOND: return java.util.Calendar.MILLISECOND; case ZONE_OFFSET: return java.util.Calendar.ZONE_OFFSET; case DST_OFFSET: return java.util.Calendar.DST_OFFSET; // case YEAR_WOY: // case DOW_LOCAL: // case EXTENDED_YEAR: // case JULIAN_DAY: // case MILLISECONDS_IN_DAY: // // Unmappable // throw new UnsupportedOperationException("Calendar field type not supported by com.ibm.icu.base"); default: // Illegal throw new ArrayIndexOutOfBoundsException("Specified calendar field is out of range"); } } }