0001: /*
0002: * Copyright (C) 1996-2006, International Business Machines
0003: * Corporation and others. All Rights Reserved.
0004: */
0005:
0006: package com.ibm.icu.util;
0007:
0008: import com.ibm.icu.impl.ICULocaleService;
0009: import com.ibm.icu.impl.ICULocaleService.LocaleKeyFactory;
0010: import com.ibm.icu.impl.ICUResourceBundle;
0011: import com.ibm.icu.impl.ICUService.Factory;
0012: import com.ibm.icu.impl.CalendarData;
0013: import com.ibm.icu.text.DateFormat;
0014: import com.ibm.icu.text.DateFormatSymbols;
0015: import com.ibm.icu.text.SimpleDateFormat;
0016: import com.ibm.icu.util.TimeZone;
0017: import com.ibm.icu.util.BuddhistCalendar;
0018: import com.ibm.icu.util.ChineseCalendar;
0019: import com.ibm.icu.util.CopticCalendar;
0020: import com.ibm.icu.util.EthiopicCalendar;
0021: import com.ibm.icu.util.GregorianCalendar;
0022: import com.ibm.icu.util.HebrewCalendar;
0023: import com.ibm.icu.util.IslamicCalendar;
0024: import com.ibm.icu.util.JapaneseCalendar;
0025:
0026: import java.io.IOException;
0027: import java.io.ObjectInputStream;
0028: import java.io.ObjectOutputStream;
0029: import java.io.Serializable;
0030: import java.text.MessageFormat;
0031: import java.util.Collections;
0032: import java.util.Date;
0033: import java.util.Hashtable;
0034: import java.util.HashMap;
0035: import java.util.Locale;
0036: import java.util.Map;
0037: import java.util.MissingResourceException;
0038: import java.util.ResourceBundle;
0039: import java.util.Set;
0040:
0041: /**
0042: * <code>Calendar</code> is an abstract base class for converting between
0043: * a <code>Date</code> object and a set of integer fields such as
0044: * <code>YEAR</code>, <code>MONTH</code>, <code>DAY</code>, <code>HOUR</code>,
0045: * and so on. (A <code>Date</code> object represents a specific instant in
0046: * time with millisecond precision. See
0047: * {@link Date}
0048: * for information about the <code>Date</code> class.)
0049: *
0050: * <p><b>Note:</b> This class is similar, but not identical, to the class
0051: * <code>java.util.Calendar</code>. Changes are detailed below.
0052: *
0053: * <p>
0054: * Subclasses of <code>Calendar</code> interpret a <code>Date</code>
0055: * according to the rules of a specific calendar system. ICU4J contains
0056: * several subclasses implementing different international calendar systems.
0057: *
0058: * <p>
0059: * Like other locale-sensitive classes, <code>Calendar</code> provides a
0060: * class method, <code>getInstance</code>, for getting a generally useful
0061: * object of this type. <code>Calendar</code>'s <code>getInstance</code> method
0062: * returns a calendar of a type appropriate to the locale, whose
0063: * time fields have been initialized with the current date and time:
0064: * <blockquote>
0065: * <pre>Calendar rightNow = Calendar.getInstance()</pre>
0066: * </blockquote>
0067: *
0068: * <p>When a <code>ULocale</code> is used by <code>getInstance</code>, its
0069: * '<code>calendar</code>' tag and value are retrieved if present. If a recognized
0070: * value is supplied, a calendar is provided and configured as appropriate.
0071: * Currently recognized tags are "buddhist", "chinese", "coptic", "ethiopic",
0072: * "gregorian", "hebrew", "islamic", "islamic-civil", and "japanese". For
0073: * example: <blockquote>
0074: * <pre>Calendar cal = Calendar.getInstance(new ULocale("en_US@calendar=japanese"));</pre>
0075: * </blockquote> will return an instance of JapaneseCalendar (using en_US conventions for
0076: * minimum days in first week, start day of week, et cetera).
0077: *
0078: * <p>A <code>Calendar</code> object can produce all the time field values
0079: * needed to implement the date-time formatting for a particular language and
0080: * calendar style (for example, Japanese-Gregorian, Japanese-Traditional).
0081: * <code>Calendar</code> defines the range of values returned by certain fields,
0082: * as well as their meaning. For example, the first month of the year has value
0083: * <code>MONTH</code> == <code>JANUARY</code> for all calendars. Other values
0084: * are defined by the concrete subclass, such as <code>ERA</code> and
0085: * <code>YEAR</code>. See individual field documentation and subclass
0086: * documentation for details.
0087: *
0088: * <p>When a <code>Calendar</code> is <em>lenient</em>, it accepts a wider range
0089: * of field values than it produces. For example, a lenient
0090: * <code>GregorianCalendar</code> interprets <code>MONTH</code> ==
0091: * <code>JANUARY</code>, <code>DAY_OF_MONTH</code> == 32 as February 1. A
0092: * non-lenient <code>GregorianCalendar</code> throws an exception when given
0093: * out-of-range field settings. When calendars recompute field values for
0094: * return by <code>get()</code>, they normalize them. For example, a
0095: * <code>GregorianCalendar</code> always produces <code>DAY_OF_MONTH</code>
0096: * values between 1 and the length of the month.
0097: *
0098: * <p><code>Calendar</code> defines a locale-specific seven day week using two
0099: * parameters: the first day of the week and the minimal days in first week
0100: * (from 1 to 7). These numbers are taken from the locale resource data when a
0101: * <code>Calendar</code> is constructed. They may also be specified explicitly
0102: * through the API.
0103: *
0104: * <p>When setting or getting the <code>WEEK_OF_MONTH</code> or
0105: * <code>WEEK_OF_YEAR</code> fields, <code>Calendar</code> must determine the
0106: * first week of the month or year as a reference point. The first week of a
0107: * month or year is defined as the earliest seven day period beginning on
0108: * <code>getFirstDayOfWeek()</code> and containing at least
0109: * <code>getMinimalDaysInFirstWeek()</code> days of that month or year. Weeks
0110: * numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow
0111: * it. Note that the normalized numbering returned by <code>get()</code> may be
0112: * different. For example, a specific <code>Calendar</code> subclass may
0113: * designate the week before week 1 of a year as week <em>n</em> of the previous
0114: * year.
0115: *
0116: * <p> When computing a <code>Date</code> from time fields, two special
0117: * circumstances may arise: there may be insufficient information to compute the
0118: * <code>Date</code> (such as only year and month but no day in the month), or
0119: * there may be inconsistent information (such as "Tuesday, July 15, 1996" --
0120: * July 15, 1996 is actually a Monday).
0121: *
0122: * <p>
0123: * <strong>Insufficient information.</strong> The calendar will use default
0124: * information to specify the missing fields. This may vary by calendar; for
0125: * the Gregorian calendar, the default for a field is the same as that of the
0126: * start of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc.
0127: *
0128: * <p>
0129: * <strong>Inconsistent information.</strong> If fields conflict, the calendar
0130: * will give preference to fields set more recently. For example, when
0131: * determining the day, the calendar will look for one of the following
0132: * combinations of fields. The most recent combination, as determined by the
0133: * most recently set single field, will be used.
0134: *
0135: * <blockquote>
0136: * <pre>
0137: * MONTH + DAY_OF_MONTH
0138: * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
0139: * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
0140: * DAY_OF_YEAR
0141: * DAY_OF_WEEK + WEEK_OF_YEAR</pre>
0142: * </blockquote>
0143: *
0144: * For the time of day:
0145: *
0146: * <blockquote>
0147: * <pre>
0148: * HOUR_OF_DAY
0149: * AM_PM + HOUR</pre>
0150: * </blockquote>
0151: *
0152: * <p>
0153: * <strong>Note:</strong> for some non-Gregorian calendars, different
0154: * fields may be necessary for complete disambiguation. For example, a full
0155: * specification of the historial Arabic astronomical calendar requires year,
0156: * month, day-of-month <em>and</em> day-of-week in some cases.
0157: *
0158: * <p>
0159: * <strong>Note:</strong> There are certain possible ambiguities in
0160: * interpretation of certain singular times, which are resolved in the
0161: * following ways:
0162: * <ol>
0163: * <li> 24:00:00 "belongs" to the following day. That is,
0164: * 23:59 on Dec 31, 1969 < 24:00 on Jan 1, 1970 < 24:01:00 on Jan 1, 1970
0165: *
0166: * <li> Although historically not precise, midnight also belongs to "am",
0167: * and noon belongs to "pm", so on the same day,
0168: * 12:00 am (midnight) < 12:01 am, and 12:00 pm (noon) < 12:01 pm
0169: * </ol>
0170: *
0171: * <p>
0172: * The date or time format strings are not part of the definition of a
0173: * calendar, as those must be modifiable or overridable by the user at
0174: * runtime. Use {@link DateFormat}
0175: * to format dates.
0176: *
0177: * <p><strong>Field manipulation methods</strong></p>
0178: *
0179: * <p><code>Calendar</code> fields can be changed using three methods:
0180: * <code>set()</code>, <code>add()</code>, and <code>roll()</code>.</p>
0181: *
0182: * <p><strong><code>set(f, value)</code></strong> changes field
0183: * <code>f</code> to <code>value</code>. In addition, it sets an
0184: * internal member variable to indicate that field <code>f</code> has
0185: * been changed. Although field <code>f</code> is changed immediately,
0186: * the calendar's milliseconds is not recomputed until the next call to
0187: * <code>get()</code>, <code>getTime()</code>, or
0188: * <code>getTimeInMillis()</code> is made. Thus, multiple calls to
0189: * <code>set()</code> do not trigger multiple, unnecessary
0190: * computations. As a result of changing a field using
0191: * <code>set()</code>, other fields may also change, depending on the
0192: * field, the field value, and the calendar system. In addition,
0193: * <code>get(f)</code> will not necessarily return <code>value</code>
0194: * after the fields have been recomputed. The specifics are determined by
0195: * the concrete calendar class.</p>
0196: *
0197: * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
0198: * originally set to August 31, 1999. Calling <code>set(Calendar.MONTH,
0199: * Calendar.SEPTEMBER)</code> sets the calendar to September 31,
0200: * 1999. This is a temporary internal representation that resolves to
0201: * October 1, 1999 if <code>getTime()</code>is then called. However, a
0202: * call to <code>set(Calendar.DAY_OF_MONTH, 30)</code> before the call to
0203: * <code>getTime()</code> sets the calendar to September 30, 1999, since
0204: * no recomputation occurs after <code>set()</code> itself.</p>
0205: *
0206: * <p><strong><code>add(f, delta)</code></strong> adds <code>delta</code>
0207: * to field <code>f</code>. This is equivalent to calling <code>set(f,
0208: * get(f) + delta)</code> with two adjustments:</p>
0209: *
0210: * <blockquote>
0211: * <p><strong>Add rule 1</strong>. The value of field <code>f</code>
0212: * after the call minus the value of field <code>f</code> before the
0213: * call is <code>delta</code>, modulo any overflow that has occurred in
0214: * field <code>f</code>. Overflow occurs when a field value exceeds its
0215: * range and, as a result, the next larger field is incremented or
0216: * decremented and the field value is adjusted back into its range.</p>
0217: *
0218: * <p><strong>Add rule 2</strong>. If a smaller field is expected to be
0219: * invariant, but it is impossible for it to be equal to its
0220: * prior value because of changes in its minimum or maximum after field
0221: * <code>f</code> is changed, then its value is adjusted to be as close
0222: * as possible to its expected value. A smaller field represents a
0223: * smaller unit of time. <code>HOUR</code> is a smaller field than
0224: * <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields
0225: * that are not expected to be invariant. The calendar system
0226: * determines what fields are expected to be invariant.</p>
0227: * </blockquote>
0228: *
0229: * <p>In addition, unlike <code>set()</code>, <code>add()</code> forces
0230: * an immediate recomputation of the calendar's milliseconds and all
0231: * fields.</p>
0232: *
0233: * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
0234: * originally set to August 31, 1999. Calling <code>add(Calendar.MONTH,
0235: * 13)</code> sets the calendar to September 30, 2000. <strong>Add rule
0236: * 1</strong> sets the <code>MONTH</code> field to September, since
0237: * adding 13 months to August gives September of the next year. Since
0238: * <code>DAY_OF_MONTH</code> cannot be 31 in September in a
0239: * <code>GregorianCalendar</code>, <strong>add rule 2</strong> sets the
0240: * <code>DAY_OF_MONTH</code> to 30, the closest possible value. Although
0241: * it is a smaller field, <code>DAY_OF_WEEK</code> is not adjusted by
0242: * rule 2, since it is expected to change when the month changes in a
0243: * <code>GregorianCalendar</code>.</p>
0244: *
0245: * <p><strong><code>roll(f, delta)</code></strong> adds
0246: * <code>delta</code> to field <code>f</code> without changing larger
0247: * fields. This is equivalent to calling <code>add(f, delta)</code> with
0248: * the following adjustment:</p>
0249: *
0250: * <blockquote>
0251: * <p><strong>Roll rule</strong>. Larger fields are unchanged after the
0252: * call. A larger field represents a larger unit of
0253: * time. <code>DAY_OF_MONTH</code> is a larger field than
0254: * <code>HOUR</code>.</p>
0255: * </blockquote>
0256: *
0257: * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
0258: * originally set to August 31, 1999. Calling <code>roll(Calendar.MONTH,
0259: * 8)</code> sets the calendar to April 30, <strong>1999</strong>. Add
0260: * rule 1 sets the <code>MONTH</code> field to April. Using a
0261: * <code>GregorianCalendar</code>, the <code>DAY_OF_MONTH</code> cannot
0262: * be 31 in the month April. Add rule 2 sets it to the closest possible
0263: * value, 30. Finally, the <strong>roll rule</strong> maintains the
0264: * <code>YEAR</code> field value of 1999.</p>
0265: *
0266: * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
0267: * originally set to Sunday June 6, 1999. Calling
0268: * <code>roll(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
0269: * Tuesday June 1, 1999, whereas calling
0270: * <code>add(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
0271: * Sunday May 30, 1999. This is because the roll rule imposes an
0272: * additional constraint: The <code>MONTH</code> must not change when the
0273: * <code>WEEK_OF_MONTH</code> is rolled. Taken together with add rule 1,
0274: * the resultant date must be between Tuesday June 1 and Saturday June
0275: * 5. According to add rule 2, the <code>DAY_OF_WEEK</code>, an invariant
0276: * when changing the <code>WEEK_OF_MONTH</code>, is set to Tuesday, the
0277: * closest possible value to Sunday (where Sunday is the first day of the
0278: * week).</p>
0279: *
0280: * <p><strong>Usage model</strong>. To motivate the behavior of
0281: * <code>add()</code> and <code>roll()</code>, consider a user interface
0282: * component with increment and decrement buttons for the month, day, and
0283: * year, and an underlying <code>GregorianCalendar</code>. If the
0284: * interface reads January 31, 1999 and the user presses the month
0285: * increment button, what should it read? If the underlying
0286: * implementation uses <code>set()</code>, it might read March 3, 1999. A
0287: * better result would be February 28, 1999. Furthermore, if the user
0288: * presses the month increment button again, it should read March 31,
0289: * 1999, not March 28, 1999. By saving the original date and using either
0290: * <code>add()</code> or <code>roll()</code>, depending on whether larger
0291: * fields should be affected, the user interface can behave as most users
0292: * will intuitively expect.</p>
0293: *
0294: * <p><b>Note:</b> You should always use {@link #roll roll} and {@link #add add} rather
0295: * than attempting to perform arithmetic operations directly on the fields
0296: * of a <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses
0297: * to have fields with non-linear behavior, for example missing months
0298: * or days during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt>
0299: * methods will take this into account, while simple arithmetic manipulations
0300: * may give invalid results.
0301: *
0302: * <p><big><big><b>Calendar Architecture in ICU4J</b></big></big></p>
0303: *
0304: * <p>Recently the implementation of <code>Calendar</code> has changed
0305: * significantly in order to better support subclassing. The original
0306: * <code>Calendar</code> class was designed to support subclassing, but
0307: * it had only one implemented subclass, <code>GregorianCalendar</code>.
0308: * With the implementation of several new calendar subclasses, including
0309: * the <code>BuddhistCalendar</code>, <code>ChineseCalendar</code>,
0310: * <code>HebrewCalendar</code>, <code>IslamicCalendar</code>, and
0311: * <code>JapaneseCalendar</code>, the subclassing API has been reworked
0312: * thoroughly. This section details the new subclassing API and other
0313: * ways in which <code>com.ibm.icu.util.Calendar</code> differs from
0314: * <code>java.util.Calendar</code>.
0315: * </p>
0316: *
0317: * <p><big><b>Changes</b></big></p>
0318: *
0319: * <p>Overview of changes between the classic <code>Calendar</code>
0320: * architecture and the new architecture.
0321: *
0322: * <ul>
0323: *
0324: * <li>The <code>fields[]</code> array is <code>private</code> now
0325: * instead of <code>protected</code>. Subclasses must access it
0326: * using the methods {@link #internalSet} and
0327: * {@link #internalGet}. <b>Motivation:</b> Subclasses should
0328: * not directly access data members.</li>
0329: *
0330: * <li>The <code>time</code> long word is <code>private</code> now
0331: * instead of <code>protected</code>. Subclasses may access it using
0332: * the method {@link #internalGetTimeInMillis}, which does not
0333: * provoke an update. <b>Motivation:</b> Subclasses should not
0334: * directly access data members.</li>
0335: *
0336: * <li>The scope of responsibility of subclasses has been drastically
0337: * reduced. As much functionality as possible is implemented in the
0338: * <code>Calendar</code> base class. As a result, it is much easier
0339: * to subclass <code>Calendar</code>. <b>Motivation:</b> Subclasses
0340: * should not have to reimplement common code. Certain behaviors are
0341: * common across calendar systems: The definition and behavior of
0342: * week-related fields and time fields, the arithmetic
0343: * ({@link #add(int, int) add} and {@link #roll(int, int) roll}) behavior of many
0344: * fields, and the field validation system.</li>
0345: *
0346: * <li>The subclassing API has been completely redesigned.</li>
0347: *
0348: * <li>The <code>Calendar</code> base class contains some Gregorian
0349: * calendar algorithmic support that subclasses can use (specifically
0350: * in {@link #handleComputeFields}). Subclasses can use the
0351: * methods <code>getGregorianXxx()</code> to obtain precomputed
0352: * values. <b>Motivation:</b> This is required by all
0353: * <code>Calendar</code> subclasses in order to implement consistent
0354: * time zone behavior, and Gregorian-derived systems can use the
0355: * already computed data.</li>
0356: *
0357: * <li>The <code>FIELD_COUNT</code> constant has been removed. Use
0358: * {@link #getFieldCount}. In addition, framework API has been
0359: * added to allow subclasses to define additional fields.
0360: * <b>Motivation: </b>The number of fields is not constant across
0361: * calendar systems.</li>
0362: *
0363: * <li>The range of handled dates has been narrowed from +/-
0364: * ~300,000,000 years to +/- ~5,000,000 years. In practical terms
0365: * this should not affect clients. However, it does mean that client
0366: * code cannot be guaranteed well-behaved results with dates such as
0367: * <code>Date(Long.MIN_VALUE)</code> or
0368: * <code>Date(Long.MAX_VALUE)</code>. Instead, the
0369: * <code>Calendar</code> constants {@link #MIN_DATE},
0370: * {@link #MAX_DATE}, {@link #MIN_MILLIS},
0371: * {@link #MAX_MILLIS}, {@link #MIN_JULIAN}, and
0372: * {@link #MAX_JULIAN} should be used. <b>Motivation:</b> With
0373: * the addition of the {@link #JULIAN_DAY} field, Julian day
0374: * numbers must be restricted to a 32-bit <code>int</code>. This
0375: * restricts the overall supported range. Furthermore, restricting
0376: * the supported range simplifies the computations by removing
0377: * special case code that was used to accomodate arithmetic overflow
0378: * at millis near <code>Long.MIN_VALUE</code> and
0379: * <code>Long.MAX_VALUE</code>.</li>
0380: *
0381: * <li>New fields are implemented: {@link #JULIAN_DAY} defines
0382: * single-field specification of the
0383: * date. {@link #MILLISECONDS_IN_DAY} defines a single-field
0384: * specification of the wall time. {@link #DOW_LOCAL} and
0385: * {@link #YEAR_WOY} implement localized day-of-week and
0386: * week-of-year behavior.</li>
0387: *
0388: * <li>Subclasses can access millisecond constants
0389: * {@link #ONE_SECOND}, {@link #ONE_MINUTE},
0390: * {@link #ONE_HOUR}, {@link #ONE_DAY}, and
0391: * {@link #ONE_WEEK} defined in <code>Calendar</code>.</li>
0392: *
0393: * <li>New API has been added to suport calendar-specific subclasses
0394: * of <code>DateFormat</code>.</li>
0395: *
0396: * <li>Several subclasses have been implemented, representing
0397: * various international calendar systems.</li>
0398: *
0399: * </ul>
0400: *
0401: * <p><big><b>Subclass API</b></big></p>
0402: *
0403: * <p>The original <code>Calendar</code> API was based on the experience
0404: * of implementing a only a single subclass,
0405: * <code>GregorianCalendar</code>. As a result, all of the subclassing
0406: * kinks had not been worked out. The new subclassing API has been
0407: * refined based on several implemented subclasses. This includes methods
0408: * that must be overridden and methods for subclasses to call. Subclasses
0409: * no longer have direct access to <code>fields</code> and
0410: * <code>stamp</code>. Instead, they have new API to access
0411: * these. Subclasses are able to allocate the <code>fields</code> array
0412: * through a protected framework method; this allows subclasses to
0413: * specify additional fields. </p>
0414: *
0415: * <p>More functionality has been moved into the base class. The base
0416: * class now contains much of the computational machinery to support the
0417: * Gregorian calendar. This is based on two things: (1) Many calendars
0418: * are based on the Gregorian calendar (such as the Buddhist and Japanese
0419: * imperial calendars). (2) <em>All</em> calendars require basic
0420: * Gregorian support in order to handle timezone computations. </p>
0421: *
0422: * <p>Common computations have been moved into
0423: * <code>Calendar</code>. Subclasses no longer compute the week related
0424: * fields and the time related fields. These are commonly handled for all
0425: * calendars by the base class. </p>
0426: *
0427: * <p><b>Subclass computation of time <tt>=></tt> fields</b>
0428: *
0429: * <p>The {@link #ERA}, {@link #YEAR},
0430: * {@link #EXTENDED_YEAR}, {@link #MONTH},
0431: * {@link #DAY_OF_MONTH}, and {@link #DAY_OF_YEAR} fields are
0432: * computed by the subclass, based on the Julian day. All other fields
0433: * are computed by <code>Calendar</code>.
0434: *
0435: * <ul>
0436: *
0437: * <li>Subclasses should implement {@link #handleComputeFields}
0438: * to compute the {@link #ERA}, {@link #YEAR},
0439: * {@link #EXTENDED_YEAR}, {@link #MONTH},
0440: * {@link #DAY_OF_MONTH}, and {@link #DAY_OF_YEAR} fields,
0441: * based on the value of the {@link #JULIAN_DAY} field. If there
0442: * are calendar-specific fields not defined by <code>Calendar</code>,
0443: * they must also be computed. These are the only fields that the
0444: * subclass should compute. All other fields are computed by the base
0445: * class, so time and week fields behave in a consistent way across
0446: * all calendars. The default version of this method in
0447: * <code>Calendar</code> implements a proleptic Gregorian
0448: * calendar. Within this method, subclasses may call
0449: * <code>getGregorianXxx()</code> to obtain the Gregorian calendar
0450: * month, day of month, and extended year for the given date.</li>
0451: *
0452: * </ul>
0453: *
0454: * <p><b>Subclass computation of fields <tt>=></tt> time</b>
0455: *
0456: * <p>The interpretation of most field values is handled entirely by
0457: * <code>Calendar</code>. <code>Calendar</code> determines which fields
0458: * are set, which are not, which are set more recently, and so on. In
0459: * addition, <code>Calendar</code> handles the computation of the time
0460: * from the time fields and handles the week-related fields. The only
0461: * thing the subclass must do is determine the extended year, based on
0462: * the year fields, and then, given an extended year and a month, it must
0463: * return a Julian day number.
0464: *
0465: * <ul>
0466: *
0467: * <li>Subclasses should implement {@link #handleGetExtendedYear}
0468: * to return the extended year for this calendar system, based on the
0469: * {@link #YEAR}, {@link #EXTENDED_YEAR}, and any fields that
0470: * the calendar system uses that are larger than a year, such as
0471: * {@link #ERA}.</li>
0472: *
0473: * <li>Subclasses should implement {@link #handleComputeMonthStart}
0474: * to return the Julian day number
0475: * associated with a month and extended year. This is the Julian day
0476: * number of the day before the first day of the month. The month
0477: * number is zero-based. This computation should not depend on any
0478: * field values.</li>
0479: *
0480: * </ul>
0481: *
0482: * <p><b>Other methods</b>
0483: *
0484: * <ul>
0485: *
0486: * <li>Subclasses should implement {@link #handleGetMonthLength}
0487: * to return the number of days in a
0488: * given month of a given extended year. The month number, as always,
0489: * is zero-based.</li>
0490: *
0491: * <li>Subclasses should implement {@link #handleGetYearLength}
0492: * to return the number of days in the given
0493: * extended year. This method is used by
0494: * <tt>computeWeekFields</tt> to compute the
0495: * {@link #WEEK_OF_YEAR} and {@link #YEAR_WOY} fields.</li>
0496: *
0497: * <li>Subclasses should implement {@link #handleGetLimit}
0498: * to return the {@link #MINIMUM},
0499: * {@link #GREATEST_MINIMUM}, {@link #LEAST_MAXIMUM}, or
0500: * {@link #MAXIMUM} of a field, depending on the value of
0501: * <code>limitType</code>. This method only needs to handle the
0502: * fields {@link #ERA}, {@link #YEAR}, {@link #MONTH},
0503: * {@link #WEEK_OF_YEAR}, {@link #WEEK_OF_MONTH},
0504: * {@link #DAY_OF_MONTH}, {@link #DAY_OF_YEAR},
0505: * {@link #DAY_OF_WEEK_IN_MONTH}, {@link #YEAR_WOY}, and
0506: * {@link #EXTENDED_YEAR}. Other fields are invariant (with
0507: * respect to calendar system) and are handled by the base
0508: * class.</li>
0509: *
0510: * <li>Optionally, subclasses may override {@link #validateField}
0511: * to check any subclass-specific fields. If the
0512: * field's value is out of range, the method should throw an
0513: * <code>IllegalArgumentException</code>. The method may call
0514: * <code>super.validateField(field)</code> to handle fields in a
0515: * generic way, that is, to compare them to the range
0516: * <code>getMinimum(field)</code>..<code>getMaximum(field)</code>.</li>
0517: *
0518: * <li>Optionally, subclasses may override
0519: * {@link #handleCreateFields} to create an <code>int[]</code>
0520: * array large enough to hold the calendar's fields. This is only
0521: * necessary if the calendar defines additional fields beyond those
0522: * defined by <code>Calendar</code>. The length of the result must be
0523: * at least {@link #BASE_FIELD_COUNT} and no more than
0524: * {@link #MAX_FIELD_COUNT}.</li>
0525: *
0526: * <li>Optionally, subclasses may override
0527: * {@link #handleGetDateFormat} to create a
0528: * <code>DateFormat</code> appropriate to this calendar. This is only
0529: * required if a calendar subclass redefines the use of a field (for
0530: * example, changes the {@link #ERA} field from a symbolic field
0531: * to a numeric one) or defines an additional field.</li>
0532: *
0533: * <li>Optionally, subclasses may override {@link #roll roll} and
0534: * {@link #add add} to handle fields that are discontinuous. For
0535: * example, in the Hebrew calendar the month "Adar I" only
0536: * occurs in leap years; in other years the calendar jumps from
0537: * Shevat (month #4) to Adar (month #6). The {@link
0538: * HebrewCalendar#add HebrewCalendar.add} and {@link
0539: * HebrewCalendar#roll HebrewCalendar.roll} methods take this into
0540: * account, so that adding 1 month to Shevat gives the proper result
0541: * (Adar) in a non-leap year. The protected utility method {@link
0542: * #pinField pinField} is often useful when implementing these two
0543: * methods. </li>
0544: *
0545: * </ul>
0546: *
0547: * <p><big><b>Normalized behavior</b></big>
0548: *
0549: * <p>The behavior of certain fields has been made consistent across all
0550: * calendar systems and implemented in <code>Calendar</code>.
0551: *
0552: * <ul>
0553: *
0554: * <li>Time is normalized. Even though some calendar systems transition
0555: * between days at sunset or at other times, all ICU4J calendars
0556: * transition between days at <em>local zone midnight</em>. This
0557: * allows ICU4J to centralize the time computations in
0558: * <code>Calendar</code> and to maintain basic correpsondences
0559: * between calendar systems. Affected fields: {@link #AM_PM},
0560: * {@link #HOUR}, {@link #HOUR_OF_DAY}, {@link #MINUTE},
0561: * {@link #SECOND}, {@link #MILLISECOND},
0562: * {@link #ZONE_OFFSET}, and {@link #DST_OFFSET}.</li>
0563: *
0564: * <li>DST behavior is normalized. Daylight savings time behavior is
0565: * computed the same for all calendar systems, and depends on the
0566: * value of several <code>GregorianCalendar</code> fields: the
0567: * {@link #YEAR}, {@link #MONTH}, and
0568: * {@link #DAY_OF_MONTH}. As a result, <code>Calendar</code>
0569: * always computes these fields, even for non-Gregorian calendar
0570: * systems. These fields are available to subclasses.</li>
0571: *
0572: * <li>Weeks are normalized. Although locales define the week
0573: * differently, in terms of the day on which it starts, and the
0574: * designation of week number one of a month or year, they all use a
0575: * common mechanism. Furthermore, the day of the week has a simple
0576: * and consistent definition throughout history. For example,
0577: * although the Gregorian calendar introduced a discontinuity when
0578: * first instituted, the day of week was not disrupted. For this
0579: * reason, the fields {@link #DAY_OF_WEEK}, <code>WEEK_OF_YEAR,
0580: * WEEK_OF_MONTH</code>, {@link #DAY_OF_WEEK_IN_MONTH},
0581: * {@link #DOW_LOCAL}, {@link #YEAR_WOY} are all computed in
0582: * a consistent way in the base class, based on the
0583: * {@link #EXTENDED_YEAR}, {@link #DAY_OF_YEAR},
0584: * {@link #MONTH}, and {@link #DAY_OF_MONTH}, which are
0585: * computed by the subclass.</li>
0586: *
0587: * </ul>
0588: *
0589: * <p><big><b>Supported range</b></big>
0590: *
0591: * <p>The allowable range of <code>Calendar</code> has been
0592: * narrowed. <code>GregorianCalendar</code> used to attempt to support
0593: * the range of dates with millisecond values from
0594: * <code>Long.MIN_VALUE</code> to <code>Long.MAX_VALUE</code>. This
0595: * introduced awkward constructions (hacks) which slowed down
0596: * performance. It also introduced non-uniform behavior at the
0597: * boundaries. The new <code>Calendar</code> protocol specifies the
0598: * maximum range of supportable dates as those having Julian day numbers
0599: * of <code>-0x7F000000</code> to <code>+0x7F000000</code>. This
0600: * corresponds to years from ~5,000,000 BCE to ~5,000,000 CE. Programmers
0601: * should use the constants {@link #MIN_DATE} (or
0602: * {@link #MIN_MILLIS} or {@link #MIN_JULIAN}) and
0603: * {@link #MAX_DATE} (or {@link #MAX_MILLIS} or
0604: * {@link #MAX_JULIAN}) in <code>Calendar</code> to specify an
0605: * extremely early or extremely late date.</p>
0606: *
0607: * <p><big><b>General notes</b></big>
0608: *
0609: * <ul>
0610: *
0611: * <li>Calendars implementations are <em>proleptic</em>. For example,
0612: * even though the Gregorian calendar was not instituted until the
0613: * 16th century, the <code>GregorianCalendar</code> class supports
0614: * dates before the historical onset of the calendar by extending the
0615: * calendar system backward in time. Similarly, the
0616: * <code>HebrewCalendar</code> extends backward before the start of
0617: * its epoch into zero and negative years. Subclasses do not throw
0618: * exceptions because a date precedes the historical start of a
0619: * calendar system. Instead, they implement
0620: * {@link #handleGetLimit} to return appropriate limits on
0621: * {@link #YEAR}, {@link #ERA}, etc. fields. Then, if the
0622: * calendar is set to not be lenient, out-of-range field values will
0623: * trigger an exception.</li>
0624: *
0625: * <li>Calendar system subclasses compute a <em>extended
0626: * year</em>. This differs from the {@link #YEAR} field in that
0627: * it ranges over all integer values, including zero and negative
0628: * values, and it encapsulates the information of the
0629: * {@link #YEAR} field and all larger fields. Thus, for the
0630: * Gregorian calendar, the {@link #EXTENDED_YEAR} is computed as
0631: * <code>ERA==AD ? YEAR : 1-YEAR</code>. Another example is the Mayan
0632: * long count, which has years (<code>KUN</code>) and nested cycles
0633: * of years (<code>KATUN</code> and <code>BAKTUN</code>). The Mayan
0634: * {@link #EXTENDED_YEAR} is computed as <code>TUN + 20 * (KATUN
0635: * + 20 * BAKTUN)</code>. The <code>Calendar</code> base class uses
0636: * the {@link #EXTENDED_YEAR} field to compute the week-related
0637: * fields.</li>
0638: *
0639: * </ul>
0640: *
0641: * @see Date
0642: * @see GregorianCalendar
0643: * @see TimeZone
0644: * @see DateFormat
0645: * @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu, Laura Werner
0646: * @stable ICU 2.0
0647: */
0648: public abstract class Calendar implements Serializable, Cloneable,
0649: Comparable {
0650:
0651: // Data flow in Calendar
0652: // ---------------------
0653:
0654: // The current time is represented in two ways by Calendar: as UTC
0655: // milliseconds from the epoch start (1 January 1970 0:00 UTC), and as local
0656: // fields such as MONTH, HOUR, AM_PM, etc. It is possible to compute the
0657: // millis from the fields, and vice versa. The data needed to do this
0658: // conversion is encapsulated by a TimeZone object owned by the Calendar.
0659: // The data provided by the TimeZone object may also be overridden if the
0660: // user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class
0661: // keeps track of what information was most recently set by the caller, and
0662: // uses that to compute any other information as needed.
0663:
0664: // If the user sets the fields using set(), the data flow is as follows.
0665: // This is implemented by the Calendar subclass's computeTime() method.
0666: // During this process, certain fields may be ignored. The disambiguation
0667: // algorithm for resolving which fields to pay attention to is described
0668: // above.
0669:
0670: // local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
0671: // |
0672: // | Using Calendar-specific algorithm
0673: // V
0674: // local standard millis
0675: // |
0676: // | Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET
0677: // V
0678: // UTC millis (in time data member)
0679:
0680: // If the user sets the UTC millis using setTime(), the data flow is as
0681: // follows. This is implemented by the Calendar subclass's computeFields()
0682: // method.
0683:
0684: // UTC millis (in time data member)
0685: // |
0686: // | Using TimeZone getOffset()
0687: // V
0688: // local standard millis
0689: // |
0690: // | Using Calendar-specific algorithm
0691: // V
0692: // local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
0693:
0694: // In general, a round trip from fields, through local and UTC millis, and
0695: // back out to fields is made when necessary. This is implemented by the
0696: // complete() method. Resolving a partial set of fields into a UTC millis
0697: // value allows all remaining fields to be generated from that value. If
0698: // the Calendar is lenient, the fields are also renormalized to standard
0699: // ranges when they are regenerated.
0700:
0701: /**
0702: * Field number for <code>get</code> and <code>set</code> indicating the
0703: * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific
0704: * value; see subclass documentation.
0705: * @see GregorianCalendar#AD
0706: * @see GregorianCalendar#BC
0707: * @stable ICU 2.0
0708: */
0709: public final static int ERA = 0;
0710:
0711: /**
0712: * Field number for <code>get</code> and <code>set</code> indicating the
0713: * year. This is a calendar-specific value; see subclass documentation.
0714: * @stable ICU 2.0
0715: */
0716: public final static int YEAR = 1;
0717:
0718: /**
0719: * Field number for <code>get</code> and <code>set</code> indicating the
0720: * month. This is a calendar-specific value. The first month of the year is
0721: * <code>JANUARY</code>; the last depends on the number of months in a year.
0722: * @see #JANUARY
0723: * @see #FEBRUARY
0724: * @see #MARCH
0725: * @see #APRIL
0726: * @see #MAY
0727: * @see #JUNE
0728: * @see #JULY
0729: * @see #AUGUST
0730: * @see #SEPTEMBER
0731: * @see #OCTOBER
0732: * @see #NOVEMBER
0733: * @see #DECEMBER
0734: * @see #UNDECIMBER
0735: * @stable ICU 2.0
0736: */
0737: public final static int MONTH = 2;
0738:
0739: /**
0740: * Field number for <code>get</code> and <code>set</code> indicating the
0741: * week number within the current year. The first week of the year, as
0742: * defined by <code>getFirstDayOfWeek()</code> and
0743: * <code>getMinimalDaysInFirstWeek()</code>, has value 1. Subclasses define
0744: * the value of <code>WEEK_OF_YEAR</code> for days before the first week of
0745: * the year.
0746: * @see #getFirstDayOfWeek
0747: * @see #getMinimalDaysInFirstWeek
0748: * @stable ICU 2.0
0749: */
0750: public final static int WEEK_OF_YEAR = 3;
0751:
0752: /**
0753: * Field number for <code>get</code> and <code>set</code> indicating the
0754: * week number within the current month. The first week of the month, as
0755: * defined by <code>getFirstDayOfWeek()</code> and
0756: * <code>getMinimalDaysInFirstWeek()</code>, has value 1. Subclasses define
0757: * the value of <code>WEEK_OF_MONTH</code> for days before the first week of
0758: * the month.
0759: * @see #getFirstDayOfWeek
0760: * @see #getMinimalDaysInFirstWeek
0761: * @stable ICU 2.0
0762: */
0763: public final static int WEEK_OF_MONTH = 4;
0764:
0765: /**
0766: * Field number for <code>get</code> and <code>set</code> indicating the
0767: * day of the month. This is a synonym for <code>DAY_OF_MONTH</code>.
0768: * The first day of the month has value 1.
0769: * @see #DAY_OF_MONTH
0770: * @stable ICU 2.0
0771: */
0772: public final static int DATE = 5;
0773:
0774: /**
0775: * Field number for <code>get</code> and <code>set</code> indicating the
0776: * day of the month. This is a synonym for <code>DATE</code>.
0777: * The first day of the month has value 1.
0778: * @see #DATE
0779: * @stable ICU 2.0
0780: */
0781: public final static int DAY_OF_MONTH = 5;
0782:
0783: /**
0784: * Field number for <code>get</code> and <code>set</code> indicating the day
0785: * number within the current year. The first day of the year has value 1.
0786: * @stable ICU 2.0
0787: */
0788: public final static int DAY_OF_YEAR = 6;
0789:
0790: /**
0791: * Field number for <code>get</code> and <code>set</code> indicating the day
0792: * of the week. This field takes values <code>SUNDAY</code>,
0793: * <code>MONDAY</code>, <code>TUESDAY</code>, <code>WEDNESDAY</code>,
0794: * <code>THURSDAY</code>, <code>FRIDAY</code>, and <code>SATURDAY</code>.
0795: * @see #SUNDAY
0796: * @see #MONDAY
0797: * @see #TUESDAY
0798: * @see #WEDNESDAY
0799: * @see #THURSDAY
0800: * @see #FRIDAY
0801: * @see #SATURDAY
0802: * @stable ICU 2.0
0803: */
0804: public final static int DAY_OF_WEEK = 7;
0805:
0806: /**
0807: * Field number for <code>get</code> and <code>set</code> indicating the
0808: * ordinal number of the day of the week within the current month. Together
0809: * with the <code>DAY_OF_WEEK</code> field, this uniquely specifies a day
0810: * within a month. Unlike <code>WEEK_OF_MONTH</code> and
0811: * <code>WEEK_OF_YEAR</code>, this field's value does <em>not</em> depend on
0812: * <code>getFirstDayOfWeek()</code> or
0813: * <code>getMinimalDaysInFirstWeek()</code>. <code>DAY_OF_MONTH 1</code>
0814: * through <code>7</code> always correspond to <code>DAY_OF_WEEK_IN_MONTH
0815: * 1</code>; <code>8</code> through <code>15</code> correspond to
0816: * <code>DAY_OF_WEEK_IN_MONTH 2</code>, and so on.
0817: * <code>DAY_OF_WEEK_IN_MONTH 0</code> indicates the week before
0818: * <code>DAY_OF_WEEK_IN_MONTH 1</code>. Negative values count back from the
0819: * end of the month, so the last Sunday of a month is specified as
0820: * <code>DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1</code>. Because
0821: * negative values count backward they will usually be aligned differently
0822: * within the month than positive values. For example, if a month has 31
0823: * days, <code>DAY_OF_WEEK_IN_MONTH -1</code> will overlap
0824: * <code>DAY_OF_WEEK_IN_MONTH 5</code> and the end of <code>4</code>.
0825: * @see #DAY_OF_WEEK
0826: * @see #WEEK_OF_MONTH
0827: * @stable ICU 2.0
0828: */
0829: public final static int DAY_OF_WEEK_IN_MONTH = 8;
0830:
0831: /**
0832: * Field number for <code>get</code> and <code>set</code> indicating
0833: * whether the <code>HOUR</code> is before or after noon.
0834: * E.g., at 10:04:15.250 PM the <code>AM_PM</code> is <code>PM</code>.
0835: * @see #AM
0836: * @see #PM
0837: * @see #HOUR
0838: * @stable ICU 2.0
0839: */
0840: public final static int AM_PM = 9;
0841:
0842: /**
0843: * Field number for <code>get</code> and <code>set</code> indicating the
0844: * hour of the morning or afternoon. <code>HOUR</code> is used for the 12-hour
0845: * clock.
0846: * E.g., at 10:04:15.250 PM the <code>HOUR</code> is 10.
0847: * @see #AM_PM
0848: * @see #HOUR_OF_DAY
0849: * @stable ICU 2.0
0850: */
0851: public final static int HOUR = 10;
0852:
0853: /**
0854: * Field number for <code>get</code> and <code>set</code> indicating the
0855: * hour of the day. <code>HOUR_OF_DAY</code> is used for the 24-hour clock.
0856: * E.g., at 10:04:15.250 PM the <code>HOUR_OF_DAY</code> is 22.
0857: * @see #HOUR
0858: * @stable ICU 2.0
0859: */
0860: public final static int HOUR_OF_DAY = 11;
0861:
0862: /**
0863: * Field number for <code>get</code> and <code>set</code> indicating the
0864: * minute within the hour.
0865: * E.g., at 10:04:15.250 PM the <code>MINUTE</code> is 4.
0866: * @stable ICU 2.0
0867: */
0868: public final static int MINUTE = 12;
0869:
0870: /**
0871: * Field number for <code>get</code> and <code>set</code> indicating the
0872: * second within the minute.
0873: * E.g., at 10:04:15.250 PM the <code>SECOND</code> is 15.
0874: * @stable ICU 2.0
0875: */
0876: public final static int SECOND = 13;
0877:
0878: /**
0879: * Field number for <code>get</code> and <code>set</code> indicating the
0880: * millisecond within the second.
0881: * E.g., at 10:04:15.250 PM the <code>MILLISECOND</code> is 250.
0882: * @stable ICU 2.0
0883: */
0884: public final static int MILLISECOND = 14;
0885:
0886: /**
0887: * Field number for <code>get</code> and <code>set</code> indicating the
0888: * raw offset from GMT in milliseconds.
0889: * @stable ICU 2.0
0890: */
0891: public final static int ZONE_OFFSET = 15;
0892:
0893: /**
0894: * Field number for <code>get</code> and <code>set</code> indicating the
0895: * daylight savings offset in milliseconds.
0896: * @stable ICU 2.0
0897: */
0898: public final static int DST_OFFSET = 16;
0899:
0900: /**
0901: * Field number for <code>get()</code> and <code>set()</code>
0902: * indicating the extended year corresponding to the
0903: * <code>WEEK_OF_YEAR</code> field. This may be one greater or less
0904: * than the value of <code>EXTENDED_YEAR</code>.
0905: * @stable ICU 2.0
0906: */
0907: public static final int YEAR_WOY = 17;
0908:
0909: /**
0910: * Field number for <code>get()</code> and <code>set()</code>
0911: * indicating the localized day of week. This will be a value from 1
0912: * to 7 inclusive, with 1 being the localized first day of the week.
0913: * @stable ICU 2.0
0914: */
0915: public static final int DOW_LOCAL = 18;
0916:
0917: /**
0918: * Field number for <code>get()</code> and <code>set()</code>
0919: * indicating the extended year. This is a single number designating
0920: * the year of this calendar system, encompassing all supra-year
0921: * fields. For example, for the Julian calendar system, year numbers
0922: * are positive, with an era of BCE or CE. An extended year value for
0923: * the Julian calendar system assigns positive values to CE years and
0924: * negative values to BCE years, with 1 BCE being year 0.
0925: * @stable ICU 2.0
0926: */
0927: public static final int EXTENDED_YEAR = 19;
0928:
0929: /**
0930: * Field number for <code>get()</code> and <code>set()</code>
0931: * indicating the modified Julian day number. This is different from
0932: * the conventional Julian day number in two regards. First, it
0933: * demarcates days at local zone midnight, rather than noon GMT.
0934: * Second, it is a local number; that is, it depends on the local time
0935: * zone. It can be thought of as a single number that encompasses all
0936: * the date-related fields.
0937: * @stable ICU 2.0
0938: */
0939: public static final int JULIAN_DAY = 20;
0940:
0941: /**
0942: * Field number for <code>get()</code> and <code>set()</code>
0943: * indicating the milliseconds in the day. This ranges from 0 to
0944: * 23:59:59.999 (regardless of DST). This field behaves
0945: * <em>exactly</em> like a composite of all time-related fields, not
0946: * including the zone fields. As such, it also reflects
0947: * discontinuities of those fields on DST transition days. On a day of
0948: * DST onset, it will jump forward. On a day of DST cessation, it will
0949: * jump backward. This reflects the fact that is must be combined with
0950: * the DST_OFFSET field to obtain a unique local time value.
0951: * @stable ICU 2.0
0952: */
0953: public static final int MILLISECONDS_IN_DAY = 21;
0954:
0955: /**
0956: * The number of fields defined by this class. Subclasses may define
0957: * addition fields starting with this number.
0958: * @stable ICU 2.0
0959: */
0960: protected static final int BASE_FIELD_COUNT = 22;
0961:
0962: /**
0963: * The maximum number of fields possible. Subclasses must not define
0964: * more total fields than this number.
0965: * @stable ICU 2.0
0966: */
0967: protected static final int MAX_FIELD_COUNT = 32;
0968:
0969: /**
0970: * Value of the <code>DAY_OF_WEEK</code> field indicating
0971: * Sunday.
0972: * @stable ICU 2.0
0973: */
0974: public final static int SUNDAY = 1;
0975:
0976: /**
0977: * Value of the <code>DAY_OF_WEEK</code> field indicating
0978: * Monday.
0979: * @stable ICU 2.0
0980: */
0981: public final static int MONDAY = 2;
0982:
0983: /**
0984: * Value of the <code>DAY_OF_WEEK</code> field indicating
0985: * Tuesday.
0986: * @stable ICU 2.0
0987: */
0988: public final static int TUESDAY = 3;
0989:
0990: /**
0991: * Value of the <code>DAY_OF_WEEK</code> field indicating
0992: * Wednesday.
0993: * @stable ICU 2.0
0994: */
0995: public final static int WEDNESDAY = 4;
0996:
0997: /**
0998: * Value of the <code>DAY_OF_WEEK</code> field indicating
0999: * Thursday.
1000: * @stable ICU 2.0
1001: */
1002: public final static int THURSDAY = 5;
1003:
1004: /**
1005: * Value of the <code>DAY_OF_WEEK</code> field indicating
1006: * Friday.
1007: * @stable ICU 2.0
1008: */
1009: public final static int FRIDAY = 6;
1010:
1011: /**
1012: * Value of the <code>DAY_OF_WEEK</code> field indicating
1013: * Saturday.
1014: * @stable ICU 2.0
1015: */
1016: public final static int SATURDAY = 7;
1017:
1018: /**
1019: * Value of the <code>MONTH</code> field indicating the
1020: * first month of the year.
1021: * @stable ICU 2.0
1022: */
1023: public final static int JANUARY = 0;
1024:
1025: /**
1026: * Value of the <code>MONTH</code> field indicating the
1027: * second month of the year.
1028: * @stable ICU 2.0
1029: */
1030: public final static int FEBRUARY = 1;
1031:
1032: /**
1033: * Value of the <code>MONTH</code> field indicating the
1034: * third month of the year.
1035: * @stable ICU 2.0
1036: */
1037: public final static int MARCH = 2;
1038:
1039: /**
1040: * Value of the <code>MONTH</code> field indicating the
1041: * fourth month of the year.
1042: * @stable ICU 2.0
1043: */
1044: public final static int APRIL = 3;
1045:
1046: /**
1047: * Value of the <code>MONTH</code> field indicating the
1048: * fifth month of the year.
1049: * @stable ICU 2.0
1050: */
1051: public final static int MAY = 4;
1052:
1053: /**
1054: * Value of the <code>MONTH</code> field indicating the
1055: * sixth month of the year.
1056: * @stable ICU 2.0
1057: */
1058: public final static int JUNE = 5;
1059:
1060: /**
1061: * Value of the <code>MONTH</code> field indicating the
1062: * seventh month of the year.
1063: * @stable ICU 2.0
1064: */
1065: public final static int JULY = 6;
1066:
1067: /**
1068: * Value of the <code>MONTH</code> field indicating the
1069: * eighth month of the year.
1070: * @stable ICU 2.0
1071: */
1072: public final static int AUGUST = 7;
1073:
1074: /**
1075: * Value of the <code>MONTH</code> field indicating the
1076: * ninth month of the year.
1077: * @stable ICU 2.0
1078: */
1079: public final static int SEPTEMBER = 8;
1080:
1081: /**
1082: * Value of the <code>MONTH</code> field indicating the
1083: * tenth month of the year.
1084: * @stable ICU 2.0
1085: */
1086: public final static int OCTOBER = 9;
1087:
1088: /**
1089: * Value of the <code>MONTH</code> field indicating the
1090: * eleventh month of the year.
1091: * @stable ICU 2.0
1092: */
1093: public final static int NOVEMBER = 10;
1094:
1095: /**
1096: * Value of the <code>MONTH</code> field indicating the
1097: * twelfth month of the year.
1098: * @stable ICU 2.0
1099: */
1100: public final static int DECEMBER = 11;
1101:
1102: /**
1103: * Value of the <code>MONTH</code> field indicating the
1104: * thirteenth month of the year. Although <code>GregorianCalendar</code>
1105: * does not use this value, lunar calendars do.
1106: * @stable ICU 2.0
1107: */
1108: public final static int UNDECIMBER = 12;
1109:
1110: /**
1111: * Value of the <code>AM_PM</code> field indicating the
1112: * period of the day from midnight to just before noon.
1113: * @stable ICU 2.0
1114: */
1115: public final static int AM = 0;
1116:
1117: /**
1118: * Value of the <code>AM_PM</code> field indicating the
1119: * period of the day from noon to just before midnight.
1120: * @stable ICU 2.0
1121: */
1122: public final static int PM = 1;
1123:
1124: /**
1125: * Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
1126: * weekday.
1127: * @see #WEEKEND
1128: * @see #WEEKEND_ONSET
1129: * @see #WEEKEND_CEASE
1130: * @see #getDayOfWeekType
1131: * @stable ICU 2.0
1132: */
1133: public static final int WEEKDAY = 0;
1134:
1135: /**
1136: * Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
1137: * weekend day.
1138: * @see #WEEKDAY
1139: * @see #WEEKEND_ONSET
1140: * @see #WEEKEND_CEASE
1141: * @see #getDayOfWeekType
1142: * @stable ICU 2.0
1143: */
1144: public static final int WEEKEND = 1;
1145:
1146: /**
1147: * Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
1148: * day that starts as a weekday and transitions to the weekend.
1149: * Call getWeekendTransition() to get the point of transition.
1150: * @see #WEEKDAY
1151: * @see #WEEKEND
1152: * @see #WEEKEND_CEASE
1153: * @see #getDayOfWeekType
1154: * @stable ICU 2.0
1155: */
1156: public static final int WEEKEND_ONSET = 2;
1157:
1158: /**
1159: * Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
1160: * day that starts as the weekend and transitions to a weekday.
1161: * Call getWeekendTransition() to get the point of transition.
1162: * @see #WEEKDAY
1163: * @see #WEEKEND
1164: * @see #WEEKEND_ONSET
1165: * @see #getDayOfWeekType
1166: * @stable ICU 2.0
1167: */
1168: public static final int WEEKEND_CEASE = 3;
1169:
1170: /**
1171: * The number of milliseconds in one second.
1172: * @stable ICU 2.0
1173: */
1174: protected static final int ONE_SECOND = 1000;
1175:
1176: /**
1177: * The number of milliseconds in one minute.
1178: * @stable ICU 2.0
1179: */
1180: protected static final int ONE_MINUTE = 60 * ONE_SECOND;
1181:
1182: /**
1183: * The number of milliseconds in one hour.
1184: * @stable ICU 2.0
1185: */
1186: protected static final int ONE_HOUR = 60 * ONE_MINUTE;
1187:
1188: /**
1189: * The number of milliseconds in one day. Although ONE_DAY and
1190: * ONE_WEEK can fit into ints, they must be longs in order to prevent
1191: * arithmetic overflow when performing (bug 4173516).
1192: * @stable ICU 2.0
1193: */
1194: protected static final long ONE_DAY = 24 * ONE_HOUR;
1195:
1196: /**
1197: * The number of milliseconds in one week. Although ONE_DAY and
1198: * ONE_WEEK can fit into ints, they must be longs in order to prevent
1199: * arithmetic overflow when performing (bug 4173516).
1200: * @stable ICU 2.0
1201: */
1202: protected static final long ONE_WEEK = 7 * ONE_DAY;
1203:
1204: /**
1205: * The Julian day of the Gregorian epoch, that is, January 1, 1 on the
1206: * Gregorian calendar.
1207: * @stable ICU 2.0
1208: */
1209: protected static final int JAN_1_1_JULIAN_DAY = 1721426;
1210:
1211: /**
1212: * The Julian day of the epoch, that is, January 1, 1970 on the
1213: * Gregorian calendar.
1214: * @stable ICU 2.0
1215: */
1216: protected static final int EPOCH_JULIAN_DAY = 2440588;
1217:
1218: /**
1219: * The minimum supported Julian day. This value is equivalent to
1220: * <code>MIN_MILLIS</code> and <code>MIN_DATE</code>.
1221: * @see #JULIAN_DAY
1222: * @stable ICU 2.0
1223: */
1224: protected static final int MIN_JULIAN = -0x7F000000;
1225:
1226: /**
1227: * The minimum supported epoch milliseconds. This value is equivalent
1228: * to <code>MIN_JULIAN</code> and <code>MIN_DATE</code>.
1229: * @stable ICU 2.0
1230: */
1231: protected static final long MIN_MILLIS = -184303902528000000L;
1232:
1233: // Get around bug in jikes 1.12 for now. Later, use:
1234: //protected static final long MIN_MILLIS = (MIN_JULIAN - EPOCH_JULIAN_DAY) * ONE_DAY;
1235:
1236: /**
1237: * The minimum supported <code>Date</code>. This value is equivalent
1238: * to <code>MIN_JULIAN</code> and <code>MIN_MILLIS</code>.
1239: * @stable ICU 2.0
1240: */
1241: protected static final Date MIN_DATE = new Date(MIN_MILLIS);
1242:
1243: /**
1244: * The maximum supported Julian day. This value is equivalent to
1245: * <code>MAX_MILLIS</code> and <code>MAX_DATE</code>.
1246: * @see #JULIAN_DAY
1247: * @stable ICU 2.0
1248: */
1249: protected static final int MAX_JULIAN = +0x7F000000;
1250:
1251: /**
1252: * The maximum supported epoch milliseconds. This value is equivalent
1253: * to <code>MAX_JULIAN</code> and <code>MAX_DATE</code>.
1254: * @stable ICU 2.0
1255: */
1256: protected static final long MAX_MILLIS = (MAX_JULIAN - EPOCH_JULIAN_DAY)
1257: * ONE_DAY;
1258:
1259: /**
1260: * The maximum supported <code>Date</code>. This value is equivalent
1261: * to <code>MAX_JULIAN</code> and <code>MAX_MILLIS</code>.
1262: * @stable ICU 2.0
1263: */
1264: protected static final Date MAX_DATE = new Date(MAX_MILLIS);
1265:
1266: // Internal notes:
1267: // Calendar contains two kinds of time representations: current "time" in
1268: // milliseconds, and a set of time "fields" representing the current time.
1269: // The two representations are usually in sync, but can get out of sync
1270: // as follows.
1271: // 1. Initially, no fields are set, and the time is invalid.
1272: // 2. If the time is set, all fields are computed and in sync.
1273: // 3. If a single field is set, the time is invalid.
1274: // Recomputation of the time and fields happens when the object needs
1275: // to return a result to the user, or use a result for a computation.
1276:
1277: /**
1278: * The field values for the currently set time for this calendar.
1279: * This is an array of at least <code>BASE_FIELD_COUNT</code> integers.
1280: * @see #handleCreateFields
1281: * @serial
1282: */
1283: private transient int fields[];
1284:
1285: /**
1286: * Pseudo-time-stamps which specify when each field was set. There
1287: * are two special values, UNSET and INTERNALLY_SET. Values from
1288: * MINIMUM_USER_SET to Integer.MAX_VALUE are legal user set values.
1289: */
1290: private transient int stamp[];
1291:
1292: /**
1293: * The currently set time for this calendar, expressed in milliseconds after
1294: * January 1, 1970, 0:00:00 GMT.
1295: * @see <tt>isTimeSet</tt>
1296: * @serial
1297: */
1298: private long time;
1299:
1300: /**
1301: * True if then the value of <code>time</code> is valid.
1302: * The time is made invalid by a change to an item of <code>field[]</code>.
1303: * @see #time
1304: * @serial
1305: */
1306: private transient boolean isTimeSet;
1307:
1308: /**
1309: * True if <code>fields[]</code> are in sync with the currently set time.
1310: * If false, then the next attempt to get the value of a field will
1311: * force a recomputation of all fields from the current value of
1312: * <code>time</code>.
1313: * @serial
1314: */
1315: private transient boolean areFieldsSet;
1316:
1317: /**
1318: * True if all fields have been set. This is only false in a few
1319: * situations: In a newly created, partially constructed object. After
1320: * a call to clear(). In an object just read from a stream using
1321: * readObject(). Once computeFields() has been called this is set to
1322: * true and stays true until one of the above situations recurs.
1323: * @serial
1324: */
1325: private transient boolean areAllFieldsSet;
1326:
1327: /**
1328: * True if all fields have been virtually set, but have not yet been
1329: * computed. This occurs only in setTimeInMillis(). A calendar set
1330: * to this state will compute all fields from the time if it becomes
1331: * necessary, but otherwise will delay such computation.
1332: */
1333: private transient boolean areFieldsVirtuallySet;
1334:
1335: /**
1336: * True if this calendar allows out-of-range field values during computation
1337: * of <code>time</code> from <code>fields[]</code>.
1338: * @see #setLenient
1339: * @serial
1340: */
1341: private boolean lenient = true;
1342:
1343: /**
1344: * The <code>TimeZone</code> used by this calendar. </code>Calendar</code>
1345: * uses the time zone data to translate between locale and GMT time.
1346: * @serial
1347: */
1348: private TimeZone zone;
1349:
1350: /**
1351: * The first day of the week, with possible values <code>SUNDAY</code>,
1352: * <code>MONDAY</code>, etc. This is a locale-dependent value.
1353: * @serial
1354: */
1355: private int firstDayOfWeek;
1356:
1357: /**
1358: * The number of days required for the first week in a month or year,
1359: * with possible values from 1 to 7. This is a locale-dependent value.
1360: * @serial
1361: */
1362: private int minimalDaysInFirstWeek;
1363:
1364: /**
1365: * First day of the weekend in this calendar's locale. Must be in
1366: * the range SUNDAY...SATURDAY (1..7). The weekend starts at
1367: * weekendOnsetMillis milliseconds after midnight on that day of
1368: * the week. This value is taken from locale resource data.
1369: */
1370: private int weekendOnset;
1371:
1372: /**
1373: * Milliseconds after midnight at which the weekend starts on the
1374: * day of the week weekendOnset. Times that are greater than or
1375: * equal to weekendOnsetMillis are considered part of the weekend.
1376: * Must be in the range 0..24*60*60*1000-1. This value is taken
1377: * from locale resource data.
1378: */
1379: private int weekendOnsetMillis;
1380:
1381: /**
1382: * Day of the week when the weekend stops in this calendar's
1383: * locale. Must be in the range SUNDAY...SATURDAY (1..7). The
1384: * weekend stops at weekendCeaseMillis milliseconds after midnight
1385: * on that day of the week. This value is taken from locale
1386: * resource data.
1387: */
1388: private int weekendCease;
1389:
1390: /**
1391: * Milliseconds after midnight at which the weekend stops on the
1392: * day of the week weekendCease. Times that are greater than or
1393: * equal to weekendCeaseMillis are considered not to be the
1394: * weekend. Must be in the range 0..24*60*60*1000-1. This value
1395: * is taken from locale resource data.
1396: */
1397: private int weekendCeaseMillis;
1398:
1399: /**
1400: * Cache to hold the firstDayOfWeek and minimalDaysInFirstWeek
1401: * of a Locale.
1402: */
1403: private static Hashtable cachedLocaleData = new Hashtable(3);
1404:
1405: /**
1406: * Value of the time stamp <code>stamp[]</code> indicating that
1407: * a field has not been set since the last call to <code>clear()</code>.
1408: * @see #INTERNALLY_SET
1409: * @see #MINIMUM_USER_STAMP
1410: * @stable ICU 2.0
1411: */
1412: protected static final int UNSET = 0;
1413:
1414: /**
1415: * Value of the time stamp <code>stamp[]</code> indicating that a field
1416: * has been set via computations from the time or from other fields.
1417: * @see #UNSET
1418: * @see #MINIMUM_USER_STAMP
1419: * @stable ICU 2.0
1420: */
1421: protected static final int INTERNALLY_SET = 1;
1422:
1423: /**
1424: * If the time stamp <code>stamp[]</code> has a value greater than or
1425: * equal to <code>MINIMUM_USER_SET</code> then it has been set by the
1426: * user via a call to <code>set()</code>.
1427: * @see #UNSET
1428: * @see #INTERNALLY_SET
1429: * @stable ICU 2.0
1430: */
1431: protected static final int MINIMUM_USER_STAMP = 2;
1432:
1433: /**
1434: * The next available value for <code>stamp[]</code>, an internal array.
1435: * This actually should not be written out to the stream, and will probably
1436: * be removed from the stream in the near future. In the meantime,
1437: * a value of <code>MINIMUM_USER_STAMP</code> should be used.
1438: * @serial
1439: */
1440: private transient int nextStamp = MINIMUM_USER_STAMP;
1441:
1442: // the internal serial version which says which version was written
1443: // - 0 (default) for version up to JDK 1.1.5
1444: // - 1 for version from JDK 1.1.6, which writes a correct 'time' value
1445: // as well as compatible values for other fields. This is a
1446: // transitional format.
1447: // - 2 (not implemented yet) a future version, in which fields[],
1448: // areFieldsSet, and isTimeSet become transient, and isSet[] is
1449: // removed. In JDK 1.1.6 we write a format compatible with version 2.
1450: // static final int currentSerialVersion = 1;
1451:
1452: /**
1453: * The version of the serialized data on the stream. Possible values:
1454: * <dl>
1455: * <dt><b>0</b> or not present on stream</dt>
1456: * <dd>
1457: * JDK 1.1.5 or earlier.
1458: * </dd>
1459: * <dt><b>1</b></dt>
1460: * <dd>
1461: * JDK 1.1.6 or later. Writes a correct 'time' value
1462: * as well as compatible values for other fields. This is a
1463: * transitional format.
1464: * </dd>
1465: * </dl>
1466: * When streaming out this class, the most recent format
1467: * and the highest allowable <code>serialVersionOnStream</code>
1468: * is written.
1469: * @serial
1470: * @since JDK1.1.6
1471: */
1472: // private int serialVersionOnStream = currentSerialVersion;
1473: // Proclaim serialization compatibility with JDK 1.1
1474: // static final long serialVersionUID = -1807547505821590642L;
1475: // haven't been compatible for awhile, no longer try
1476: // jdk1.4.2 serialver
1477: private static final long serialVersionUID = 6222646104888790989L;
1478:
1479: /**
1480: * Bitmask for internalSet() defining which fields may legally be set
1481: * by subclasses. Any attempt to set a field not in this bitmask
1482: * results in an exception, because such fields must be set by the base
1483: * class.
1484: */
1485: private transient int internalSetMask;
1486:
1487: /**
1488: * The Gregorian year, as computed by computeGregorianFields() and
1489: * returned by getGregorianYear().
1490: */
1491: private transient int gregorianYear;
1492:
1493: /**
1494: * The Gregorian month, as computed by computeGregorianFields() and
1495: * returned by getGregorianMonth().
1496: */
1497: private transient int gregorianMonth;
1498:
1499: /**
1500: * The Gregorian day of the year, as computed by
1501: * computeGregorianFields() and returned by getGregorianDayOfYear().
1502: */
1503: private transient int gregorianDayOfYear;
1504:
1505: /**
1506: * The Gregorian day of the month, as computed by
1507: * computeGregorianFields() and returned by getGregorianDayOfMonth().
1508: */
1509: private transient int gregorianDayOfMonth;
1510:
1511: /**
1512: * Constructs a Calendar with the default time zone
1513: * and locale.
1514: * @see TimeZone#getDefault
1515: * @stable ICU 2.0
1516: */
1517: protected Calendar() {
1518: this (TimeZone.getDefault(), ULocale.getDefault());
1519: }
1520:
1521: /**
1522: * Constructs a calendar with the specified time zone and locale.
1523: * @param zone the time zone to use
1524: * @param aLocale the locale for the week data
1525: * @stable ICU 2.0
1526: */
1527: protected Calendar(TimeZone zone, Locale aLocale) {
1528: this (zone, ULocale.forLocale(aLocale));
1529: }
1530:
1531: /**
1532: * Constructs a calendar with the specified time zone and locale.
1533: * @param zone the time zone to use
1534: * @param locale the ulocale for the week data
1535: * @draft ICU 3.2
1536: * @provisional This API might change or be removed in a future release.
1537: */
1538: protected Calendar(TimeZone zone, ULocale locale) {
1539: this .zone = zone;
1540: setWeekData(locale);
1541: initInternal();
1542: }
1543:
1544: private void initInternal() {
1545: // Allocate fields through the framework method. Subclasses
1546: // may override this to define additional fields.
1547: fields = handleCreateFields();
1548: ///CLOVER:OFF
1549: // todo: fix, difficult to test without subclassing
1550: if (fields == null || fields.length < BASE_FIELD_COUNT
1551: || fields.length > MAX_FIELD_COUNT) {
1552: throw new IllegalStateException("Invalid fields[]");
1553: }
1554: ///CLOVER:ON
1555: stamp = new int[fields.length];
1556: int mask = (1 << ERA) | (1 << YEAR) | (1 << MONTH)
1557: | (1 << DAY_OF_MONTH) | (1 << DAY_OF_YEAR)
1558: | (1 << EXTENDED_YEAR);
1559: for (int i = BASE_FIELD_COUNT; i < fields.length; ++i) {
1560: mask |= (1 << i);
1561: }
1562: internalSetMask = mask;
1563: }
1564:
1565: /**
1566: * Gets a calendar using the default time zone and locale.
1567: * @return a Calendar.
1568: * @stable ICU 2.0
1569: */
1570: public static synchronized Calendar getInstance() {
1571: return getInstance(TimeZone.getDefault(), ULocale.getDefault(),
1572: null);
1573: }
1574:
1575: /**
1576: * Gets a calendar using the specified time zone and default locale.
1577: * @param zone the time zone to use
1578: * @return a Calendar.
1579: * @stable ICU 2.0
1580: */
1581: public static synchronized Calendar getInstance(TimeZone zone) {
1582: return getInstance(zone, ULocale.getDefault(), null);
1583: }
1584:
1585: /**
1586: * Gets a calendar using the default time zone and specified locale.
1587: * @param aLocale the locale for the week data
1588: * @return a Calendar.
1589: * @stable ICU 2.0
1590: */
1591: public static synchronized Calendar getInstance(Locale aLocale) {
1592: return getInstance(TimeZone.getDefault(), ULocale
1593: .forLocale(aLocale), null);
1594: }
1595:
1596: /**
1597: * Gets a calendar using the default time zone and specified locale.
1598: * @param locale the ulocale for the week data
1599: * @return a Calendar.
1600: * @draft ICU 3.2
1601: * @provisional This API might change or be removed in a future release.
1602: */
1603: public static synchronized Calendar getInstance(ULocale locale) {
1604: return getInstance(TimeZone.getDefault(), locale, null);
1605: }
1606:
1607: /**
1608: * Gets a calendar with the specified time zone and locale.
1609: * @param zone the time zone to use
1610: * @param aLocale the locale for the week data
1611: * @return a Calendar.
1612: * @stable ICU 2.0
1613: */
1614: public static synchronized Calendar getInstance(TimeZone zone,
1615: Locale aLocale) {
1616: return getInstance(zone, ULocale.forLocale(aLocale), null);
1617: }
1618:
1619: /**
1620: * Gets a calendar with the specified time zone and locale.
1621: * @param zone the time zone to use
1622: * @param locale the ulocale for the week data
1623: * @return a Calendar.
1624: * @draft ICU 3.2
1625: * @provisional This API might change or be removed in a future release.
1626: */
1627: public static synchronized Calendar getInstance(TimeZone zone,
1628: ULocale locale) {
1629: return getInstance(zone, locale, null);
1630: }
1631:
1632: // ==== Factory Stuff ====
1633: ///CLOVER:OFF
1634: /**
1635: * Return a calendar of for the TimeZone and locale. If factoryName is
1636: * not null, looks in the collection of CalendarFactories for a match
1637: * and uses that factory to instantiate the calendar. Otherwise, it
1638: * uses the default factory that has been registered for the locale.
1639: * @prototype
1640: */
1641: /* public */static synchronized Calendar getInstance(
1642: TimeZone zone, ULocale locale, String factoryName) {
1643: CalendarFactory factory = null;
1644: if (factoryName != null) {
1645: factory = (CalendarFactory) getFactoryMap()
1646: .get(factoryName);
1647: }
1648:
1649: ULocale[] actualReturn = new ULocale[1];
1650: if (factory == null && service != null) {
1651: factory = (CalendarFactory) service.get(locale,
1652: actualReturn);
1653: }
1654:
1655: if (factory == null) {
1656: int calType = getCalendarType(locale);
1657: switch (calType) {
1658: case BUDDHIST:
1659: return new BuddhistCalendar(zone, locale);
1660: case CHINESE:
1661: return new ChineseCalendar(zone, locale);
1662: case COPTIC:
1663: return new CopticCalendar(zone, locale);
1664: case ETHIOPIC:
1665: return new EthiopicCalendar(zone, locale);
1666: case GREGORIAN:
1667: return new GregorianCalendar(zone, locale);
1668: case HEBREW:
1669: return new HebrewCalendar(zone, locale);
1670: case ISLAMIC:
1671: case ISLAMIC_CIVIL: {
1672: IslamicCalendar result = new IslamicCalendar(zone,
1673: locale);
1674: result.setCivil(calType == ISLAMIC_CIVIL);
1675: return result;
1676: }
1677: case JAPANESE:
1678: return new JapaneseCalendar(zone, locale);
1679: default:
1680: throw new IllegalStateException();
1681: }
1682: } else {
1683: Calendar result = factory.create(zone, locale);
1684:
1685: // TODO: get the actual/valid locale properly
1686: ULocale uloc = actualReturn[0];
1687: result.setLocale(uloc, uloc);
1688:
1689: return result;
1690: }
1691: }
1692:
1693: private static final int BUDDHIST = 0;
1694: private static final int CHINESE = 1;
1695: private static final int COPTIC = 2;
1696: private static final int ETHIOPIC = 3;
1697: private static final int GREGORIAN = 4;
1698: private static final int HEBREW = 5;
1699: private static final int ISLAMIC = 6;
1700: private static final int ISLAMIC_CIVIL = 7;
1701: private static final int JAPANESE = 8;
1702:
1703: private static final String[] calTypes = { "buddhist", "chinese",
1704: "coptic", "ethiopic", "gregorian", "hebrew", "islamic",
1705: "islamic-civil", "japanese", };
1706:
1707: private static int getCalendarType(ULocale l) {
1708: String s = l.getKeywordValue("calendar");
1709: if (s == null) {
1710: l = ICUResourceBundle.getFunctionalEquivalent(
1711: ICUResourceBundle.ICU_BASE_NAME, "calendar",
1712: "calendar", l, null);
1713: s = l.getKeywordValue("calendar");
1714: }
1715: return getCalendarType(s);
1716: }
1717:
1718: private static int getCalendarType(String s) {
1719: if (s != null) {
1720: s = s.toLowerCase();
1721: for (int i = 0; i < calTypes.length; ++i) {
1722: if (s.equals(calTypes[i])) {
1723: return i;
1724: }
1725: }
1726: }
1727: return GREGORIAN;
1728: }
1729:
1730: ///CLOVER:ON
1731: /**
1732: * Gets the list of locales for which Calendars are installed.
1733: * @return the list of locales for which Calendars are installed.
1734: * @stable ICU 2.0
1735: */
1736: public static Locale[] getAvailableLocales() {
1737: return service == null ? ICUResourceBundle
1738: .getAvailableLocales(ICUResourceBundle.ICU_BASE_NAME)
1739: : service.getAvailableLocales();
1740: }
1741:
1742: /**
1743: * Gets the list of locales for which Calendars are installed.
1744: * @return the list of locales for which Calendars are installed.
1745: * @draft ICU 3.2
1746: * @provisional This API might change or be removed in a future release.
1747: */
1748: public static ULocale[] getAvailableULocales() {
1749: return service == null ? ICUResourceBundle
1750: .getAvailableULocales(ICUResourceBundle.ICU_BASE_NAME)
1751: : service.getAvailableULocales();
1752: }
1753:
1754: ///CLOVER:OFF
1755: private static Map factoryMap;
1756:
1757: private static Map getFactoryMap() {
1758: if (factoryMap == null) {
1759: Map m = new HashMap(5);
1760: /*
1761: addFactory(m, BuddhistCalendar.factory());
1762: addFactory(m, ChineseCalendar.factory());
1763: addFactory(m, GregorianCalendar.factory());
1764: addFactory(m, HebrewCalendar.factory());
1765: addFactory(m, IslamicCalendar.factory());
1766: addFactory(m, JapaneseCalendar.factory());
1767: */
1768: factoryMap = m;
1769: }
1770: return factoryMap;
1771: }
1772:
1773: // Never used -- why is this here? Alan 2003-05
1774: // private static void addFactory(Map m, CalendarFactory f) {
1775: // m.put(f.factoryName(), f);
1776: // }
1777:
1778: /**
1779: * Return a set of all the registered calendar factory names.
1780: * @prototype
1781: */
1782: /* public */static Set getCalendarFactoryNames() {
1783: return Collections.unmodifiableSet(getFactoryMap().keySet());
1784: }
1785:
1786: /**
1787: * Register a new CalendarFactory. getInstance(TimeZone, ULocale, String) will
1788: * try to locate a registered factories matching the factoryName. Only registered
1789: * factories will be found.
1790: * @prototype
1791: */
1792: private static void registerFactory(CalendarFactory factory) {
1793: if (factory == null) {
1794: throw new IllegalArgumentException(
1795: "Factory must not be null");
1796: }
1797: getFactoryMap().put(factory.factoryName(), factory);
1798: }
1799:
1800: /**
1801: * Convenience override of register(CalendarFactory, ULocale, boolean);
1802: * @prototype
1803: */
1804: /* public */static Object register(CalendarFactory factory,
1805: ULocale locale) {
1806: return register(factory, locale, true);
1807: }
1808:
1809: /**
1810: * Registers a default CalendarFactory for the provided locale.
1811: * If the factory has not already been registered with
1812: * registerFactory, it will be.
1813: * @prototype
1814: */
1815: /* public */static Object register(CalendarFactory factory,
1816: ULocale locale, boolean visible) {
1817: if (factory == null) {
1818: throw new IllegalArgumentException(
1819: "calendar must not be null");
1820: }
1821: registerFactory(factory);
1822: return getService().registerObject(factory, locale, visible);
1823: }
1824:
1825: /**
1826: * Unregister the CalendarFactory associated with this key
1827: * (obtained from register).
1828: * @prototype
1829: */
1830: /* public */static boolean unregister(Object registryKey) {
1831: return service == null ? false : service
1832: .unregisterFactory((Factory) registryKey);
1833: }
1834:
1835: private static ICULocaleService service = null;
1836:
1837: private static ICULocaleService getService() {
1838: synchronized (Calendar.class) {
1839: if (service == null) {
1840: service = new ICULocaleService("Calendar");
1841: }
1842: }
1843: return service;
1844: }
1845:
1846: ///CLOVER:ON
1847: // ==== End of factory Stuff ====
1848:
1849: /**
1850: * Gets this Calendar's current time.
1851: * @return the current time.
1852: * @stable ICU 2.0
1853: */
1854: public final Date getTime() {
1855: return new Date(getTimeInMillis());
1856: }
1857:
1858: /**
1859: * Sets this Calendar's current time with the given Date.
1860: * <p>
1861: * Note: Calling <code>setTime()</code> with
1862: * <code>Date(Long.MAX_VALUE)</code> or <code>Date(Long.MIN_VALUE)</code>
1863: * may yield incorrect field values from <code>get()</code>.
1864: * @param date the given Date.
1865: * @stable ICU 2.0
1866: */
1867: public final void setTime(Date date) {
1868: setTimeInMillis(date.getTime());
1869: }
1870:
1871: /**
1872: * Gets this Calendar's current time as a long.
1873: * @return the current time as UTC milliseconds from the epoch.
1874: * @stable ICU 2.0
1875: */
1876: public long getTimeInMillis() {
1877: if (!isTimeSet)
1878: updateTime();
1879: return time;
1880: }
1881:
1882: /**
1883: * Sets this Calendar's current time from the given long value.
1884: * @param millis the new time in UTC milliseconds from the epoch.
1885: * @stable ICU 2.0
1886: */
1887: public void setTimeInMillis(long millis) {
1888: if (millis > MAX_MILLIS) {
1889: millis = MAX_MILLIS;
1890: } else if (millis < MIN_MILLIS) {
1891: millis = MIN_MILLIS;
1892: }
1893: time = millis;
1894: areFieldsSet = areAllFieldsSet = false;
1895: isTimeSet = areFieldsVirtuallySet = true;
1896: }
1897:
1898: /**
1899: * Gets the value for a given time field.
1900: * @param field the given time field.
1901: * @return the value for the given time field.
1902: * @stable ICU 2.0
1903: */
1904: public final int get(int field) {
1905: complete();
1906: return fields[field];
1907: }
1908:
1909: /**
1910: * Gets the value for a given time field. This is an internal method
1911: * for subclasses that does <em>not</em> trigger any calculations.
1912: * @param field the given time field.
1913: * @return the value for the given time field.
1914: * @stable ICU 2.0
1915: */
1916: protected final int internalGet(int field) {
1917: return fields[field];
1918: }
1919:
1920: /**
1921: * Get the value for a given time field, or return the given default
1922: * value if the field is not set. This is an internal method for
1923: * subclasses that does <em>not</em> trigger any calculations.
1924: * @param field the given time field.
1925: * @param defaultValue value to return if field is not set
1926: * @return the value for the given time field of defaultValue if the
1927: * field is unset
1928: * @stable ICU 2.0
1929: */
1930: protected final int internalGet(int field, int defaultValue) {
1931: return (stamp[field] > UNSET) ? fields[field] : defaultValue;
1932: }
1933:
1934: /**
1935: * Sets the time field with the given value.
1936: * @param field the given time field.
1937: * @param value the value to be set for the given time field.
1938: * @stable ICU 2.0
1939: */
1940: public final void set(int field, int value) {
1941: if (areFieldsVirtuallySet) {
1942: computeFields();
1943: }
1944: fields[field] = value;
1945: stamp[field] = nextStamp++;
1946: isTimeSet = areFieldsSet = areFieldsVirtuallySet = false;
1947: }
1948:
1949: /**
1950: * Sets the values for the fields year, month, and date.
1951: * Previous values of other fields are retained. If this is not desired,
1952: * call <code>clear</code> first.
1953: * @param year the value used to set the YEAR time field.
1954: * @param month the value used to set the MONTH time field.
1955: * Month value is 0-based. e.g., 0 for January.
1956: * @param date the value used to set the DATE time field.
1957: * @stable ICU 2.0
1958: */
1959: public final void set(int year, int month, int date) {
1960: set(YEAR, year);
1961: set(MONTH, month);
1962: set(DATE, date);
1963: }
1964:
1965: /**
1966: * Sets the values for the fields year, month, date, hour, and minute.
1967: * Previous values of other fields are retained. If this is not desired,
1968: * call <code>clear</code> first.
1969: * @param year the value used to set the YEAR time field.
1970: * @param month the value used to set the MONTH time field.
1971: * Month value is 0-based. e.g., 0 for January.
1972: * @param date the value used to set the DATE time field.
1973: * @param hour the value used to set the HOUR_OF_DAY time field.
1974: * @param minute the value used to set the MINUTE time field.
1975: * @stable ICU 2.0
1976: */
1977: public final void set(int year, int month, int date, int hour,
1978: int minute) {
1979: set(YEAR, year);
1980: set(MONTH, month);
1981: set(DATE, date);
1982: set(HOUR_OF_DAY, hour);
1983: set(MINUTE, minute);
1984: }
1985:
1986: /**
1987: * Sets the values for the fields year, month, date, hour, minute, and second.
1988: * Previous values of other fields are retained. If this is not desired,
1989: * call <code>clear</code> first.
1990: * @param year the value used to set the YEAR time field.
1991: * @param month the value used to set the MONTH time field.
1992: * Month value is 0-based. e.g., 0 for January.
1993: * @param date the value used to set the DATE time field.
1994: * @param hour the value used to set the HOUR_OF_DAY time field.
1995: * @param minute the value used to set the MINUTE time field.
1996: * @param second the value used to set the SECOND time field.
1997: * @stable ICU 2.0
1998: */
1999: public final void set(int year, int month, int date, int hour,
2000: int minute, int second) {
2001: set(YEAR, year);
2002: set(MONTH, month);
2003: set(DATE, date);
2004: set(HOUR_OF_DAY, hour);
2005: set(MINUTE, minute);
2006: set(SECOND, second);
2007: }
2008:
2009: /**
2010: * Clears the values of all the time fields.
2011: * @stable ICU 2.0
2012: */
2013: public final void clear() {
2014: for (int i = 0; i < fields.length; ++i) {
2015: fields[i] = stamp[i] = 0; // UNSET == 0
2016: }
2017: isTimeSet = areFieldsSet = areAllFieldsSet = areFieldsVirtuallySet = false;
2018: }
2019:
2020: /**
2021: * Clears the value in the given time field.
2022: * @param field the time field to be cleared.
2023: * @stable ICU 2.0
2024: */
2025: public final void clear(int field) {
2026: if (areFieldsVirtuallySet) {
2027: computeFields();
2028: }
2029: fields[field] = 0;
2030: stamp[field] = UNSET;
2031: isTimeSet = areFieldsSet = areAllFieldsSet = areFieldsVirtuallySet = false;
2032: }
2033:
2034: /**
2035: * Determines if the given time field has a value set.
2036: * @return true if the given time field has a value set; false otherwise.
2037: * @stable ICU 2.0
2038: */
2039: public final boolean isSet(int field) {
2040: return areFieldsVirtuallySet || (stamp[field] != UNSET);
2041: }
2042:
2043: /**
2044: * Fills in any unset fields in the time field list.
2045: * @stable ICU 2.0
2046: */
2047: protected void complete() {
2048: if (!isTimeSet)
2049: updateTime();
2050: if (!areFieldsSet) {
2051: computeFields(); // fills in unset fields
2052: areFieldsSet = true;
2053: areAllFieldsSet = true;
2054: }
2055: }
2056:
2057: /**
2058: * Compares this calendar to the specified object.
2059: * The result is <code>true</code> if and only if the argument is
2060: * not <code>null</code> and is a <code>Calendar</code> object that
2061: * represents the same calendar as this object.
2062: * @param obj the object to compare with.
2063: * @return <code>true</code> if the objects are the same;
2064: * <code>false</code> otherwise.
2065: * @stable ICU 2.0
2066: */
2067: public boolean equals(Object obj) {
2068: if (this == obj) {
2069: return true;
2070: }
2071: if (this .getClass() != obj.getClass()) {
2072: return false;
2073: }
2074:
2075: Calendar that = (Calendar) obj;
2076:
2077: return isEquivalentTo(that)
2078: && getTimeInMillis() == that.getTime().getTime();
2079: }
2080:
2081: /**
2082: * Returns true if the given Calendar object is equivalent to this
2083: * one. An equivalent Calendar will behave exactly as this one
2084: * does, but it may be set to a different time. By contrast, for
2085: * the equals() method to return true, the other Calendar must
2086: * be set to the same time.
2087: *
2088: * @param other the Calendar to be compared with this Calendar
2089: * @stable ICU 2.4
2090: */
2091: public boolean isEquivalentTo(Calendar other) {
2092: return this .getClass() == other.getClass()
2093: && isLenient() == other.isLenient()
2094: && getFirstDayOfWeek() == other.getFirstDayOfWeek()
2095: && getMinimalDaysInFirstWeek() == other
2096: .getMinimalDaysInFirstWeek()
2097: && getTimeZone().equals(other.getTimeZone());
2098: }
2099:
2100: /**
2101: * Returns a hash code for this calendar.
2102: * @return a hash code value for this object.
2103: * @stable ICU 2.0
2104: */
2105: public int hashCode() {
2106: /* Don't include the time because (a) we don't want the hash value to
2107: * move around just because a calendar is set to different times, and
2108: * (b) we don't want to trigger a time computation just to get a hash.
2109: * Note that it is not necessary for unequal objects to always have
2110: * unequal hashes, but equal objects must have equal hashes. */
2111: return (lenient ? 1 : 0) | (firstDayOfWeek << 1)
2112: | (minimalDaysInFirstWeek << 4)
2113: | (zone.hashCode() << 7);
2114: }
2115:
2116: /**
2117: * Return the difference in milliseconds between the moment this
2118: * calendar is set to and the moment the given calendar or Date object
2119: * is set to.
2120: */
2121: private long compare(Object that) {
2122: long thatMs;
2123: if (that instanceof Calendar) {
2124: thatMs = ((Calendar) that).getTimeInMillis();
2125: } else if (that instanceof Date) {
2126: thatMs = ((Date) that).getTime();
2127: } else {
2128: throw new IllegalArgumentException(that
2129: + "is not a Calendar or Date");
2130: }
2131: return getTimeInMillis() - thatMs;
2132: }
2133:
2134: /**
2135: * Compares the time field records.
2136: * Equivalent to comparing result of conversion to UTC.
2137: * @param when the Calendar to be compared with this Calendar.
2138: * @return true if the current time of this Calendar is before
2139: * the time of Calendar when; false otherwise.
2140: * @stable ICU 2.0
2141: */
2142: public boolean before(Object when) {
2143: return compare(when) < 0;
2144: }
2145:
2146: /**
2147: * Compares the time field records.
2148: * Equivalent to comparing result of conversion to UTC.
2149: * @param when the Calendar to be compared with this Calendar.
2150: * @return true if the current time of this Calendar is after
2151: * the time of Calendar when; false otherwise.
2152: * @stable ICU 2.0
2153: */
2154: public boolean after(Object when) {
2155: return compare(when) > 0;
2156: }
2157:
2158: /**
2159: * Return the maximum value that this field could have, given the
2160: * current date. For example, with the Gregorian date February 3, 1997
2161: * and the {@link #DAY_OF_MONTH DAY_OF_MONTH} field, the actual maximum
2162: * is 28; for February 3, 1996 it is 29.
2163: *
2164: * <p>The actual maximum computation ignores smaller fields and the
2165: * current value of like-sized fields. For example, the actual maximum
2166: * of the DAY_OF_YEAR or MONTH depends only on the year and supra-year
2167: * fields. The actual maximum of the DAY_OF_MONTH depends, in
2168: * addition, on the MONTH field and any other fields at that
2169: * granularity (such as ChineseCalendar.IS_LEAP_MONTH). The
2170: * DAY_OF_WEEK_IN_MONTH field does not depend on the current
2171: * DAY_OF_WEEK; it returns the maximum for any day of week in the
2172: * current month. Likewise for the WEEK_OF_MONTH and WEEK_OF_YEAR
2173: * fields.
2174: *
2175: * @param field the field whose maximum is desired
2176: * @return the maximum of the given field for the current date of this calendar
2177: * @see #getMaximum
2178: * @see #getLeastMaximum
2179: * @stable ICU 2.0
2180: */
2181: public int getActualMaximum(int field) {
2182: int result;
2183:
2184: switch (field) {
2185: case DAY_OF_MONTH: {
2186: Calendar cal = (Calendar) clone();
2187: cal.prepareGetActual(field, false);
2188: result = handleGetMonthLength(cal.get(EXTENDED_YEAR), cal
2189: .get(MONTH));
2190: }
2191: break;
2192:
2193: case DAY_OF_YEAR: {
2194: Calendar cal = (Calendar) clone();
2195: cal.prepareGetActual(field, false);
2196: result = handleGetYearLength(cal.get(EXTENDED_YEAR));
2197: }
2198: break;
2199:
2200: case DAY_OF_WEEK:
2201: case AM_PM:
2202: case HOUR:
2203: case HOUR_OF_DAY:
2204: case MINUTE:
2205: case SECOND:
2206: case MILLISECOND:
2207: case ZONE_OFFSET:
2208: case DST_OFFSET:
2209: case DOW_LOCAL:
2210: case JULIAN_DAY:
2211: case MILLISECONDS_IN_DAY:
2212: // These fields all have fixed minima/maxima
2213: result = getMaximum(field);
2214: break;
2215:
2216: default:
2217: // For all other fields, do it the hard way....
2218: result = getActualHelper(field, getLeastMaximum(field),
2219: getMaximum(field));
2220: break;
2221: }
2222: return result;
2223: }
2224:
2225: /**
2226: * Return the minimum value that this field could have, given the current date.
2227: * For most fields, this is the same as {@link #getMinimum getMinimum}
2228: * and {@link #getGreatestMinimum getGreatestMinimum}. However, some fields,
2229: * especially those related to week number, are more complicated.
2230: * <p>
2231: * For example, assume {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek}
2232: * returns 4 and {@link #getFirstDayOfWeek getFirstDayOfWeek} returns SUNDAY.
2233: * If the first day of the month is Sunday, Monday, Tuesday, or Wednesday
2234: * there will be four or more days in the first week, so it will be week number 1,
2235: * and <code>getActualMinimum(WEEK_OF_MONTH)</code> will return 1. However,
2236: * if the first of the month is a Thursday, Friday, or Saturday, there are
2237: * <em>not</em> four days in that week, so it is week number 0, and
2238: * <code>getActualMinimum(WEEK_OF_MONTH)</code> will return 0.
2239: * <p>
2240: * @param field the field whose actual minimum value is desired.
2241: * @return the minimum of the given field for the current date of this calendar
2242: *
2243: * @see #getMinimum
2244: * @see #getGreatestMinimum
2245: * @stable ICU 2.0
2246: */
2247: public int getActualMinimum(int field) {
2248: int result;
2249:
2250: switch (field) {
2251: case DAY_OF_WEEK:
2252: case AM_PM:
2253: case HOUR:
2254: case HOUR_OF_DAY:
2255: case MINUTE:
2256: case SECOND:
2257: case MILLISECOND:
2258: case ZONE_OFFSET:
2259: case DST_OFFSET:
2260: case DOW_LOCAL:
2261: case JULIAN_DAY:
2262: case MILLISECONDS_IN_DAY:
2263: // These fields all have fixed minima/maxima
2264: result = getMinimum(field);
2265: break;
2266:
2267: default:
2268: // For all other fields, do it the hard way....
2269: result = getActualHelper(field, getGreatestMinimum(field),
2270: getMinimum(field));
2271: break;
2272: }
2273: return result;
2274: }
2275:
2276: /**
2277: * Prepare this calendar for computing the actual minimum or maximum.
2278: * This method modifies this calendar's fields; it is called on a
2279: * temporary calendar.
2280: *
2281: * <p>Rationale: The semantics of getActualXxx() is to return the
2282: * maximum or minimum value that the given field can take, taking into
2283: * account other relevant fields. In general these other fields are
2284: * larger fields. For example, when computing the actual maximum
2285: * DAY_OF_MONTH, the current value of DAY_OF_MONTH itself is ignored,
2286: * as is the value of any field smaller.
2287: *
2288: * <p>The time fields all have fixed minima and maxima, so we don't
2289: * need to worry about them. This also lets us set the
2290: * MILLISECONDS_IN_DAY to zero to erase any effects the time fields
2291: * might have when computing date fields.
2292: *
2293: * <p>DAY_OF_WEEK is adjusted specially for the WEEK_OF_MONTH and
2294: * WEEK_OF_YEAR fields to ensure that they are computed correctly.
2295: * @stable ICU 2.0
2296: */
2297: protected void prepareGetActual(int field, boolean isMinimum) {
2298: set(MILLISECONDS_IN_DAY, 0);
2299:
2300: switch (field) {
2301: case YEAR:
2302: case YEAR_WOY:
2303: case EXTENDED_YEAR:
2304: set(DAY_OF_YEAR, getGreatestMinimum(DAY_OF_YEAR));
2305: break;
2306:
2307: case MONTH:
2308: set(DAY_OF_MONTH, getGreatestMinimum(DAY_OF_MONTH));
2309: break;
2310:
2311: case DAY_OF_WEEK_IN_MONTH:
2312: // For dowim, the maximum occurs for the DOW of the first of the
2313: // month.
2314: set(DAY_OF_MONTH, 1);
2315: set(DAY_OF_WEEK, get(DAY_OF_WEEK)); // Make this user set
2316: break;
2317:
2318: case WEEK_OF_MONTH:
2319: case WEEK_OF_YEAR:
2320: // If we're counting weeks, set the day of the week to either the
2321: // first or last localized DOW. We know the last week of a month
2322: // or year will contain the first day of the week, and that the
2323: // first week will contain the last DOW.
2324: {
2325: int dow = firstDayOfWeek;
2326: if (isMinimum) {
2327: dow = (dow + 6) % 7; // set to last DOW
2328: if (dow < SUNDAY) {
2329: dow += 7;
2330: }
2331: }
2332: set(DAY_OF_WEEK, dow);
2333: }
2334: break;
2335: }
2336:
2337: // Do this last to give it the newest time stamp
2338: set(field, getGreatestMinimum(field));
2339: }
2340:
2341: private int getActualHelper(int field, int startValue, int endValue) {
2342:
2343: if (startValue == endValue) {
2344: // if we know that the maximum value is always the same, just return it
2345: return startValue;
2346: }
2347:
2348: final int delta = (endValue > startValue) ? 1 : -1;
2349:
2350: // clone the calendar so we don't mess with the real one, and set it to
2351: // accept anything for the field values
2352: Calendar work = (Calendar) clone();
2353: work.setLenient(true);
2354: work.prepareGetActual(field, delta < 0);
2355:
2356: // now try each value from the start to the end one by one until
2357: // we get a value that normalizes to another value. The last value that
2358: // normalizes to itself is the actual maximum for the current date
2359: int result = startValue;
2360: do {
2361: work.set(field, startValue);
2362: if (work.get(field) != startValue) {
2363: break;
2364: } else {
2365: result = startValue;
2366: startValue += delta;
2367: }
2368: } while (result != endValue);
2369:
2370: return result;
2371: }
2372:
2373: /**
2374: * Rolls (up/down) a single unit of time on the given field. If the
2375: * field is rolled past its maximum allowable value, it will "wrap" back
2376: * to its minimum and continue rolling. For
2377: * example, to roll the current date up by one day, you can call:
2378: * <p>
2379: * <code>roll({@link #DATE}, true)</code>
2380: * <p>
2381: * When rolling on the {@link #YEAR} field, it will roll the year
2382: * value in the range between 1 and the value returned by calling
2383: * {@link #getMaximum getMaximum}({@link #YEAR}).
2384: * <p>
2385: * When rolling on certain fields, the values of other fields may conflict and
2386: * need to be changed. For example, when rolling the <code>MONTH</code> field
2387: * for the Gregorian date 1/31/96 upward, the <code>DAY_OF_MONTH</code> field
2388: * must be adjusted so that the result is 2/29/96 rather than the invalid
2389: * 2/31/96.
2390: * <p>
2391: * <b>Note:</b> Calling <tt>roll(field, true)</tt> N times is <em>not</em>
2392: * necessarily equivalent to calling <tt>roll(field, N)</tt>. For example,
2393: * imagine that you start with the date Gregorian date January 31, 1995. If you call
2394: * <tt>roll(Calendar.MONTH, 2)</tt>, the result will be March 31, 1995.
2395: * But if you call <tt>roll(Calendar.MONTH, true)</tt>, the result will be
2396: * February 28, 1995. Calling it one more time will give March 28, 1995, which
2397: * is usually not the desired result.
2398: * <p>
2399: * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather
2400: * than attempting to perform arithmetic operations directly on the fields
2401: * of a <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses
2402: * to have fields with non-linear behavior, for example missing months
2403: * or days during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt>
2404: * methods will take this into account, while simple arithmetic manipulations
2405: * may give invalid results.
2406: * <p>
2407: * @param field the calendar field to roll.
2408: *
2409: * @param up indicates if the value of the specified time field is to be
2410: * rolled up or rolled down. Use <code>true</code> if rolling up,
2411: * <code>false</code> otherwise.
2412: *
2413: * @exception IllegalArgumentException if the field is invalid or refers
2414: * to a field that cannot be handled by this method.
2415: * @see #roll(int, int)
2416: * @see #add
2417: * @stable ICU 2.0
2418: */
2419: public final void roll(int field, boolean up) {
2420: roll(field, up ? +1 : -1);
2421: }
2422:
2423: /**
2424: * Rolls (up/down) a specified amount time on the given field. For
2425: * example, to roll the current date up by three days, you can call
2426: * <code>roll(Calendar.DATE, 3)</code>. If the
2427: * field is rolled past its maximum allowable value, it will "wrap" back
2428: * to its minimum and continue rolling.
2429: * For example, calling <code>roll(Calendar.DATE, 10)</code>
2430: * on a Gregorian calendar set to 4/25/96 will result in the date 4/5/96.
2431: * <p>
2432: * When rolling on certain fields, the values of other fields may conflict and
2433: * need to be changed. For example, when rolling the {@link #MONTH MONTH} field
2434: * for the Gregorian date 1/31/96 by +1, the {@link #DAY_OF_MONTH DAY_OF_MONTH} field
2435: * must be adjusted so that the result is 2/29/96 rather than the invalid
2436: * 2/31/96.
2437: * <p>
2438: * The <code>com.ibm.icu.util.Calendar</code> implementation of this method is able to roll
2439: * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET},
2440: * and {@link #ZONE_OFFSET ZONE_OFFSET}. Subclasses may, of course, add support for
2441: * additional fields in their overrides of <code>roll</code>.
2442: * <p>
2443: * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather
2444: * than attempting to perform arithmetic operations directly on the fields
2445: * of a <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses
2446: * to have fields with non-linear behavior, for example missing months
2447: * or days during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt>
2448: * methods will take this into account, while simple arithmetic manipulations
2449: * may give invalid results.
2450: * <p>
2451: * <b>Subclassing:</b><br>
2452: * This implementation of <code>roll</code> assumes that the behavior of the
2453: * field is continuous between its minimum and maximum, which are found by
2454: * calling {@link #getActualMinimum getActualMinimum} and {@link #getActualMaximum getActualMaximum}.
2455: * For most such fields, simple addition, subtraction, and modulus operations
2456: * are sufficient to perform the roll. For week-related fields,
2457: * the results of {@link #getFirstDayOfWeek getFirstDayOfWeek} and
2458: * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} are also necessary.
2459: * Subclasses can override these two methods if their values differ from the defaults.
2460: * <p>
2461: * Subclasses that have fields for which the assumption of continuity breaks
2462: * down must overide <code>roll</code> to handle those fields specially.
2463: * For example, in the Hebrew calendar the month "Adar I"
2464: * only occurs in leap years; in other years the calendar jumps from
2465: * Shevat (month #4) to Adar (month #6). The
2466: * {@link HebrewCalendar#roll HebrewCalendar.roll} method takes this into account,
2467: * so that rolling the month of Shevat by one gives the proper result (Adar) in a
2468: * non-leap year.
2469: * <p>
2470: * @param field the calendar field to roll.
2471: * @param amount the amount by which the field should be rolled.
2472: *
2473: * @exception IllegalArgumentException if the field is invalid or refers
2474: * to a field that cannot be handled by this method.
2475: * @see #roll(int, boolean)
2476: * @see #add
2477: * @stable ICU 2.0
2478: */
2479: public void roll(int field, int amount) {
2480:
2481: if (amount == 0) {
2482: return; // Nothing to do
2483: }
2484:
2485: complete();
2486:
2487: switch (field) {
2488: case DAY_OF_MONTH:
2489: case AM_PM:
2490: case MINUTE:
2491: case SECOND:
2492: case MILLISECOND:
2493: case MILLISECONDS_IN_DAY:
2494: case ERA:
2495: // These are the standard roll instructions. These work for all
2496: // simple cases, that is, cases in which the limits are fixed, such
2497: // as the hour, the day of the month, and the era.
2498: {
2499: int min = getActualMinimum(field);
2500: int max = getActualMaximum(field);
2501: int gap = max - min + 1;
2502:
2503: int value = internalGet(field) + amount;
2504: value = (value - min) % gap;
2505: if (value < 0) {
2506: value += gap;
2507: }
2508: value += min;
2509:
2510: set(field, value);
2511: return;
2512: }
2513:
2514: case HOUR:
2515: case HOUR_OF_DAY:
2516: // Rolling the hour is difficult on the ONSET and CEASE days of
2517: // daylight savings. For example, if the change occurs at
2518: // 2 AM, we have the following progression:
2519: // ONSET: 12 Std -> 1 Std -> 3 Dst -> 4 Dst
2520: // CEASE: 12 Dst -> 1 Dst -> 1 Std -> 2 Std
2521: // To get around this problem we don't use fields; we manipulate
2522: // the time in millis directly.
2523: {
2524: // Assume min == 0 in calculations below
2525: long start = getTimeInMillis();
2526: int oldHour = internalGet(field);
2527: int max = getMaximum(field);
2528: int newHour = (oldHour + amount) % (max + 1);
2529: if (newHour < 0) {
2530: newHour += max + 1;
2531: }
2532: setTimeInMillis(start + ONE_HOUR * (newHour - oldHour));
2533: return;
2534: }
2535:
2536: case MONTH:
2537: // Rolling the month involves both pinning the final value
2538: // and adjusting the DAY_OF_MONTH if necessary. We only adjust the
2539: // DAY_OF_MONTH if, after updating the MONTH field, it is illegal.
2540: // E.g., <jan31>.roll(MONTH, 1) -> <feb28> or <feb29>.
2541: {
2542: int max = getActualMaximum(MONTH);
2543: int mon = (internalGet(MONTH) + amount) % (max + 1);
2544:
2545: if (mon < 0) {
2546: mon += (max + 1);
2547: }
2548: set(MONTH, mon);
2549:
2550: // Keep the day of month in range. We don't want to spill over
2551: // into the next month; e.g., we don't want jan31 + 1 mo -> feb31 ->
2552: // mar3.
2553: pinField(DAY_OF_MONTH);
2554: return;
2555: }
2556:
2557: case YEAR:
2558: case YEAR_WOY:
2559: case EXTENDED_YEAR:
2560: // Rolling the year can involve pinning the DAY_OF_MONTH.
2561: set(field, internalGet(field) + amount);
2562: pinField(MONTH);
2563: pinField(DAY_OF_MONTH);
2564: return;
2565:
2566: case WEEK_OF_MONTH: {
2567: // This is tricky, because during the roll we may have to shift
2568: // to a different day of the week. For example:
2569:
2570: // s m t w r f s
2571: // 1 2 3 4 5
2572: // 6 7 8 9 10 11 12
2573:
2574: // When rolling from the 6th or 7th back one week, we go to the
2575: // 1st (assuming that the first partial week counts). The same
2576: // thing happens at the end of the month.
2577:
2578: // The other tricky thing is that we have to figure out whether
2579: // the first partial week actually counts or not, based on the
2580: // minimal first days in the week. And we have to use the
2581: // correct first day of the week to delineate the week
2582: // boundaries.
2583:
2584: // Here's our algorithm. First, we find the real boundaries of
2585: // the month. Then we discard the first partial week if it
2586: // doesn't count in this locale. Then we fill in the ends with
2587: // phantom days, so that the first partial week and the last
2588: // partial week are full weeks. We then have a nice square
2589: // block of weeks. We do the usual rolling within this block,
2590: // as is done elsewhere in this method. If we wind up on one of
2591: // the phantom days that we added, we recognize this and pin to
2592: // the first or the last day of the month. Easy, eh?
2593:
2594: // Normalize the DAY_OF_WEEK so that 0 is the first day of the week
2595: // in this locale. We have dow in 0..6.
2596: int dow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek();
2597: if (dow < 0)
2598: dow += 7;
2599:
2600: // Find the day of the week (normalized for locale) for the first
2601: // of the month.
2602: int fdm = (dow - internalGet(DAY_OF_MONTH) + 1) % 7;
2603: if (fdm < 0)
2604: fdm += 7;
2605:
2606: // Get the first day of the first full week of the month,
2607: // including phantom days, if any. Figure out if the first week
2608: // counts or not; if it counts, then fill in phantom days. If
2609: // not, advance to the first real full week (skip the partial week).
2610: int start;
2611: if ((7 - fdm) < getMinimalDaysInFirstWeek())
2612: start = 8 - fdm; // Skip the first partial week
2613: else
2614: start = 1 - fdm; // This may be zero or negative
2615:
2616: // Get the day of the week (normalized for locale) for the last
2617: // day of the month.
2618: int monthLen = getActualMaximum(DAY_OF_MONTH);
2619: int ldm = (monthLen - internalGet(DAY_OF_MONTH) + dow) % 7;
2620: // We know monthLen >= DAY_OF_MONTH so we skip the += 7 step here.
2621:
2622: // Get the limit day for the blocked-off rectangular month; that
2623: // is, the day which is one past the last day of the month,
2624: // after the month has already been filled in with phantom days
2625: // to fill out the last week. This day has a normalized DOW of 0.
2626: int limit = monthLen + 7 - ldm;
2627:
2628: // Now roll between start and (limit - 1).
2629: int gap = limit - start;
2630: int day_of_month = (internalGet(DAY_OF_MONTH) + amount * 7 - start)
2631: % gap;
2632: if (day_of_month < 0)
2633: day_of_month += gap;
2634: day_of_month += start;
2635:
2636: // Finally, pin to the real start and end of the month.
2637: if (day_of_month < 1)
2638: day_of_month = 1;
2639: if (day_of_month > monthLen)
2640: day_of_month = monthLen;
2641:
2642: // Set the DAY_OF_MONTH. We rely on the fact that this field
2643: // takes precedence over everything else (since all other fields
2644: // are also set at this point). If this fact changes (if the
2645: // disambiguation algorithm changes) then we will have to unset
2646: // the appropriate fields here so that DAY_OF_MONTH is attended
2647: // to.
2648: set(DAY_OF_MONTH, day_of_month);
2649: return;
2650: }
2651: case WEEK_OF_YEAR: {
2652: // This follows the outline of WEEK_OF_MONTH, except it applies
2653: // to the whole year. Please see the comment for WEEK_OF_MONTH
2654: // for general notes.
2655:
2656: // Normalize the DAY_OF_WEEK so that 0 is the first day of the week
2657: // in this locale. We have dow in 0..6.
2658: int dow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek();
2659: if (dow < 0)
2660: dow += 7;
2661:
2662: // Find the day of the week (normalized for locale) for the first
2663: // of the year.
2664: int fdy = (dow - internalGet(DAY_OF_YEAR) + 1) % 7;
2665: if (fdy < 0)
2666: fdy += 7;
2667:
2668: // Get the first day of the first full week of the year,
2669: // including phantom days, if any. Figure out if the first week
2670: // counts or not; if it counts, then fill in phantom days. If
2671: // not, advance to the first real full week (skip the partial week).
2672: int start;
2673: if ((7 - fdy) < getMinimalDaysInFirstWeek())
2674: start = 8 - fdy; // Skip the first partial week
2675: else
2676: start = 1 - fdy; // This may be zero or negative
2677:
2678: // Get the day of the week (normalized for locale) for the last
2679: // day of the year.
2680: int yearLen = getActualMaximum(DAY_OF_YEAR);
2681: int ldy = (yearLen - internalGet(DAY_OF_YEAR) + dow) % 7;
2682: // We know yearLen >= DAY_OF_YEAR so we skip the += 7 step here.
2683:
2684: // Get the limit day for the blocked-off rectangular year; that
2685: // is, the day which is one past the last day of the year,
2686: // after the year has already been filled in with phantom days
2687: // to fill out the last week. This day has a normalized DOW of 0.
2688: int limit = yearLen + 7 - ldy;
2689:
2690: // Now roll between start and (limit - 1).
2691: int gap = limit - start;
2692: int day_of_year = (internalGet(DAY_OF_YEAR) + amount * 7 - start)
2693: % gap;
2694: if (day_of_year < 0)
2695: day_of_year += gap;
2696: day_of_year += start;
2697:
2698: // Finally, pin to the real start and end of the month.
2699: if (day_of_year < 1)
2700: day_of_year = 1;
2701: if (day_of_year > yearLen)
2702: day_of_year = yearLen;
2703:
2704: // Make sure that the year and day of year are attended to by
2705: // clearing other fields which would normally take precedence.
2706: // If the disambiguation algorithm is changed, this section will
2707: // have to be updated as well.
2708: set(DAY_OF_YEAR, day_of_year);
2709: clear(MONTH);
2710: return;
2711: }
2712: case DAY_OF_YEAR: {
2713: // Roll the day of year using millis. Compute the millis for
2714: // the start of the year, and get the length of the year.
2715: long delta = amount * ONE_DAY; // Scale up from days to millis
2716: long min2 = time - (internalGet(DAY_OF_YEAR) - 1) * ONE_DAY;
2717: int yearLength = getActualMaximum(DAY_OF_YEAR);
2718: time = (time + delta - min2) % (yearLength * ONE_DAY);
2719: if (time < 0)
2720: time += yearLength * ONE_DAY;
2721: setTimeInMillis(time + min2);
2722: return;
2723: }
2724: case DAY_OF_WEEK:
2725: case DOW_LOCAL: {
2726: // Roll the day of week using millis. Compute the millis for
2727: // the start of the week, using the first day of week setting.
2728: // Restrict the millis to [start, start+7days).
2729: long delta = amount * ONE_DAY; // Scale up from days to millis
2730: // Compute the number of days before the current day in this
2731: // week. This will be a value 0..6.
2732: int leadDays = internalGet(field);
2733: leadDays -= (field == DAY_OF_WEEK) ? getFirstDayOfWeek()
2734: : 1;
2735: if (leadDays < 0)
2736: leadDays += 7;
2737: long min2 = time - leadDays * ONE_DAY;
2738: time = (time + delta - min2) % ONE_WEEK;
2739: if (time < 0)
2740: time += ONE_WEEK;
2741: setTimeInMillis(time + min2);
2742: return;
2743: }
2744: case DAY_OF_WEEK_IN_MONTH: {
2745: // Roll the day of week in the month using millis. Determine
2746: // the first day of the week in the month, and then the last,
2747: // and then roll within that range.
2748: long delta = amount * ONE_WEEK; // Scale up from weeks to millis
2749: // Find the number of same days of the week before this one
2750: // in this month.
2751: int preWeeks = (internalGet(DAY_OF_MONTH) - 1) / 7;
2752: // Find the number of same days of the week after this one
2753: // in this month.
2754: int postWeeks = (getActualMaximum(DAY_OF_MONTH) - internalGet(DAY_OF_MONTH)) / 7;
2755: // From these compute the min and gap millis for rolling.
2756: long min2 = time - preWeeks * ONE_WEEK;
2757: long gap2 = ONE_WEEK * (preWeeks + postWeeks + 1); // Must add 1!
2758: // Roll within this range
2759: time = (time + delta - min2) % gap2;
2760: if (time < 0)
2761: time += gap2;
2762: setTimeInMillis(time + min2);
2763: return;
2764: }
2765: case JULIAN_DAY:
2766: set(field, internalGet(field) + amount);
2767: return;
2768: default:
2769: // Other fields cannot be rolled by this method
2770: throw new IllegalArgumentException("Calendar.roll("
2771: + fieldName(field) + ") not supported");
2772: }
2773: }
2774:
2775: /**
2776: * Add a signed amount to a specified field, using this calendar's rules.
2777: * For example, to add three days to the current date, you can call
2778: * <code>add(Calendar.DATE, 3)</code>.
2779: * <p>
2780: * When adding to certain fields, the values of other fields may conflict and
2781: * need to be changed. For example, when adding one to the {@link #MONTH MONTH} field
2782: * for the Gregorian date 1/31/96, the {@link #DAY_OF_MONTH DAY_OF_MONTH} field
2783: * must be adjusted so that the result is 2/29/96 rather than the invalid
2784: * 2/31/96.
2785: * <p>
2786: * The <code>com.ibm.icu.util.Calendar</code> implementation of this method is able to add to
2787: * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET},
2788: * and {@link #ZONE_OFFSET ZONE_OFFSET}. Subclasses may, of course, add support for
2789: * additional fields in their overrides of <code>add</code>.
2790: * <p>
2791: * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather
2792: * than attempting to perform arithmetic operations directly on the fields
2793: * of a <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses
2794: * to have fields with non-linear behavior, for example missing months
2795: * or days during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt>
2796: * methods will take this into account, while simple arithmetic manipulations
2797: * may give invalid results.
2798: * <p>
2799: * <b>Subclassing:</b><br>
2800: * This implementation of <code>add</code> assumes that the behavior of the
2801: * field is continuous between its minimum and maximum, which are found by
2802: * calling {@link #getActualMinimum getActualMinimum} and
2803: * {@link #getActualMaximum getActualMaximum}.
2804: * For such fields, simple arithmetic operations are sufficient to
2805: * perform the add.
2806: * <p>
2807: * Subclasses that have fields for which this assumption of continuity breaks
2808: * down must overide <code>add</code> to handle those fields specially.
2809: * For example, in the Hebrew calendar the month "Adar I"
2810: * only occurs in leap years; in other years the calendar jumps from
2811: * Shevat (month #4) to Adar (month #6). The
2812: * {@link HebrewCalendar#add HebrewCalendar.add} method takes this into account,
2813: * so that adding one month
2814: * to a date in Shevat gives the proper result (Adar) in a non-leap year.
2815: * <p>
2816: * @param field the time field.
2817: * @param amount the amount to add to the field.
2818: *
2819: * @exception IllegalArgumentException if the field is invalid or refers
2820: * to a field that cannot be handled by this method.
2821: * @see #roll(int, int)
2822: * @stable ICU 2.0
2823: */
2824: public void add(int field, int amount) {
2825:
2826: if (amount == 0) {
2827: return; // Do nothing!
2828: }
2829:
2830: // We handle most fields in the same way. The algorithm is to add
2831: // a computed amount of millis to the current millis. The only
2832: // wrinkle is with DST -- for some fields, like the DAY_OF_MONTH,
2833: // we don't want the HOUR to shift due to changes in DST. If the
2834: // result of the add operation is to move from DST to Standard, or
2835: // vice versa, we need to adjust by an hour forward or back,
2836: // respectively. For such fields we set keepHourInvariant to true.
2837:
2838: // We only adjust the DST for fields larger than an hour. For
2839: // fields smaller than an hour, we cannot adjust for DST without
2840: // causing problems. for instance, if you add one hour to April 5,
2841: // 1998, 1:00 AM, in PST, the time becomes "2:00 AM PDT" (an
2842: // illegal value), but then the adjustment sees the change and
2843: // compensates by subtracting an hour. As a result the time
2844: // doesn't advance at all.
2845:
2846: // For some fields larger than a day, such as a MONTH, we pin the
2847: // DAY_OF_MONTH. This allows <March 31>.add(MONTH, 1) to be
2848: // <April 30>, rather than <April 31> => <May 1>.
2849:
2850: long delta = amount; // delta in ms
2851: boolean keepHourInvariant = true;
2852:
2853: switch (field) {
2854: case ERA:
2855: set(field, get(field) + amount);
2856: pinField(ERA);
2857: return;
2858:
2859: case YEAR:
2860: case EXTENDED_YEAR:
2861: case YEAR_WOY:
2862: case MONTH:
2863: set(field, get(field) + amount);
2864: pinField(DAY_OF_MONTH);
2865: return;
2866:
2867: case WEEK_OF_YEAR:
2868: case WEEK_OF_MONTH:
2869: case DAY_OF_WEEK_IN_MONTH:
2870: delta *= ONE_WEEK;
2871: break;
2872:
2873: case AM_PM:
2874: delta *= 12 * ONE_HOUR;
2875: break;
2876:
2877: case DAY_OF_MONTH:
2878: case DAY_OF_YEAR:
2879: case DAY_OF_WEEK:
2880: case DOW_LOCAL:
2881: case JULIAN_DAY:
2882: delta *= ONE_DAY;
2883: break;
2884:
2885: case HOUR_OF_DAY:
2886: case HOUR:
2887: delta *= ONE_HOUR;
2888: keepHourInvariant = false;
2889: break;
2890:
2891: case MINUTE:
2892: delta *= ONE_MINUTE;
2893: keepHourInvariant = false;
2894: break;
2895:
2896: case SECOND:
2897: delta *= ONE_SECOND;
2898: keepHourInvariant = false;
2899: break;
2900:
2901: case MILLISECOND:
2902: case MILLISECONDS_IN_DAY:
2903: keepHourInvariant = false;
2904: break;
2905:
2906: default:
2907: throw new IllegalArgumentException("Calendar.add("
2908: + fieldName(field) + ") not supported");
2909: }
2910:
2911: // In order to keep the hour invariant (for fields where this is
2912: // appropriate), record the DST_OFFSET before and after the add()
2913: // operation. If it has changed, then adjust the millis to
2914: // compensate.
2915: int dst = 0;
2916: int hour = 0;
2917: if (keepHourInvariant) {
2918: dst = get(DST_OFFSET);
2919: hour = internalGet(HOUR_OF_DAY);
2920: }
2921:
2922: setTimeInMillis(getTimeInMillis() + delta);
2923:
2924: if (keepHourInvariant) {
2925: dst -= get(DST_OFFSET);
2926: if (dst != 0) {
2927: // We have done an hour-invariant adjustment but the
2928: // DST offset has altered. We adjust millis to keep
2929: // the hour constant. In cases such as midnight after
2930: // a DST change which occurs at midnight, there is the
2931: // danger of adjusting into a different day. To avoid
2932: // this we make the adjustment only if it actually
2933: // maintains the hour.
2934: long t = time;
2935: setTimeInMillis(time + dst);
2936: if (get(HOUR_OF_DAY) != hour) {
2937: setTimeInMillis(t);
2938: }
2939: }
2940: }
2941: }
2942:
2943: /**
2944: * Return the name of this calendar in the language of the given locale.
2945: * @stable ICU 2.0
2946: */
2947: public String getDisplayName(Locale loc) {
2948: return this .getClass().getName();
2949: }
2950:
2951: /**
2952: * Return the name of this calendar in the language of the given locale.
2953: * @draft ICU 3.2
2954: * @provisional This API might change or be removed in a future release.
2955: */
2956: public String getDisplayName(ULocale loc) {
2957: return this .getClass().getName();
2958: }
2959:
2960: /**
2961: * Compares the times (in millis) represented by two
2962: * <code>Calendar</code> objects.
2963: *
2964: * @param that the <code>Calendar</code> to compare to this.
2965: * @return <code>0</code> if the time represented by
2966: * this <code>Calendar</code> is equal to the time represented
2967: * by that <code>Calendar</code>, a value less than
2968: * <code>0</code> if the time represented by this is before
2969: * the time represented by that, and a value greater than
2970: * <code>0</code> if the time represented by this
2971: * is after the time represented by that.
2972: * @throws NullPointerException if that
2973: * <code>Calendar</code> is null.
2974: * @throws IllegalArgumentException if the time of that
2975: * <code>Calendar</code> can't be obtained because of invalid
2976: * calendar values.
2977: * @draft ICU 3.4
2978: * @provisional This API might change or be removed in a future release.
2979: */
2980: public int compareTo(Calendar that) {
2981: long v = getTimeInMillis() - that.getTimeInMillis();
2982: return v < 0 ? -1 : (v > 0 ? 1 : 0);
2983: }
2984:
2985: /**
2986: * Implement comparable API as a convenience override of
2987: * {@link #compareTo(Calendar)}.
2988: * @draft ICU 3.4
2989: * @provisional This API might change or be removed in a future release.
2990: */
2991: public int compareTo(Object that) {
2992: return compareTo((Calendar) that);
2993: }
2994:
2995: //-------------------------------------------------------------------------
2996: // Interface for creating custon DateFormats for different types of Calendars
2997: //-------------------------------------------------------------------------
2998:
2999: /**
3000: * Return a <code>DateFormat</code> appropriate to this calendar.
3001: * Subclasses wishing to specialize this behavior should override
3002: * <code>handleGetDateFormat()</code>
3003: * @see #handleGetDateFormat
3004: * @stable ICU 2.0
3005: */
3006: public DateFormat getDateTimeFormat(int dateStyle, int timeStyle,
3007: Locale loc) {
3008: return formatHelper(this , ULocale.forLocale(loc), dateStyle,
3009: timeStyle);
3010: }
3011:
3012: /**
3013: * Return a <code>DateFormat</code> appropriate to this calendar.
3014: * Subclasses wishing to specialize this behavior should override
3015: * <code>handleGetDateFormat()</code>
3016: * @see #handleGetDateFormat
3017: * @draft ICU 3.2
3018: * @provisional This API might change or be removed in a future release.
3019: */
3020: public DateFormat getDateTimeFormat(int dateStyle, int timeStyle,
3021: ULocale loc) {
3022: return formatHelper(this , loc, dateStyle, timeStyle);
3023: }
3024:
3025: /**
3026: * Create a <code>DateFormat</code> appropriate to this calendar.
3027: * This is a framework method for subclasses to override. This method
3028: * is responsible for creating the calendar-specific DateFormat and
3029: * DateFormatSymbols objects as needed.
3030: * @param pattern the pattern, specific to the <code>DateFormat</code>
3031: * subclass
3032: * @param locale the locale for which the symbols should be drawn
3033: * @return a <code>DateFormat</code> appropriate to this calendar
3034: * @stable ICU 2.0
3035: */
3036: protected DateFormat handleGetDateFormat(String pattern,
3037: Locale locale) {
3038: return handleGetDateFormat(pattern, ULocale.forLocale(locale));
3039: }
3040:
3041: /**
3042: * Create a <code>DateFormat</code> appropriate to this calendar.
3043: * This is a framework method for subclasses to override. This method
3044: * is responsible for creating the calendar-specific DateFormat and
3045: * DateFormatSymbols objects as needed.
3046: * @param pattern the pattern, specific to the <code>DateFormat</code>
3047: * subclass
3048: * @param locale the locale for which the symbols should be drawn
3049: * @return a <code>DateFormat</code> appropriate to this calendar
3050: * @draft ICU 3.2
3051: * @provisional This API might change or be removed in a future release.
3052: */
3053: protected DateFormat handleGetDateFormat(String pattern,
3054: ULocale locale) {
3055: DateFormatSymbols symbols = new DateFormatSymbols(this , locale);
3056: return new SimpleDateFormat(pattern, symbols, locale);
3057: }
3058:
3059: static private DateFormat formatHelper(Calendar cal, ULocale loc,
3060: int dateStyle, int timeStyle) {
3061: // See if there are any custom resources for this calendar
3062: // If not, just use the default DateFormat
3063: DateFormat result = null;
3064:
3065: try {
3066: CalendarData calData = new CalendarData(loc, cal.getType());
3067: String[] patterns = calData.get("DateTimePatterns")
3068: .getStringArray();
3069:
3070: String pattern = null;
3071: if ((timeStyle >= 0) && (dateStyle >= 0)) {
3072: Object[] dateTimeArgs = { patterns[timeStyle],
3073: patterns[dateStyle + 4] };
3074: pattern = MessageFormat.format(patterns[8],
3075: dateTimeArgs);
3076: } else if (timeStyle >= 0) {
3077: pattern = patterns[timeStyle];
3078: } else if (dateStyle >= 0) {
3079: pattern = patterns[dateStyle + 4];
3080: } else {
3081: throw new IllegalArgumentException(
3082: "No date or time style specified");
3083: }
3084: result = cal.handleGetDateFormat(pattern, loc);
3085: } catch (MissingResourceException e) {
3086: // !!! need dateformat subclass appropriate to calendar type here!
3087: // No custom patterns
3088: // !!! note: possible circularity here, if getDateTimeInstance calls us because of
3089: // loc specifying a calendar.
3090: result = DateFormat.getDateTimeInstance(dateStyle,
3091: timeStyle, loc);
3092:
3093: DateFormatSymbols symbols = new DateFormatSymbols(cal, loc);
3094: ((SimpleDateFormat) result).setDateFormatSymbols(symbols); // aliu
3095: }
3096: result.setCalendar(cal);
3097: return result;
3098: }
3099:
3100: //-------------------------------------------------------------------------
3101: // Protected utility methods for use by subclasses. These are very handy
3102: // for implementing add, roll, and computeFields.
3103: //-------------------------------------------------------------------------
3104:
3105: /**
3106: * Adjust the specified field so that it is within
3107: * the allowable range for the date to which this calendar is set.
3108: * For example, in a Gregorian calendar pinning the {@link #DAY_OF_MONTH DAY_OF_MONTH}
3109: * field for a calendar set to April 31 would cause it to be set
3110: * to April 30.
3111: * <p>
3112: * <b>Subclassing:</b>
3113: * <br>
3114: * This utility method is intended for use by subclasses that need to implement
3115: * their own overrides of {@link #roll roll} and {@link #add add}.
3116: * <p>
3117: * <b>Note:</b>
3118: * <code>pinField</code> is implemented in terms of
3119: * {@link #getActualMinimum getActualMinimum}
3120: * and {@link #getActualMaximum getActualMaximum}. If either of those methods uses
3121: * a slow, iterative algorithm for a particular field, it would be
3122: * unwise to attempt to call <code>pinField</code> for that field. If you
3123: * really do need to do so, you should override this method to do
3124: * something more efficient for that field.
3125: * <p>
3126: * @param field The calendar field whose value should be pinned.
3127: *
3128: * @see #getActualMinimum
3129: * @see #getActualMaximum
3130: * @stable ICU 2.0
3131: */
3132: protected void pinField(int field) {
3133: int max = getActualMaximum(field);
3134: int min = getActualMinimum(field);
3135:
3136: if (fields[field] > max) {
3137: set(field, max);
3138: } else if (fields[field] < min) {
3139: set(field, min);
3140: }
3141: }
3142:
3143: /**
3144: * Return the week number of a day, within a period. This may be the week number in
3145: * a year or the week number in a month. Usually this will be a value >= 1, but if
3146: * some initial days of the period are excluded from week 1, because
3147: * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} is > 1, then
3148: * the week number will be zero for those
3149: * initial days. This method requires the day number and day of week for some
3150: * known date in the period in order to determine the day of week
3151: * on the desired day.
3152: * <p>
3153: * <b>Subclassing:</b>
3154: * <br>
3155: * This method is intended for use by subclasses in implementing their
3156: * {@link #computeTime computeTime} and/or {@link #computeFields computeFields} methods.
3157: * It is often useful in {@link #getActualMinimum getActualMinimum} and
3158: * {@link #getActualMaximum getActualMaximum} as well.
3159: * <p>
3160: * This variant is handy for computing the week number of some other
3161: * day of a period (often the first or last day of the period) when its day
3162: * of the week is not known but the day number and day of week for some other
3163: * day in the period (e.g. the current date) <em>is</em> known.
3164: * <p>
3165: * @param desiredDay The {@link #DAY_OF_YEAR DAY_OF_YEAR} or
3166: * {@link #DAY_OF_MONTH DAY_OF_MONTH} whose week number is desired.
3167: * Should be 1 for the first day of the period.
3168: *
3169: * @param dayOfPeriod The {@link #DAY_OF_YEAR DAY_OF_YEAR}
3170: * or {@link #DAY_OF_MONTH DAY_OF_MONTH} for a day in the period whose
3171: * {@link #DAY_OF_WEEK DAY_OF_WEEK} is specified by the
3172: * <code>dayOfWeek</code> parameter.
3173: * Should be 1 for first day of period.
3174: *
3175: * @param dayOfWeek The {@link #DAY_OF_WEEK DAY_OF_WEEK} for the day
3176: * corresponding to the <code>dayOfPeriod</code> parameter.
3177: * 1-based with 1=Sunday.
3178: *
3179: * @return The week number (one-based), or zero if the day falls before
3180: * the first week because
3181: * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek}
3182: * is more than one.
3183: * @stable ICU 2.0
3184: */
3185: protected int weekNumber(int desiredDay, int dayOfPeriod,
3186: int dayOfWeek) {
3187: // Determine the day of the week of the first day of the period
3188: // in question (either a year or a month). Zero represents the
3189: // first day of the week on this calendar.
3190: int periodStartDayOfWeek = (dayOfWeek - getFirstDayOfWeek()
3191: - dayOfPeriod + 1) % 7;
3192: if (periodStartDayOfWeek < 0)
3193: periodStartDayOfWeek += 7;
3194:
3195: // Compute the week number. Initially, ignore the first week, which
3196: // may be fractional (or may not be). We add periodStartDayOfWeek in
3197: // order to fill out the first week, if it is fractional.
3198: int weekNo = (desiredDay + periodStartDayOfWeek - 1) / 7;
3199:
3200: // If the first week is long enough, then count it. If
3201: // the minimal days in the first week is one, or if the period start
3202: // is zero, we always increment weekNo.
3203: if ((7 - periodStartDayOfWeek) >= getMinimalDaysInFirstWeek())
3204: ++weekNo;
3205:
3206: return weekNo;
3207: }
3208:
3209: /**
3210: * Return the week number of a day, within a period. This may be the week number in
3211: * a year, or the week number in a month. Usually this will be a value >= 1, but if
3212: * some initial days of the period are excluded from week 1, because
3213: * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} is > 1,
3214: * then the week number will be zero for those
3215: * initial days. This method requires the day of week for the given date in order to
3216: * determine the result.
3217: * <p>
3218: * <b>Subclassing:</b>
3219: * <br>
3220: * This method is intended for use by subclasses in implementing their
3221: * {@link #computeTime computeTime} and/or {@link #computeFields computeFields} methods.
3222: * It is often useful in {@link #getActualMinimum getActualMinimum} and
3223: * {@link #getActualMaximum getActualMaximum} as well.
3224: * <p>
3225: * @param dayOfPeriod The {@link #DAY_OF_YEAR DAY_OF_YEAR} or
3226: * {@link #DAY_OF_MONTH DAY_OF_MONTH} whose week number is desired.
3227: * Should be 1 for the first day of the period.
3228: *
3229: * @param dayOfWeek The {@link #DAY_OF_WEEK DAY_OF_WEEK} for the day
3230: * corresponding to the <code>dayOfPeriod</code> parameter.
3231: * 1-based with 1=Sunday.
3232: *
3233: * @return The week number (one-based), or zero if the day falls before
3234: * the first week because
3235: * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek}
3236: * is more than one.
3237: * @stable ICU 2.0
3238: */
3239: protected final int weekNumber(int dayOfPeriod, int dayOfWeek) {
3240: return weekNumber(dayOfPeriod, dayOfPeriod, dayOfWeek);
3241: }
3242:
3243: //-------------------------------------------------------------------------
3244: // Constants
3245: //-------------------------------------------------------------------------
3246:
3247: /**
3248: * [NEW]
3249: * Return the difference between the given time and the time this
3250: * calendar object is set to. If this calendar is set
3251: * <em>before</em> the given time, the returned value will be
3252: * positive. If this calendar is set <em>after</em> the given
3253: * time, the returned value will be negative. The
3254: * <code>field</code> parameter specifies the units of the return
3255: * value. For example, if <code>fieldDifference(when,
3256: * Calendar.MONTH)</code> returns 3, then this calendar is set to
3257: * 3 months before <code>when</code>, and possibly some additional
3258: * time less than one month.
3259: *
3260: * <p>As a side effect of this call, this calendar is advanced
3261: * toward <code>when</code> by the given amount. That is, calling
3262: * this method has the side effect of calling <code>add(field,
3263: * n)</code>, where <code>n</code> is the return value.
3264: *
3265: * <p>Usage: To use this method, call it first with the largest
3266: * field of interest, then with progressively smaller fields. For
3267: * example:
3268: *
3269: * <pre>
3270: * int y = cal.fieldDifference(when, Calendar.YEAR);
3271: * int m = cal.fieldDifference(when, Calendar.MONTH);
3272: * int d = cal.fieldDifference(when, Calendar.DATE);</pre>
3273: *
3274: * computes the difference between <code>cal</code> and
3275: * <code>when</code> in years, months, and days.
3276: *
3277: * <p>Note: <code>fieldDifference()</code> is
3278: * <em>asymmetrical</em>. That is, in the following code:
3279: *
3280: * <pre>
3281: * cal.setTime(date1);
3282: * int m1 = cal.fieldDifference(date2, Calendar.MONTH);
3283: * int d1 = cal.fieldDifference(date2, Calendar.DATE);
3284: * cal.setTime(date2);
3285: * int m2 = cal.fieldDifference(date1, Calendar.MONTH);
3286: * int d2 = cal.fieldDifference(date1, Calendar.DATE);</pre>
3287: *
3288: * one might expect that <code>m1 == -m2 && d1 == -d2</code>.
3289: * However, this is not generally the case, because of
3290: * irregularities in the underlying calendar system (e.g., the
3291: * Gregorian calendar has a varying number of days per month).
3292: *
3293: * @param when the date to compare this calendar's time to
3294: * @param field the field in which to compute the result
3295: * @return the difference, either positive or negative, between
3296: * this calendar's time and <code>when</code>, in terms of
3297: * <code>field</code>.
3298: * @stable ICU 2.0
3299: */
3300: public int fieldDifference(Date when, int field) {
3301: int min = 0;
3302: long startMs = getTimeInMillis();
3303: long targetMs = when.getTime();
3304: // Always add from the start millis. This accomodates
3305: // operations like adding years from February 29, 2000 up to
3306: // February 29, 2004. If 1, 1, 1, 1 is added to the year
3307: // field, the DOM gets pinned to 28 and stays there, giving an
3308: // incorrect DOM difference of 1. We have to add 1, reset, 2,
3309: // reset, 3, reset, 4.
3310: if (startMs < targetMs) {
3311: int max = 1;
3312: // Find a value that is too large
3313: for (;;) {
3314: setTimeInMillis(startMs);
3315: add(field, max);
3316: long ms = getTimeInMillis();
3317: if (ms == targetMs) {
3318: return max;
3319: } else if (ms > targetMs) {
3320: break;
3321: } else {
3322: max <<= 1;
3323: if (max < 0) {
3324: // Field difference too large to fit into int
3325: throw new RuntimeException();
3326: }
3327: }
3328: }
3329: // Do a binary search
3330: while ((max - min) > 1) {
3331: int t = (min + max) / 2;
3332: setTimeInMillis(startMs);
3333: add(field, t);
3334: long ms = getTimeInMillis();
3335: if (ms == targetMs) {
3336: return t;
3337: } else if (ms > targetMs) {
3338: max = t;
3339: } else {
3340: min = t;
3341: }
3342: }
3343: } else if (startMs > targetMs) {
3344: if (false) {
3345: // This works, and makes the code smaller, but costs
3346: // an extra object creation and an extra couple cycles
3347: // of calendar computation.
3348: setTimeInMillis(targetMs);
3349: min = -fieldDifference(new Date(startMs), field);
3350: }
3351: int max = -1;
3352: // Find a value that is too small
3353: for (;;) {
3354: setTimeInMillis(startMs);
3355: add(field, max);
3356: long ms = getTimeInMillis();
3357: if (ms == targetMs) {
3358: return max;
3359: } else if (ms < targetMs) {
3360: break;
3361: } else {
3362: max <<= 1;
3363: if (max == 0) {
3364: // Field difference too large to fit into int
3365: throw new RuntimeException();
3366: }
3367: }
3368: }
3369: // Do a binary search
3370: while ((min - max) > 1) {
3371: int t = (min + max) / 2;
3372: setTimeInMillis(startMs);
3373: add(field, t);
3374: long ms = getTimeInMillis();
3375: if (ms == targetMs) {
3376: return t;
3377: } else if (ms < targetMs) {
3378: max = t;
3379: } else {
3380: min = t;
3381: }
3382: }
3383: }
3384: // Set calendar to end point
3385: setTimeInMillis(startMs);
3386: add(field, min);
3387: return min;
3388: }
3389:
3390: /**
3391: * Sets the time zone with the given time zone value.
3392: * @param value the given time zone.
3393: * @stable ICU 2.0
3394: */
3395: public void setTimeZone(TimeZone value) {
3396: zone = value;
3397: /* Recompute the fields from the time using the new zone. This also
3398: * works if isTimeSet is false (after a call to set()). In that case
3399: * the time will be computed from the fields using the new zone, then
3400: * the fields will get recomputed from that. Consider the sequence of
3401: * calls: cal.setTimeZone(EST); cal.set(HOUR, 1); cal.setTimeZone(PST).
3402: * Is cal set to 1 o'clock EST or 1 o'clock PST? Answer: PST. More
3403: * generally, a call to setTimeZone() affects calls to set() BEFORE AND
3404: * AFTER it up to the next call to complete().
3405: */
3406: areFieldsSet = false;
3407: }
3408:
3409: /**
3410: * Gets the time zone.
3411: * @return the time zone object associated with this calendar.
3412: * @stable ICU 2.0
3413: */
3414: public TimeZone getTimeZone() {
3415: return zone;
3416: }
3417:
3418: /**
3419: * Specify whether or not date/time interpretation is to be lenient. With
3420: * lenient interpretation, a date such as "February 942, 1996" will be
3421: * treated as being equivalent to the 941st day after February 1, 1996.
3422: * With strict interpretation, such dates will cause an exception to be
3423: * thrown.
3424: *
3425: * @see DateFormat#setLenient
3426: * @stable ICU 2.0
3427: */
3428: public void setLenient(boolean lenient) {
3429: this .lenient = lenient;
3430: }
3431:
3432: /**
3433: * Tell whether date/time interpretation is to be lenient.
3434: * @stable ICU 2.0
3435: */
3436: public boolean isLenient() {
3437: return lenient;
3438: }
3439:
3440: /**
3441: * Sets what the first day of the week is; e.g., Sunday in US,
3442: * Monday in France.
3443: * @param value the given first day of the week.
3444: * @stable ICU 2.0
3445: */
3446: public void setFirstDayOfWeek(int value) {
3447: if (firstDayOfWeek != value) {
3448: if (value < SUNDAY || value > SATURDAY) {
3449: throw new IllegalArgumentException(
3450: "Invalid day of week");
3451: }
3452: firstDayOfWeek = value;
3453: areFieldsSet = false;
3454: }
3455: }
3456:
3457: /**
3458: * Gets what the first day of the week is; e.g., Sunday in US,
3459: * Monday in France.
3460: * @return the first day of the week.
3461: * @stable ICU 2.0
3462: */
3463: public int getFirstDayOfWeek() {
3464: return firstDayOfWeek;
3465: }
3466:
3467: /**
3468: * Sets what the minimal days required in the first week of the year are.
3469: * For example, if the first week is defined as one that contains the first
3470: * day of the first month of a year, call the method with value 1. If it
3471: * must be a full week, use value 7.
3472: * @param value the given minimal days required in the first week
3473: * of the year.
3474: * @stable ICU 2.0
3475: */
3476: public void setMinimalDaysInFirstWeek(int value) {
3477: // Values less than 1 have the same effect as 1; values greater
3478: // than 7 have the same effect as 7. However, we normalize values
3479: // so operator== and so forth work.
3480: if (value < 1) {
3481: value = 1;
3482: } else if (value > 7) {
3483: value = 7;
3484: }
3485: if (minimalDaysInFirstWeek != value) {
3486: minimalDaysInFirstWeek = value;
3487: areFieldsSet = false;
3488: }
3489: }
3490:
3491: /**
3492: * Gets what the minimal days required in the first week of the year are;
3493: * e.g., if the first week is defined as one that contains the first day
3494: * of the first month of a year, getMinimalDaysInFirstWeek returns 1. If
3495: * the minimal days required must be a full week, getMinimalDaysInFirstWeek
3496: * returns 7.
3497: * @return the minimal days required in the first week of the year.
3498: * @stable ICU 2.0
3499: */
3500: public int getMinimalDaysInFirstWeek() {
3501: return minimalDaysInFirstWeek;
3502: }
3503:
3504: private static final int LIMITS[][] = {
3505: // Minimum Greatest min Least max Greatest max
3506: {/* */}, // ERA
3507: {/* */}, // YEAR
3508: {/* */}, // MONTH
3509: {/* */}, // WEEK_OF_YEAR
3510: {/* */}, // WEEK_OF_MONTH
3511: {/* */}, // DAY_OF_MONTH
3512: {/* */}, // DAY_OF_YEAR
3513: { 1, 1, 7, 7 }, // DAY_OF_WEEK
3514: {/* */}, // DAY_OF_WEEK_IN_MONTH
3515: { 0, 0, 1, 1 }, // AM_PM
3516: { 0, 0, 11, 11 }, // HOUR
3517: { 0, 0, 23, 23 }, // HOUR_OF_DAY
3518: { 0, 0, 59, 59 }, // MINUTE
3519: { 0, 0, 59, 59 }, // SECOND
3520: { 0, 0, 999, 999 }, // MILLISECOND
3521: { -12 * ONE_HOUR, -12 * ONE_HOUR, 12 * ONE_HOUR,
3522: 12 * ONE_HOUR }, // ZONE_OFFSET
3523: { 0, 0, 1 * ONE_HOUR, 1 * ONE_HOUR }, // DST_OFFSET
3524: {/* */}, // YEAR_WOY
3525: { 1, 1, 7, 7 }, // DOW_LOCAL
3526: {/* */}, // EXTENDED_YEAR
3527: { -0x7F000000, -0x7F000000, 0x7F000000, 0x7F000000 }, // JULIAN_DAY
3528: { 0, 0, 24 * ONE_HOUR - 1, 24 * ONE_HOUR - 1 }, // MILLISECONDS_IN_DAY
3529: };
3530:
3531: /**
3532: * Subclass API for defining limits of different types.
3533: * Subclasses must implement this method to return limits for the
3534: * following fields:
3535: *
3536: * <pre>ERA
3537: * YEAR
3538: * MONTH
3539: * WEEK_OF_YEAR
3540: * WEEK_OF_MONTH
3541: * DAY_OF_MONTH
3542: * DAY_OF_YEAR
3543: * DAY_OF_WEEK_IN_MONTH
3544: * YEAR_WOY
3545: * EXTENDED_YEAR</pre>
3546: *
3547: * @param field one of the above field numbers
3548: * @param limitType one of <code>MINIMUM</code>, <code>GREATEST_MINIMUM</code>,
3549: * <code>LEAST_MAXIMUM</code>, or <code>MAXIMUM</code>
3550: * @stable ICU 2.0
3551: */
3552: abstract protected int handleGetLimit(int field, int limitType);
3553:
3554: /**
3555: * Return a limit for a field.
3556: * @param field the field, from 0..</code>getFieldCount()-1</code>
3557: * @param limitType the type specifier for the limit
3558: * @see #MINIMUM
3559: * @see #GREATEST_MINIMUM
3560: * @see #LEAST_MAXIMUM
3561: * @see #MAXIMUM
3562: * @stable ICU 2.0
3563: */
3564: protected int getLimit(int field, int limitType) {
3565: switch (field) {
3566: case DAY_OF_WEEK:
3567: case AM_PM:
3568: case HOUR:
3569: case HOUR_OF_DAY:
3570: case MINUTE:
3571: case SECOND:
3572: case MILLISECOND:
3573: case ZONE_OFFSET:
3574: case DST_OFFSET:
3575: case DOW_LOCAL:
3576: case JULIAN_DAY:
3577: case MILLISECONDS_IN_DAY:
3578: return LIMITS[field][limitType];
3579: }
3580: return handleGetLimit(field, limitType);
3581: }
3582:
3583: /**
3584: * Limit type for <code>getLimit()</code> and <code>handleGetLimit()</code>
3585: * indicating the minimum value that a field can take (least minimum).
3586: * @see #getLimit
3587: * @see #handleGetLimit
3588: * @stable ICU 2.0
3589: */
3590: protected static final int MINIMUM = 0;
3591:
3592: /**
3593: * Limit type for <code>getLimit()</code> and <code>handleGetLimit()</code>
3594: * indicating the greatest minimum value that a field can take.
3595: * @see #getLimit
3596: * @see #handleGetLimit
3597: * @stable ICU 2.0
3598: */
3599: protected static final int GREATEST_MINIMUM = 1;
3600:
3601: /**
3602: * Limit type for <code>getLimit()</code> and <code>handleGetLimit()</code>
3603: * indicating the least maximum value that a field can take.
3604: * @see #getLimit
3605: * @see #handleGetLimit
3606: * @stable ICU 2.0
3607: */
3608: protected static final int LEAST_MAXIMUM = 2;
3609:
3610: /**
3611: * Limit type for <code>getLimit()</code> and <code>handleGetLimit()</code>
3612: * indicating the maximum value that a field can take (greatest maximum).
3613: * @see #getLimit
3614: * @see #handleGetLimit
3615: * @stable ICU 2.0
3616: */
3617: protected static final int MAXIMUM = 3;
3618:
3619: /**
3620: * Gets the minimum value for the given time field.
3621: * e.g., for Gregorian DAY_OF_MONTH, 1.
3622: * @param field the given time field.
3623: * @return the minimum value for the given time field.
3624: * @stable ICU 2.0
3625: */
3626: public final int getMinimum(int field) {
3627: return getLimit(field, MINIMUM);
3628: }
3629:
3630: /**
3631: * Gets the maximum value for the given time field.
3632: * e.g. for Gregorian DAY_OF_MONTH, 31.
3633: * @param field the given time field.
3634: * @return the maximum value for the given time field.
3635: * @stable ICU 2.0
3636: */
3637: public final int getMaximum(int field) {
3638: return getLimit(field, MAXIMUM);
3639: }
3640:
3641: /**
3642: * Gets the highest minimum value for the given field if varies.
3643: * Otherwise same as getMinimum(). For Gregorian, no difference.
3644: * @param field the given time field.
3645: * @return the highest minimum value for the given time field.
3646: * @stable ICU 2.0
3647: */
3648: public final int getGreatestMinimum(int field) {
3649: return getLimit(field, GREATEST_MINIMUM);
3650: }
3651:
3652: /**
3653: * Gets the lowest maximum value for the given field if varies.
3654: * Otherwise same as getMaximum(). e.g., for Gregorian DAY_OF_MONTH, 28.
3655: * @param field the given time field.
3656: * @return the lowest maximum value for the given time field.
3657: * @stable ICU 2.0
3658: */
3659: public final int getLeastMaximum(int field) {
3660: return getLimit(field, LEAST_MAXIMUM);
3661: }
3662:
3663: //-------------------------------------------------------------------------
3664: // Weekend support -- determining which days of the week are the weekend
3665: // in a given locale
3666: //-------------------------------------------------------------------------
3667:
3668: /**
3669: * Return whether the given day of the week is a weekday, a
3670: * weekend day, or a day that transitions from one to the other,
3671: * in this calendar system. If a transition occurs at midnight,
3672: * then the days before and after the transition will have the
3673: * type WEEKDAY or WEEKEND. If a transition occurs at a time
3674: * other than midnight, then the day of the transition will have
3675: * the type WEEKEND_ONSET or WEEKEND_CEASE. In this case, the
3676: * method getWeekendTransition() will return the point of
3677: * transition.
3678: * @param dayOfWeek either SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
3679: * THURSDAY, FRIDAY, or SATURDAY
3680: * @return either WEEKDAY, WEEKEND, WEEKEND_ONSET, or
3681: * WEEKEND_CEASE
3682: * @exception IllegalArgumentException if dayOfWeek is not
3683: * between SUNDAY and SATURDAY, inclusive
3684: * @see #WEEKDAY
3685: * @see #WEEKEND
3686: * @see #WEEKEND_ONSET
3687: * @see #WEEKEND_CEASE
3688: * @see #getWeekendTransition
3689: * @see #isWeekend(Date)
3690: * @see #isWeekend()
3691: * @stable ICU 2.0
3692: */
3693: public int getDayOfWeekType(int dayOfWeek) {
3694: if (dayOfWeek < SUNDAY || dayOfWeek > SATURDAY) {
3695: throw new IllegalArgumentException("Invalid day of week");
3696: }
3697: if (weekendOnset < weekendCease) {
3698: if (dayOfWeek < weekendOnset || dayOfWeek > weekendCease) {
3699: return WEEKDAY;
3700: }
3701: } else {
3702: if (dayOfWeek > weekendCease && dayOfWeek < weekendOnset) {
3703: return WEEKDAY;
3704: }
3705: }
3706: if (dayOfWeek == weekendOnset) {
3707: return (weekendOnsetMillis == 0) ? WEEKEND : WEEKEND_ONSET;
3708: }
3709: if (dayOfWeek == weekendCease) {
3710: return (weekendCeaseMillis == 0) ? WEEKDAY : WEEKEND_CEASE;
3711: }
3712: return WEEKEND;
3713: }
3714:
3715: /**
3716: * Return the time during the day at which the weekend begins or end in
3717: * this calendar system. If getDayOfWeekType(dayOfWeek) ==
3718: * WEEKEND_ONSET return the time at which the weekend begins. If
3719: * getDayOfWeekType(dayOfWeek) == WEEKEND_CEASE return the time at
3720: * which the weekend ends. If getDayOfWeekType(dayOfWeek) has some
3721: * other value, then throw an exception.
3722: * @param dayOfWeek either SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
3723: * THURSDAY, FRIDAY, or SATURDAY
3724: * @return the milliseconds after midnight at which the
3725: * weekend begins or ends
3726: * @exception IllegalArgumentException if dayOfWeek is not
3727: * WEEKEND_ONSET or WEEKEND_CEASE
3728: * @see #getDayOfWeekType
3729: * @see #isWeekend(Date)
3730: * @see #isWeekend()
3731: * @stable ICU 2.0
3732: */
3733: public int getWeekendTransition(int dayOfWeek) {
3734: if (dayOfWeek == weekendOnset) {
3735: return weekendOnsetMillis;
3736: } else if (dayOfWeek == weekendCease) {
3737: return weekendCeaseMillis;
3738: }
3739: throw new IllegalArgumentException("Not weekend transition day");
3740: }
3741:
3742: /**
3743: * Return true if the given date and time is in the weekend in
3744: * this calendar system. Equivalent to calling setTime() followed
3745: * by isWeekend(). Note: This method changes the time this
3746: * calendar is set to.
3747: * @param date the date and time
3748: * @return true if the given date and time is part of the
3749: * weekend
3750: * @see #getDayOfWeekType
3751: * @see #getWeekendTransition
3752: * @see #isWeekend()
3753: * @stable ICU 2.0
3754: */
3755: public boolean isWeekend(Date date) {
3756: setTime(date);
3757: return isWeekend();
3758: }
3759:
3760: /**
3761: * Return true if this Calendar's current date and time is in the
3762: * weekend in this calendar system.
3763: * @return true if the given date and time is part of the
3764: * weekend
3765: * @see #getDayOfWeekType
3766: * @see #getWeekendTransition
3767: * @see #isWeekend(Date)
3768: * @stable ICU 2.0
3769: */
3770: public boolean isWeekend() {
3771: int dow = get(DAY_OF_WEEK);
3772: int dowt = getDayOfWeekType(dow);
3773: switch (dowt) {
3774: case WEEKDAY:
3775: return false;
3776: case WEEKEND:
3777: return true;
3778: default: // That is, WEEKEND_ONSET or WEEKEND_CEASE
3779: // Use internalGet() because the above call to get() populated
3780: // all fields.
3781: // [Note: There should be a better way to get millis in day.
3782: // For ICU4J, submit request for a MILLIS_IN_DAY field
3783: // and a DAY_NUMBER field (could be Julian day #). - aliu]
3784: int millisInDay = internalGet(MILLISECOND)
3785: + 1000
3786: * (internalGet(SECOND) + 60 * (internalGet(MINUTE) + 60 * internalGet(HOUR_OF_DAY)));
3787: int transition = getWeekendTransition(dow);
3788: return (dowt == WEEKEND_ONSET) ? (millisInDay >= transition)
3789: : (millisInDay < transition);
3790: }
3791: // (We can never reach this point.)
3792: }
3793:
3794: //-------------------------------------------------------------------------
3795: // End of weekend support
3796: //-------------------------------------------------------------------------
3797:
3798: /**
3799: * Overrides Cloneable
3800: * @stable ICU 2.0
3801: */
3802: public Object clone() {
3803: try {
3804: Calendar other = (Calendar) super .clone();
3805:
3806: other.fields = new int[fields.length];
3807: other.stamp = new int[fields.length];
3808: System.arraycopy(this .fields, 0, other.fields, 0,
3809: fields.length);
3810: System.arraycopy(this .stamp, 0, other.stamp, 0,
3811: fields.length);
3812:
3813: other.zone = (TimeZone) zone.clone();
3814: return other;
3815: } catch (CloneNotSupportedException e) {
3816: // this shouldn't happen, since we are Cloneable
3817: throw new IllegalStateException();
3818: }
3819: }
3820:
3821: /**
3822: * Return a string representation of this calendar. This method
3823: * is intended to be used only for debugging purposes, and the
3824: * format of the returned string may vary between implementations.
3825: * The returned string may be empty but may not be <code>null</code>.
3826: *
3827: * @return a string representation of this calendar.
3828: * @stable ICU 2.0
3829: */
3830: public String toString() {
3831: StringBuffer buffer = new StringBuffer();
3832: buffer.append(getClass().getName());
3833: buffer.append("[time=");
3834: buffer.append(isTimeSet ? String.valueOf(time) : "?");
3835: buffer.append(",areFieldsSet=");
3836: buffer.append(areFieldsSet);
3837: buffer.append(",areAllFieldsSet=");
3838: buffer.append(areAllFieldsSet);
3839: buffer.append(",lenient=");
3840: buffer.append(lenient);
3841: buffer.append(",zone=");
3842: buffer.append(zone);
3843: buffer.append(",firstDayOfWeek=");
3844: buffer.append(firstDayOfWeek);
3845: buffer.append(",minimalDaysInFirstWeek=");
3846: buffer.append(minimalDaysInFirstWeek);
3847: for (int i = 0; i < fields.length; ++i) {
3848: buffer.append(',').append(FIELD_NAME[i]).append('=');
3849: buffer.append(isSet(i) ? String.valueOf(fields[i]) : "?");
3850: }
3851: buffer.append(']');
3852: return buffer.toString();
3853: }
3854:
3855: // =======================privates===============================
3856:
3857: /**
3858: * Internal class that holds cached locale data.
3859: */
3860: private static class WeekData {
3861: public int firstDayOfWeek;
3862: public int minimalDaysInFirstWeek;
3863: public int weekendOnset;
3864: public int weekendOnsetMillis;
3865: public int weekendCease;
3866: public int weekendCeaseMillis;
3867: public ULocale actualLocale;
3868:
3869: public WeekData(int fdow, int mdifw, int weekendOnset,
3870: int weekendOnsetMillis, int weekendCease,
3871: int weekendCeaseMillis, ULocale actualLoc) {
3872: this .firstDayOfWeek = fdow;
3873: this .minimalDaysInFirstWeek = mdifw;
3874: this .actualLocale = actualLoc;
3875: this .weekendOnset = weekendOnset;
3876: this .weekendOnsetMillis = weekendOnsetMillis;
3877: this .weekendCease = weekendCease;
3878: this .weekendCeaseMillis = weekendCeaseMillis;
3879: }
3880: }
3881:
3882: /**
3883: * Set this calendar to contain week and weekend data for the given
3884: * locale.
3885: * @param locale the locale
3886: */
3887: private void setWeekData(ULocale locale) {
3888: /* try to get the Locale data from the cache */
3889: WeekData data = (WeekData) cachedLocaleData.get(locale);
3890:
3891: if (data == null) { /* cache miss */
3892:
3893: CalendarData calData = new CalendarData(locale, getType());
3894: int[] dateTimeElements = calData.get("DateTimeElements")
3895: .getIntVector();
3896: int[] weekend = calData.get("weekend").getIntVector();
3897: data = new WeekData(dateTimeElements[0],
3898: dateTimeElements[1], weekend[0], weekend[1],
3899: weekend[2], weekend[3], calData.getULocale());
3900: /* cache update */
3901: cachedLocaleData.put(locale, data);
3902: }
3903: setFirstDayOfWeek(data.firstDayOfWeek);
3904: setMinimalDaysInFirstWeek(data.minimalDaysInFirstWeek);
3905: weekendOnset = data.weekendOnset;
3906: weekendOnsetMillis = data.weekendOnsetMillis;
3907: weekendCease = data.weekendCease;
3908: weekendCeaseMillis = data.weekendCeaseMillis;
3909:
3910: // TODO: determine the actual/valid locale
3911: ULocale uloc = data.actualLocale;
3912: setLocale(uloc, uloc);
3913: }
3914:
3915: /**
3916: * Recompute the time and update the status fields isTimeSet
3917: * and areFieldsSet. Callers should check isTimeSet and only
3918: * call this method if isTimeSet is false.
3919: */
3920: private void updateTime() {
3921: computeTime();
3922: // If we are lenient, we need to recompute the fields to normalize
3923: // the values. Also, if we haven't set all the fields yet (i.e.,
3924: // in a newly-created object), we need to fill in the fields. [LIU]
3925: if (isLenient() || !areAllFieldsSet)
3926: areFieldsSet = false;
3927: isTimeSet = true;
3928: areFieldsVirtuallySet = false;
3929: }
3930:
3931: /**
3932: * Save the state of this object to a stream (i.e., serialize it).
3933: *
3934: * Ideally, <code>Calendar</code> would only write out its state data and
3935: * the current time, and not write any field data out, such as
3936: * <code>fields[]</code>, <code>isTimeSet</code>, <code>areFieldsSet</code>,
3937: * and <code>isSet[]</code>. <code>nextStamp</code> also should not be part
3938: * of the persistent state. Unfortunately, this didn't happen before JDK 1.1
3939: * shipped. To be compatible with JDK 1.1, we will always have to write out
3940: * the field values and state flags. However, <code>nextStamp</code> can be
3941: * removed from the serialization stream; this will probably happen in the
3942: * near future.
3943: */
3944: private void writeObject(ObjectOutputStream stream)
3945: throws IOException {
3946: // Try to compute the time correctly, for the future (stream
3947: // version 2) in which we don't write out fields[] or isSet[].
3948: if (!isTimeSet) {
3949: try {
3950: updateTime();
3951: } catch (IllegalArgumentException e) {
3952: }
3953: }
3954:
3955: // Write out the 1.1 FCS object.
3956: stream.defaultWriteObject();
3957: }
3958:
3959: /**
3960: * Reconstitute this object from a stream (i.e., deserialize it).
3961: */
3962: private void readObject(ObjectInputStream stream)
3963: throws IOException, ClassNotFoundException {
3964:
3965: stream.defaultReadObject();
3966:
3967: initInternal();
3968:
3969: isTimeSet = true;
3970: areFieldsSet = areAllFieldsSet = false;
3971: nextStamp = MINIMUM_USER_STAMP;
3972: }
3973:
3974: //----------------------------------------------------------------------
3975: // Time -> Fields
3976: //----------------------------------------------------------------------
3977:
3978: /**
3979: * Converts the current millisecond time value <code>time</code> to
3980: * field values in <code>fields[]</code>. This synchronizes the time
3981: * field values with a new time that is set for the calendar. The time
3982: * is <em>not</em> recomputed first; to recompute the time, then the
3983: * fields, call the <code>complete</code> method.
3984: * @see #complete
3985: * @stable ICU 2.0
3986: */
3987: protected void computeFields() {
3988: int offsets[] = new int[2];
3989: getTimeZone().getOffset(time, false, offsets);
3990: long localMillis = time + offsets[0] + offsets[1];
3991:
3992: // Mark fields as set. Do this before calling handleComputeFields().
3993: int mask = internalSetMask;
3994: for (int i = 0; i < fields.length; ++i) {
3995: if ((mask & 1) == 0) {
3996: stamp[i] = INTERNALLY_SET;
3997: } else {
3998: stamp[i] = UNSET;
3999: }
4000: mask >>= 1;
4001: }
4002:
4003: // We used to check for and correct extreme millis values (near
4004: // Long.MIN_VALUE or Long.MAX_VALUE) here. Such values would cause
4005: // overflows from positive to negative (or vice versa) and had to
4006: // be manually tweaked. We no longer need to do this because we
4007: // have limited the range of supported dates to those that have a
4008: // Julian day that fits into an int. This allows us to implement a
4009: // JULIAN_DAY field and also removes some inelegant code. - Liu
4010: // 11/6/00
4011:
4012: long days = floorDivide(localMillis, ONE_DAY);
4013:
4014: fields[JULIAN_DAY] = (int) days + EPOCH_JULIAN_DAY;
4015:
4016: // In some cases we will have to call this method again below to
4017: // adjust for DST pushing us into the next Julian day.
4018: computeGregorianAndDOWFields(fields[JULIAN_DAY]);
4019:
4020: // Call framework method to have subclass compute its fields.
4021: // These must include, at a minimum, MONTH, DAY_OF_MONTH,
4022: // EXTENDED_YEAR, YEAR, DAY_OF_YEAR. This method will call internalSet(),
4023: // which will update stamp[].
4024: handleComputeFields(fields[JULIAN_DAY]);
4025:
4026: // Compute week-related fields, based on the subclass-computed
4027: // fields computed by handleComputeFields().
4028: computeWeekFields();
4029:
4030: // Compute time-related fields. These are indepent of the date and
4031: // of the subclass algorithm. They depend only on the local zone
4032: // wall milliseconds in day.
4033: int millisInDay = (int) (localMillis - (days * ONE_DAY));
4034: fields[MILLISECONDS_IN_DAY] = millisInDay;
4035: fields[MILLISECOND] = millisInDay % 1000;
4036: millisInDay /= 1000;
4037: fields[SECOND] = millisInDay % 60;
4038: millisInDay /= 60;
4039: fields[MINUTE] = millisInDay % 60;
4040: millisInDay /= 60;
4041: fields[HOUR_OF_DAY] = millisInDay;
4042: fields[AM_PM] = millisInDay / 12; // Assume AM == 0
4043: fields[HOUR] = millisInDay % 12;
4044: fields[ZONE_OFFSET] = offsets[0];
4045: fields[DST_OFFSET] = offsets[1];
4046: }
4047:
4048: /**
4049: * Compute the Gregorian calendar year, month, and day of month from
4050: * the given Julian day. These values are not stored in fields, but in
4051: * member variables gregorianXxx. Also compute the DAY_OF_WEEK and
4052: * DOW_LOCAL fields.
4053: */
4054: private final void computeGregorianAndDOWFields(int julianDay) {
4055: computeGregorianFields(julianDay);
4056:
4057: // Compute day of week: JD 0 = Monday
4058: int dow = fields[DAY_OF_WEEK] = julianDayToDayOfWeek(julianDay);
4059:
4060: // Calculate 1-based localized day of week
4061: int dowLocal = dow - getFirstDayOfWeek() + 1;
4062: if (dowLocal < 1) {
4063: dowLocal += 7;
4064: }
4065: fields[DOW_LOCAL] = dowLocal;
4066: }
4067:
4068: /**
4069: * Compute the Gregorian calendar year, month, and day of month from the
4070: * Julian day. These values are not stored in fields, but in member
4071: * variables gregorianXxx. They are used for time zone computations and by
4072: * subclasses that are Gregorian derivatives. Subclasses may call this
4073: * method to perform a Gregorian calendar millis->fields computation.
4074: * To perform a Gregorian calendar fields->millis computation, call
4075: * computeGregorianMonthStart().
4076: * @see #computeGregorianMonthStart
4077: * @stable ICU 2.0
4078: */
4079: protected final void computeGregorianFields(int julianDay) {
4080: int year, month, dayOfMonth, dayOfYear;
4081:
4082: // The Gregorian epoch day is zero for Monday January 1, year 1.
4083: long gregorianEpochDay = julianDay - JAN_1_1_JULIAN_DAY;
4084:
4085: // Here we convert from the day number to the multiple radix
4086: // representation. We use 400-year, 100-year, and 4-year cycles.
4087: // For example, the 4-year cycle has 4 years + 1 leap day; giving
4088: // 1461 == 365*4 + 1 days.
4089: int[] rem = new int[1];
4090: int n400 = floorDivide(gregorianEpochDay, 146097, rem); // 400-year cycle length
4091: int n100 = floorDivide(rem[0], 36524, rem); // 100-year cycle length
4092: int n4 = floorDivide(rem[0], 1461, rem); // 4-year cycle length
4093: int n1 = floorDivide(rem[0], 365, rem);
4094: year = 400 * n400 + 100 * n100 + 4 * n4 + n1;
4095: dayOfYear = rem[0]; // zero-based day of year
4096: if (n100 == 4 || n1 == 4) {
4097: dayOfYear = 365; // Dec 31 at end of 4- or 400-yr cycle
4098: } else {
4099: ++year;
4100: }
4101:
4102: boolean isLeap = ((year & 0x3) == 0) && // equiv. to (year%4 == 0)
4103: (year % 100 != 0 || year % 400 == 0);
4104:
4105: int correction = 0;
4106: int march1 = isLeap ? 60 : 59; // zero-based DOY for March 1
4107: if (dayOfYear >= march1)
4108: correction = isLeap ? 1 : 2;
4109: month = (12 * (dayOfYear + correction) + 6) / 367; // zero-based month
4110: dayOfMonth = dayOfYear
4111: - GREGORIAN_MONTH_COUNT[month][isLeap ? 3 : 2] + 1; // one-based DOM
4112:
4113: gregorianYear = year;
4114: gregorianMonth = month; // 0-based already
4115: gregorianDayOfMonth = dayOfMonth; // 1-based already
4116: gregorianDayOfYear = dayOfYear + 1; // Convert from 0-based to 1-based
4117: }
4118:
4119: /**
4120: * Compute the fields WEEK_OF_YEAR, YEAR_WOY, WEEK_OF_MONTH,
4121: * DAY_OF_WEEK_IN_MONTH, and DOW_LOCAL from EXTENDED_YEAR, YEAR,
4122: * DAY_OF_WEEK, and DAY_OF_YEAR. The latter fields are computed by the
4123: * subclass based on the calendar system.
4124: *
4125: * <p>The YEAR_WOY field is computed simplistically. It is equal to YEAR
4126: * most of the time, but at the year boundary it may be adjusted to YEAR-1
4127: * or YEAR+1 to reflect the overlap of a week into an adjacent year. In
4128: * this case, a simple increment or decrement is performed on YEAR, even
4129: * though this may yield an invalid YEAR value. For instance, if the YEAR
4130: * is part of a calendar system with an N-year cycle field CYCLE, then
4131: * incrementing the YEAR may involve incrementing CYCLE and setting YEAR
4132: * back to 0 or 1. This is not handled by this code, and in fact cannot be
4133: * simply handled without having subclasses define an entire parallel set of
4134: * fields for fields larger than or equal to a year. This additional
4135: * complexity is not warranted, since the intention of the YEAR_WOY field is
4136: * to support ISO 8601 notation, so it will typically be used with a
4137: * proleptic Gregorian calendar, which has no field larger than a year.
4138: */
4139: private final void computeWeekFields() {
4140: int eyear = fields[EXTENDED_YEAR];
4141: int year = fields[YEAR];
4142: int dayOfWeek = fields[DAY_OF_WEEK];
4143: int dayOfYear = fields[DAY_OF_YEAR];
4144:
4145: // WEEK_OF_YEAR start
4146: // Compute the week of the year. For the Gregorian calendar, valid week
4147: // numbers run from 1 to 52 or 53, depending on the year, the first day
4148: // of the week, and the minimal days in the first week. For other
4149: // calendars, the valid range may be different -- it depends on the year
4150: // length. Days at the start of the year may fall into the last week of
4151: // the previous year; days at the end of the year may fall into the
4152: // first week of the next year. ASSUME that the year length is less than
4153: // 7000 days.
4154: int yearOfWeekOfYear = year;
4155: int relDow = (dayOfWeek + 7 - getFirstDayOfWeek()) % 7; // 0..6
4156: int relDowJan1 = (dayOfWeek - dayOfYear + 7001 - getFirstDayOfWeek()) % 7; // 0..6
4157: int woy = (dayOfYear - 1 + relDowJan1) / 7; // 0..53
4158: if ((7 - relDowJan1) >= getMinimalDaysInFirstWeek()) {
4159: ++woy;
4160: }
4161:
4162: // Adjust for weeks at the year end that overlap into the previous or
4163: // next calendar year.
4164: if (woy == 0) {
4165: // We are the last week of the previous year.
4166: // Check to see if we are in the last week; if so, we need
4167: // to handle the case in which we are the first week of the
4168: // next year.
4169:
4170: int prevDoy = dayOfYear + handleGetYearLength(eyear - 1);
4171: woy = weekNumber(prevDoy, dayOfWeek);
4172: yearOfWeekOfYear--;
4173: } else {
4174: int lastDoy = handleGetYearLength(eyear);
4175: // Fast check: For it to be week 1 of the next year, the DOY
4176: // must be on or after L-5, where L is yearLength(), then it
4177: // cannot possibly be week 1 of the next year:
4178: // L-5 L
4179: // doy: 359 360 361 362 363 364 365 001
4180: // dow: 1 2 3 4 5 6 7
4181: if (dayOfYear >= (lastDoy - 5)) {
4182: int lastRelDow = (relDow + lastDoy - dayOfYear) % 7;
4183: if (lastRelDow < 0) {
4184: lastRelDow += 7;
4185: }
4186: if (((6 - lastRelDow) >= getMinimalDaysInFirstWeek())
4187: && ((dayOfYear + 7 - relDow) > lastDoy)) {
4188: woy = 1;
4189: yearOfWeekOfYear++;
4190: }
4191: }
4192: }
4193: fields[WEEK_OF_YEAR] = woy;
4194: fields[YEAR_WOY] = yearOfWeekOfYear;
4195: // WEEK_OF_YEAR end
4196:
4197: int dayOfMonth = fields[DAY_OF_MONTH];
4198: fields[WEEK_OF_MONTH] = weekNumber(dayOfMonth, dayOfWeek);
4199: fields[DAY_OF_WEEK_IN_MONTH] = (dayOfMonth - 1) / 7 + 1;
4200: }
4201:
4202: //----------------------------------------------------------------------
4203: // Fields -> Time
4204: //----------------------------------------------------------------------
4205:
4206: /**
4207: * Value to OR against resolve table field values for remapping.
4208: * @see #resolveFields
4209: * @stable ICU 2.0
4210: */
4211: protected static final int RESOLVE_REMAP = 32;
4212: // A power of 2 greater than or equal to MAX_FIELD_COUNT
4213:
4214: // Default table for day in year
4215: static final int[][][] DATE_PRECEDENCE = {
4216: { { DAY_OF_MONTH }, { WEEK_OF_YEAR, DAY_OF_WEEK },
4217: { WEEK_OF_MONTH, DAY_OF_WEEK },
4218: { DAY_OF_WEEK_IN_MONTH, DAY_OF_WEEK },
4219: { WEEK_OF_YEAR, DOW_LOCAL },
4220: { WEEK_OF_MONTH, DOW_LOCAL },
4221: { DAY_OF_WEEK_IN_MONTH, DOW_LOCAL },
4222: { DAY_OF_YEAR }, },
4223: {
4224: { WEEK_OF_YEAR },
4225: { WEEK_OF_MONTH },
4226: { DAY_OF_WEEK_IN_MONTH },
4227: { RESOLVE_REMAP | DAY_OF_WEEK_IN_MONTH, DAY_OF_WEEK },
4228: { RESOLVE_REMAP | DAY_OF_WEEK_IN_MONTH, DOW_LOCAL }, }, };
4229:
4230: static final int[][][] DOW_PRECEDENCE = { { { DAY_OF_WEEK },
4231: { DOW_LOCAL }, }, };
4232:
4233: /**
4234: * Given a precedence table, return the newest field combination in
4235: * the table, or -1 if none is found.
4236: *
4237: * <p>The precedence table is a 3-dimensional array of integers. It
4238: * may be thought of as an array of groups. Each group is an array of
4239: * lines. Each line is an array of field numbers. Within a line, if
4240: * all fields are set, then the time stamp of the line is taken to be
4241: * the stamp of the most recently set field. If any field of a line is
4242: * unset, then the line fails to match. Within a group, the line with
4243: * the newest time stamp is selected. The first field of the line is
4244: * returned to indicate which line matched.
4245: *
4246: * <p>In some cases, it may be desirable to map a line to field that
4247: * whose stamp is NOT examined. For example, if the best field is
4248: * DAY_OF_WEEK then the DAY_OF_WEEK_IN_MONTH algorithm may be used. In
4249: * order to do this, insert the value <code>REMAP_RESOLVE | F</code> at
4250: * the start of the line, where <code>F</code> is the desired return
4251: * field value. This field will NOT be examined; it only determines
4252: * the return value if the other fields in the line are the newest.
4253: *
4254: * <p>If all lines of a group contain at least one unset field, then no
4255: * line will match, and the group as a whole will fail to match. In
4256: * that case, the next group will be processed. If all groups fail to
4257: * match, then -1 is returned.
4258: * @stable ICU 2.0
4259: */
4260: protected int resolveFields(int[][][] precedenceTable) {
4261: int bestField = -1;
4262: for (int g = 0; g < precedenceTable.length && bestField < 0; ++g) {
4263: int[][] group = precedenceTable[g];
4264: int bestStamp = UNSET;
4265: linesInGroup: for (int l = 0; l < group.length; ++l) {
4266: int[] line = group[l];
4267: int lineStamp = UNSET;
4268: // Skip over first entry if it is negative
4269: for (int i = (line[0] >= RESOLVE_REMAP) ? 1 : 0; i < line.length; ++i) {
4270: int s = stamp[line[i]];
4271: // If any field is unset then don't use this line
4272: if (s == UNSET) {
4273: continue linesInGroup;
4274: } else {
4275: lineStamp = Math.max(lineStamp, s);
4276: }
4277: }
4278: // Record new maximum stamp & field no.
4279: if (lineStamp > bestStamp) {
4280: bestStamp = lineStamp;
4281: bestField = line[0]; // First field refers to entire line
4282: }
4283: }
4284: }
4285: return (bestField >= RESOLVE_REMAP) ? (bestField & (RESOLVE_REMAP - 1))
4286: : bestField;
4287: }
4288:
4289: /**
4290: * Return the newest stamp of a given range of fields.
4291: * @stable ICU 2.0
4292: */
4293: protected int newestStamp(int first, int last, int bestStampSoFar) {
4294: int bestStamp = bestStampSoFar;
4295: for (int i = first; i <= last; ++i) {
4296: if (stamp[i] > bestStamp) {
4297: bestStamp = stamp[i];
4298: }
4299: }
4300: return bestStamp;
4301: }
4302:
4303: /**
4304: * Return the timestamp of a field.
4305: * @stable ICU 2.0
4306: */
4307: protected final int getStamp(int field) {
4308: return stamp[field];
4309: }
4310:
4311: /**
4312: * Return the field that is newer, either defaultField, or
4313: * alternateField. If neither is newer or neither is set, return defaultField.
4314: * @stable ICU 2.0
4315: */
4316: protected int newerField(int defaultField, int alternateField) {
4317: if (stamp[alternateField] > stamp[defaultField]) {
4318: return alternateField;
4319: }
4320: return defaultField;
4321: }
4322:
4323: /**
4324: * Ensure that each field is within its valid range by calling {@link
4325: * #validateField(int)} on each field that has been set. This method
4326: * should only be called if this calendar is not lenient.
4327: * @see #isLenient
4328: * @see #validateField(int)
4329: * @stable ICU 2.0
4330: */
4331: protected void validateFields() {
4332: for (int field = 0; field < fields.length; field++) {
4333: if (isSet(field)) {
4334: validateField(field);
4335: }
4336: }
4337: }
4338:
4339: /**
4340: * Validate a single field of this calendar. Subclasses should
4341: * override this method to validate any calendar-specific fields.
4342: * Generic fields can be handled by
4343: * <code>Calendar.validateField()</code>.
4344: * @see #validateField(int, int, int)
4345: * @stable ICU 2.0
4346: */
4347: protected void validateField(int field) {
4348: int y;
4349: switch (field) {
4350: case DAY_OF_MONTH:
4351: y = handleGetExtendedYear();
4352: validateField(field, 1, handleGetMonthLength(y,
4353: internalGet(MONTH)));
4354: break;
4355: case DAY_OF_YEAR:
4356: y = handleGetExtendedYear();
4357: validateField(field, 1, handleGetYearLength(y));
4358: break;
4359: case DAY_OF_WEEK_IN_MONTH:
4360: if (internalGet(field) == 0) {
4361: throw new IllegalArgumentException(
4362: "DAY_OF_WEEK_IN_MONTH cannot be zero");
4363: }
4364: validateField(field, getMinimum(field), getMaximum(field));
4365: break;
4366: default:
4367: validateField(field, getMinimum(field), getMaximum(field));
4368: break;
4369: }
4370: }
4371:
4372: /**
4373: * Validate a single field of this calendar given its minimum and
4374: * maximum allowed value. If the field is out of range, throw a
4375: * descriptive <code>IllegalArgumentException</code>. Subclasses may
4376: * use this method in their implementation of {@link
4377: * #validateField(int)}.
4378: * @stable ICU 2.0
4379: */
4380: protected final void validateField(int field, int min, int max) {
4381: int value = fields[field];
4382: if (value < min || value > max) {
4383: throw new IllegalArgumentException(fieldName(field) + '='
4384: + value + ", valid range=" + min + ".." + max);
4385: }
4386: }
4387:
4388: /**
4389: * Converts the current field values in <code>fields[]</code> to the
4390: * millisecond time value <code>time</code>.
4391: * @stable ICU 2.0
4392: */
4393: protected void computeTime() {
4394: if (!isLenient()) {
4395: validateFields();
4396: }
4397:
4398: // Compute the Julian day
4399: int julianDay = computeJulianDay();
4400:
4401: long millis = julianDayToMillis(julianDay);
4402:
4403: int millisInDay;
4404:
4405: // We only use MILLISECONDS_IN_DAY if it has been set by the user.
4406: // This makes it possible for the caller to set the calendar to a
4407: // time and call clear(MONTH) to reset the MONTH to January. This
4408: // is legacy behavior. Without this, clear(MONTH) has no effect,
4409: // since the internally set JULIAN_DAY is used.
4410: if (stamp[MILLISECONDS_IN_DAY] >= MINIMUM_USER_STAMP
4411: && newestStamp(AM_PM, MILLISECOND, UNSET) <= stamp[MILLISECONDS_IN_DAY]) {
4412: millisInDay = internalGet(MILLISECONDS_IN_DAY);
4413: } else {
4414: millisInDay = computeMillisInDay();
4415: }
4416:
4417: // Compute the time zone offset and DST offset. There are two potential
4418: // ambiguities here. We'll assume a 2:00 am (wall time) switchover time
4419: // for discussion purposes here.
4420: // 1. The transition into DST. Here, a designated time of 2:00 am - 2:59 am
4421: // can be in standard or in DST depending. However, 2:00 am is an invalid
4422: // representation (the representation jumps from 1:59:59 am Std to 3:00:00 am DST).
4423: // We assume standard time.
4424: // 2. The transition out of DST. Here, a designated time of 1:00 am - 1:59 am
4425: // can be in standard or DST. Both are valid representations (the rep
4426: // jumps from 1:59:59 DST to 1:00:00 Std).
4427: // Again, we assume standard time.
4428: // We use the TimeZone object, unless the user has explicitly set the ZONE_OFFSET
4429: // or DST_OFFSET fields; then we use those fields.
4430: if (stamp[ZONE_OFFSET] >= MINIMUM_USER_STAMP
4431: || stamp[DST_OFFSET] >= MINIMUM_USER_STAMP) {
4432: millisInDay -= internalGet(ZONE_OFFSET)
4433: + internalGet(DST_OFFSET);
4434: } else {
4435: millisInDay -= computeZoneOffset(millis, millisInDay);
4436: }
4437:
4438: time = millis + millisInDay;
4439: }
4440:
4441: /**
4442: * Compute the milliseconds in the day from the fields. This is a
4443: * value from 0 to 23:59:59.999 inclusive, unless fields are out of
4444: * range, in which case it can be an arbitrary value. This value
4445: * reflects local zone wall time.
4446: * @stable ICU 2.0
4447: */
4448: protected int computeMillisInDay() {
4449: // Do the time portion of the conversion.
4450:
4451: int millisInDay = 0;
4452:
4453: // Find the best set of fields specifying the time of day. There
4454: // are only two possibilities here; the HOUR_OF_DAY or the
4455: // AM_PM and the HOUR.
4456: int hourOfDayStamp = stamp[HOUR_OF_DAY];
4457: int hourStamp = Math.max(stamp[HOUR], stamp[AM_PM]);
4458: int bestStamp = (hourStamp > hourOfDayStamp) ? hourStamp
4459: : hourOfDayStamp;
4460:
4461: // Hours
4462: if (bestStamp != UNSET) {
4463: if (bestStamp == hourOfDayStamp) {
4464: // Don't normalize here; let overflow bump into the next period.
4465: // This is consistent with how we handle other fields.
4466: millisInDay += internalGet(HOUR_OF_DAY);
4467: } else {
4468: // Don't normalize here; let overflow bump into the next period.
4469: // This is consistent with how we handle other fields.
4470: millisInDay += internalGet(HOUR);
4471: millisInDay += 12 * internalGet(AM_PM); // Default works for unset AM_PM
4472: }
4473: }
4474:
4475: // We use the fact that unset == 0; we start with millisInDay
4476: // == HOUR_OF_DAY.
4477: millisInDay *= 60;
4478: millisInDay += internalGet(MINUTE); // now have minutes
4479: millisInDay *= 60;
4480: millisInDay += internalGet(SECOND); // now have seconds
4481: millisInDay *= 1000;
4482: millisInDay += internalGet(MILLISECOND); // now have millis
4483:
4484: return millisInDay;
4485: }
4486:
4487: /**
4488: * This method can assume EXTENDED_YEAR has been set.
4489: * @param millis milliseconds of the date fields (local midnight millis)
4490: * @param millisInDay milliseconds of the time fields; may be out
4491: * or range.
4492: * @return total zone offset (raw + DST) for the given moment
4493: * @stable ICU 2.0
4494: */
4495: protected int computeZoneOffset(long millis, int millisInDay) {
4496: int offsets[] = new int[2];
4497: zone.getOffset(millis + millisInDay, true, offsets);
4498: return offsets[0] + offsets[1];
4499:
4500: // Note: Because we pass in wall millisInDay, rather than
4501: // standard millisInDay, we interpret "1:00 am" on the day
4502: // of cessation of DST as "1:00 am Std" (assuming the time
4503: // of cessation is 2:00 am).
4504: }
4505:
4506: /**
4507: * Compute the Julian day number as specified by this calendar's fields.
4508: * @stable ICU 2.0
4509: */
4510: protected int computeJulianDay() {
4511:
4512: // We want to see if any of the date fields is newer than the
4513: // JULIAN_DAY. If not, then we use JULIAN_DAY. If so, then we do
4514: // the normal resolution. We only use JULIAN_DAY if it has been
4515: // set by the user. This makes it possible for the caller to set
4516: // the calendar to a time and call clear(MONTH) to reset the MONTH
4517: // to January. This is legacy behavior. Without this,
4518: // clear(MONTH) has no effect, since the internally set JULIAN_DAY
4519: // is used.
4520: if (stamp[JULIAN_DAY] >= MINIMUM_USER_STAMP) {
4521: int bestStamp = newestStamp(ERA, DAY_OF_WEEK_IN_MONTH,
4522: UNSET);
4523: bestStamp = newestStamp(YEAR_WOY, EXTENDED_YEAR, bestStamp);
4524: if (bestStamp <= stamp[JULIAN_DAY]) {
4525: return internalGet(JULIAN_DAY);
4526: }
4527: }
4528:
4529: int bestField = resolveFields(getFieldResolutionTable());
4530: if (bestField < 0) {
4531: bestField = DAY_OF_MONTH;
4532: }
4533:
4534: return handleComputeJulianDay(bestField);
4535: }
4536:
4537: /**
4538: * Return the field resolution array for this calendar. Calendars that
4539: * define additional fields or change the semantics of existing fields
4540: * should override this method to adjust the field resolution semantics
4541: * accordingly. Other subclasses should not override this method.
4542: * @see #resolveFields
4543: * @stable ICU 2.0
4544: */
4545: protected int[][][] getFieldResolutionTable() {
4546: return DATE_PRECEDENCE;
4547: }
4548:
4549: /**
4550: * Return the Julian day number of day before the first day of the
4551: * given month in the given extended year. Subclasses should override
4552: * this method to implement their calendar system.
4553: * @param eyear the extended year
4554: * @param month the zero-based month, or 0 if useMonth is false
4555: * @param useMonth if false, compute the day before the first day of
4556: * the given year, otherwise, compute the day before the first day of
4557: * the given month
4558: * @return the Julian day number of the day before the first
4559: * day of the given month and year
4560: * @stable ICU 2.0
4561: */
4562: abstract protected int handleComputeMonthStart(int eyear,
4563: int month, boolean useMonth);
4564:
4565: /**
4566: * Return the extended year defined by the current fields. This will
4567: * use the EXTENDED_YEAR field or the YEAR and supra-year fields (such
4568: * as ERA) specific to the calendar system, depending on which set of
4569: * fields is newer.
4570: * @return the extended year
4571: * @stable ICU 2.0
4572: */
4573: abstract protected int handleGetExtendedYear();
4574:
4575: // (The following method is not called because all existing subclasses
4576: // override it. 2003-06-11 ICU 2.6 Alan)
4577: ///CLOVER:OFF
4578: /**
4579: * Return the number of days in the given month of the given extended
4580: * year of this calendar system. Subclasses should override this
4581: * method if they can provide a more correct or more efficient
4582: * implementation than the default implementation in Calendar.
4583: * @stable ICU 2.0
4584: */
4585: protected int handleGetMonthLength(int extendedYear, int month) {
4586: return handleComputeMonthStart(extendedYear, month + 1, true)
4587: - handleComputeMonthStart(extendedYear, month, true);
4588: }
4589:
4590: ///CLOVER:ON
4591:
4592: /**
4593: * Return the number of days in the given extended year of this
4594: * calendar system. Subclasses should override this method if they can
4595: * provide a more correct or more efficient implementation than the
4596: * default implementation in Calendar.
4597: * @stable ICU 2.0
4598: */
4599: protected int handleGetYearLength(int eyear) {
4600: return handleComputeMonthStart(eyear + 1, 0, false)
4601: - handleComputeMonthStart(eyear, 0, false);
4602: }
4603:
4604: /**
4605: * Subclasses that use additional fields beyond those defined in
4606: * <code>Calendar</code> should override this method to return an
4607: * <code>int[]</code> array of the appropriate length. The length
4608: * must be at least <code>BASE_FIELD_COUNT</code> and no more than
4609: * <code>MAX_FIELD_COUNT</code>.
4610: * @stable ICU 2.0
4611: */
4612: protected int[] handleCreateFields() {
4613: return new int[BASE_FIELD_COUNT];
4614: }
4615:
4616: /**
4617: * Subclasses may override this.
4618: * Called by handleComputeJulianDay. Returns the default month (0-based) for the year,
4619: * taking year and era into account. Defaults to 0 (JANUARY) for Gregorian.
4620: * @param extendedYear the extendedYear, as returned by handleGetExtendedYear
4621: * @return the default month
4622: * @provisional ICU 3.6
4623: * @draft ICU 3.6
4624: * @see #MONTH
4625: */
4626: protected int getDefaultMonthInYear(int extendedYear) {
4627: return Calendar.JANUARY;
4628: }
4629:
4630: /**
4631: * Subclasses may override this.
4632: * Called by handleComputeJulianDay. Returns the default day (1-based) for the month,
4633: * taking currently-set year and era into account. Defaults to 1 for Gregorian.
4634: * @param extendedYear the extendedYear, as returned by handleGetExtendedYear
4635: * @param month the month, as returned by getDefaultMonthInYear
4636: * @return the default day of the month
4637: * @draft ICU 3.6
4638: * @provisional ICU 3.6
4639: * @see #DAY_OF_MONTH
4640: */
4641: protected int getDefaultDayInMonth(int extendedYear, int month) {
4642: return 1;
4643: }
4644:
4645: /**
4646: * Subclasses may override this. This method calls
4647: * handleGetMonthLength() to obtain the calendar-specific month
4648: * length.
4649: * @stable ICU 2.0
4650: */
4651: protected int handleComputeJulianDay(int bestField) {
4652:
4653: boolean useMonth = (bestField == DAY_OF_MONTH
4654: || bestField == WEEK_OF_MONTH || bestField == DAY_OF_WEEK_IN_MONTH);
4655:
4656: int year = handleGetExtendedYear();
4657: internalSet(EXTENDED_YEAR, year);
4658:
4659: int month = useMonth ? internalGet(MONTH,
4660: getDefaultMonthInYear(year)) : 0;
4661:
4662: int dom = internalGet(DAY_OF_MONTH, getDefaultDayInMonth(year,
4663: month));
4664:
4665: // Get the Julian day of the day BEFORE the start of this year.
4666: // If useMonth is true, get the day before the start of the month.
4667: int julianDay = handleComputeMonthStart(year, month, useMonth);
4668:
4669: if (bestField == DAY_OF_MONTH) {
4670: if (isSet(DAY_OF_MONTH)) {
4671: return julianDay
4672: + internalGet(DAY_OF_MONTH,
4673: getDefaultDayInMonth(year, month));
4674: } else {
4675: return julianDay + getDefaultDayInMonth(year, month);
4676: }
4677: }
4678:
4679: if (bestField == DAY_OF_YEAR) {
4680: return julianDay + internalGet(DAY_OF_YEAR);
4681: }
4682:
4683: int firstDayOfWeek = getFirstDayOfWeek(); // Localized fdw
4684:
4685: // At this point julianDay is the 0-based day BEFORE the first day of
4686: // January 1, year 1 of the given calendar. If julianDay == 0, it
4687: // specifies (Jan. 1, 1) - 1, in whatever calendar we are using (Julian
4688: // or Gregorian).
4689:
4690: // At this point we need to process the WEEK_OF_MONTH or
4691: // WEEK_OF_YEAR, which are similar, or the DAY_OF_WEEK_IN_MONTH.
4692: // First, perform initial shared computations. These locate the
4693: // first week of the period.
4694:
4695: // Get the 0-based localized DOW of day one of the month or year.
4696: // Valid range 0..6.
4697: int first = julianDayToDayOfWeek(julianDay + 1)
4698: - firstDayOfWeek;
4699: if (first < 0) {
4700: first += 7;
4701: }
4702:
4703: // Get zero-based localized DOW, valid range 0..6. This is the DOW
4704: // we are looking for.
4705: int dowLocal = 0;
4706: switch (resolveFields(DOW_PRECEDENCE)) {
4707: case DAY_OF_WEEK:
4708: dowLocal = internalGet(DAY_OF_WEEK) - firstDayOfWeek;
4709: break;
4710: case DOW_LOCAL:
4711: dowLocal = internalGet(DOW_LOCAL) - 1;
4712: break;
4713: }
4714: dowLocal = dowLocal % 7;
4715: if (dowLocal < 0) {
4716: dowLocal += 7;
4717: }
4718:
4719: // Find the first target DOW (dowLocal) in the month or year.
4720: // Actually, it may be just before the first of the month or year.
4721: // It will be an integer from -5..7.
4722: int date = 1 - first + dowLocal;
4723:
4724: if (bestField == DAY_OF_WEEK_IN_MONTH) {
4725:
4726: // Adjust the target DOW to be in the month or year.
4727: if (date < 1) {
4728: date += 7;
4729: }
4730:
4731: // The only trickiness occurs if the day-of-week-in-month is
4732: // negative.
4733: int dim = internalGet(DAY_OF_WEEK_IN_MONTH, 1);
4734: if (dim >= 0) {
4735: date += 7 * (dim - 1);
4736:
4737: } else {
4738: // Move date to the last of this day-of-week in this month,
4739: // then back up as needed. If dim==-1, we don't back up at
4740: // all. If dim==-2, we back up once, etc. Don't back up
4741: // past the first of the given day-of-week in this month.
4742: // Note that we handle -2, -3, etc. correctly, even though
4743: // values < -1 are technically disallowed.
4744: int m = internalGet(MONTH, JANUARY);
4745: int monthLength = handleGetMonthLength(year, m);
4746: date += ((monthLength - date) / 7 + dim + 1) * 7;
4747: }
4748: } else {
4749: // assert(bestField == WEEK_OF_MONTH || bestField == WEEK_OF_YEAR)
4750:
4751: // Adjust for minimal days in first week
4752: if ((7 - first) < getMinimalDaysInFirstWeek()) {
4753: date += 7;
4754: }
4755:
4756: // Now adjust for the week number.
4757: date += 7 * (internalGet(bestField) - 1);
4758: }
4759:
4760: return julianDay + date;
4761: }
4762:
4763: /**
4764: * Compute the Julian day of a month of the Gregorian calendar.
4765: * Subclasses may call this method to perform a Gregorian calendar
4766: * fields->millis computation. To perform a Gregorian calendar
4767: * millis->fields computation, call computeGregorianFields().
4768: * @param year extended Gregorian year
4769: * @param month zero-based Gregorian month
4770: * @return the Julian day number of the day before the first
4771: * day of the given month in the given extended year
4772: * @see #computeGregorianFields
4773: * @stable ICU 2.0
4774: */
4775: protected int computeGregorianMonthStart(int year, int month) {
4776:
4777: // If the month is out of range, adjust it into range, and
4778: // modify the extended year value accordingly.
4779: if (month < 0 || month > 11) {
4780: int[] rem = new int[1];
4781: year += floorDivide(month, 12, rem);
4782: month = rem[0];
4783: }
4784:
4785: boolean isLeap = (year % 4 == 0)
4786: && ((year % 100 != 0) || (year % 400 == 0));
4787: int y = year - 1;
4788: // This computation is actually ... + (JAN_1_1_JULIAN_DAY - 3) + 2.
4789: // Add 2 because Gregorian calendar starts 2 days after Julian
4790: // calendar.
4791: int julianDay = 365 * y + floorDivide(y, 4)
4792: - floorDivide(y, 100) + floorDivide(y, 400)
4793: + JAN_1_1_JULIAN_DAY - 1;
4794:
4795: // At this point julianDay indicates the day BEFORE the first day
4796: // of January 1, <eyear> of the Gregorian calendar.
4797: if (month != 0) {
4798: julianDay += GREGORIAN_MONTH_COUNT[month][isLeap ? 3 : 2];
4799: }
4800:
4801: return julianDay;
4802: }
4803:
4804: //----------------------------------------------------------------------
4805: // Subclass API
4806: // For subclasses to override
4807: //----------------------------------------------------------------------
4808:
4809: // (The following method is not called because all existing subclasses
4810: // override it. 2003-06-11 ICU 2.6 Alan)
4811: ///CLOVER:OFF
4812: /**
4813: * Subclasses may override this method to compute several fields
4814: * specific to each calendar system. These are:
4815: *
4816: * <ul><li>ERA
4817: * <li>YEAR
4818: * <li>MONTH
4819: * <li>DAY_OF_MONTH
4820: * <li>DAY_OF_YEAR
4821: * <li>EXTENDED_YEAR</ul>
4822: *
4823: * Subclasses can refer to the DAY_OF_WEEK and DOW_LOCAL fields, which
4824: * will be set when this method is called. Subclasses can also call
4825: * the getGregorianXxx() methods to obtain Gregorian calendar
4826: * equivalents for the given Julian day.
4827: *
4828: * <p>In addition, subclasses should compute any subclass-specific
4829: * fields, that is, fields from BASE_FIELD_COUNT to
4830: * getFieldCount() - 1.
4831: *
4832: * <p>The default implementation in <code>Calendar</code> implements
4833: * a pure proleptic Gregorian calendar.
4834: * @stable ICU 2.0
4835: */
4836: protected void handleComputeFields(int julianDay) {
4837: internalSet(MONTH, getGregorianMonth());
4838: internalSet(DAY_OF_MONTH, getGregorianDayOfMonth());
4839: internalSet(DAY_OF_YEAR, getGregorianDayOfYear());
4840: int eyear = getGregorianYear();
4841: internalSet(EXTENDED_YEAR, eyear);
4842: int era = GregorianCalendar.AD;
4843: if (eyear < 1) {
4844: era = GregorianCalendar.BC;
4845: eyear = 1 - eyear;
4846: }
4847: internalSet(ERA, era);
4848: internalSet(YEAR, eyear);
4849: }
4850:
4851: ///CLOVER:ON
4852:
4853: //----------------------------------------------------------------------
4854: // Subclass API
4855: // For subclasses to call
4856: //----------------------------------------------------------------------
4857:
4858: /**
4859: * Return the extended year on the Gregorian calendar as computed by
4860: * <code>computeGregorianFields()</code>.
4861: * @see #computeGregorianFields
4862: * @stable ICU 2.0
4863: */
4864: protected final int getGregorianYear() {
4865: return gregorianYear;
4866: }
4867:
4868: /**
4869: * Return the month (0-based) on the Gregorian calendar as computed by
4870: * <code>computeGregorianFields()</code>.
4871: * @see #computeGregorianFields
4872: * @stable ICU 2.0
4873: */
4874: protected final int getGregorianMonth() {
4875: return gregorianMonth;
4876: }
4877:
4878: /**
4879: * Return the day of year (1-based) on the Gregorian calendar as
4880: * computed by <code>computeGregorianFields()</code>.
4881: * @see #computeGregorianFields
4882: * @stable ICU 2.0
4883: */
4884: protected final int getGregorianDayOfYear() {
4885: return gregorianDayOfYear;
4886: }
4887:
4888: /**
4889: * Return the day of month (1-based) on the Gregorian calendar as
4890: * computed by <code>computeGregorianFields()</code>.
4891: * @see #computeGregorianFields
4892: * @stable ICU 2.0
4893: */
4894: protected final int getGregorianDayOfMonth() {
4895: return gregorianDayOfMonth;
4896: }
4897:
4898: /**
4899: * Return the number of fields defined by this calendar. Valid field
4900: * arguments to <code>set()</code> and <code>get()</code> are
4901: * <code>0..getFieldCount()-1</code>.
4902: * @stable ICU 2.0
4903: */
4904: public final int getFieldCount() {
4905: return fields.length;
4906: }
4907:
4908: /**
4909: * Set a field to a value. Subclasses should use this method when
4910: * computing fields. It sets the time stamp in the
4911: * <code>stamp[]</code> array to <code>INTERNALLY_SET</code>. If a
4912: * field that may not be set by subclasses is passed in, an
4913: * <code>IllegalArgumentException</code> is thrown. This prevents
4914: * subclasses from modifying fields that are intended to be
4915: * calendar-system invariant.
4916: * @stable ICU 2.0
4917: */
4918: protected final void internalSet(int field, int value) {
4919: if (((1 << field) & internalSetMask) == 0) {
4920: throw new IllegalStateException("Subclass cannot set "
4921: + fieldName(field));
4922: }
4923: fields[field] = value;
4924: stamp[field] = INTERNALLY_SET;
4925: }
4926:
4927: private static final int[][] GREGORIAN_MONTH_COUNT = {
4928: //len len2 st st2
4929: { 31, 31, 0, 0 }, // Jan
4930: { 28, 29, 31, 31 }, // Feb
4931: { 31, 31, 59, 60 }, // Mar
4932: { 30, 30, 90, 91 }, // Apr
4933: { 31, 31, 120, 121 }, // May
4934: { 30, 30, 151, 152 }, // Jun
4935: { 31, 31, 181, 182 }, // Jul
4936: { 31, 31, 212, 213 }, // Aug
4937: { 30, 30, 243, 244 }, // Sep
4938: { 31, 31, 273, 274 }, // Oct
4939: { 30, 30, 304, 305 }, // Nov
4940: { 31, 31, 334, 335 } // Dec
4941: // len length of month
4942: // len2 length of month in a leap year
4943: // st days in year before start of month
4944: // st2 days in year before month in leap year
4945: };
4946:
4947: /**
4948: * Determines if the given year is a leap year. Returns true if the
4949: * given year is a leap year.
4950: * @param year the given year.
4951: * @return true if the given year is a leap year; false otherwise.
4952: * @stable ICU 2.0
4953: */
4954: protected static final boolean isGregorianLeapYear(int year) {
4955: return (year % 4 == 0)
4956: && ((year % 100 != 0) || (year % 400 == 0));
4957: }
4958:
4959: /**
4960: * Return the length of a month of the Gregorian calendar.
4961: * @param y the extended year
4962: * @param m the 0-based month number
4963: * @return the number of days in the given month
4964: * @stable ICU 2.0
4965: */
4966: protected static final int gregorianMonthLength(int y, int m) {
4967: return GREGORIAN_MONTH_COUNT[m][isGregorianLeapYear(y) ? 1 : 0];
4968: }
4969:
4970: /**
4971: * Return the length of a previous month of the Gregorian calendar.
4972: * @param y the extended year
4973: * @param m the 0-based month number
4974: * @return the number of days in the month previous to the given month
4975: * @stable ICU 2.0
4976: */
4977: protected static final int gregorianPreviousMonthLength(int y, int m) {
4978: return (m > 0) ? gregorianMonthLength(y, m - 1) : 31;
4979: }
4980:
4981: /**
4982: * Divide two long integers, returning the floor of the quotient.
4983: * <p>
4984: * Unlike the built-in division, this is mathematically well-behaved.
4985: * E.g., <code>-1/4</code> => 0
4986: * but <code>floorDivide(-1,4)</code> => -1.
4987: * @param numerator the numerator
4988: * @param denominator a divisor which must be > 0
4989: * @return the floor of the quotient.
4990: * @stable ICU 2.0
4991: */
4992: protected static final long floorDivide(long numerator,
4993: long denominator) {
4994: // We do this computation in order to handle
4995: // a numerator of Long.MIN_VALUE correctly
4996: return (numerator >= 0) ? numerator / denominator
4997: : ((numerator + 1) / denominator) - 1;
4998: }
4999:
5000: /**
5001: * Divide two integers, returning the floor of the quotient.
5002: * <p>
5003: * Unlike the built-in division, this is mathematically well-behaved.
5004: * E.g., <code>-1/4</code> => 0
5005: * but <code>floorDivide(-1,4)</code> => -1.
5006: * @param numerator the numerator
5007: * @param denominator a divisor which must be > 0
5008: * @return the floor of the quotient.
5009: * @stable ICU 2.0
5010: */
5011: protected static final int floorDivide(int numerator,
5012: int denominator) {
5013: // We do this computation in order to handle
5014: // a numerator of Integer.MIN_VALUE correctly
5015: return (numerator >= 0) ? numerator / denominator
5016: : ((numerator + 1) / denominator) - 1;
5017: }
5018:
5019: /**
5020: * Divide two integers, returning the floor of the quotient, and
5021: * the modulus remainder.
5022: * <p>
5023: * Unlike the built-in division, this is mathematically well-behaved.
5024: * E.g., <code>-1/4</code> => 0 and <code>-1%4</code> => -1,
5025: * but <code>floorDivide(-1,4)</code> => -1 with <code>remainder[0]</code> => 3.
5026: * @param numerator the numerator
5027: * @param denominator a divisor which must be > 0
5028: * @param remainder an array of at least one element in which the value
5029: * <code>numerator mod denominator</code> is returned. Unlike <code>numerator
5030: * % denominator</code>, this will always be non-negative.
5031: * @return the floor of the quotient.
5032: * @stable ICU 2.0
5033: */
5034: protected static final int floorDivide(int numerator,
5035: int denominator, int[] remainder) {
5036: if (numerator >= 0) {
5037: remainder[0] = numerator % denominator;
5038: return numerator / denominator;
5039: }
5040: int quotient = ((numerator + 1) / denominator) - 1;
5041: remainder[0] = numerator - (quotient * denominator);
5042: return quotient;
5043: }
5044:
5045: /**
5046: * Divide two integers, returning the floor of the quotient, and
5047: * the modulus remainder.
5048: * <p>
5049: * Unlike the built-in division, this is mathematically well-behaved.
5050: * E.g., <code>-1/4</code> => 0 and <code>-1%4</code> => -1,
5051: * but <code>floorDivide(-1,4)</code> => -1 with <code>remainder[0]</code> => 3.
5052: * @param numerator the numerator
5053: * @param denominator a divisor which must be > 0
5054: * @param remainder an array of at least one element in which the value
5055: * <code>numerator mod denominator</code> is returned. Unlike <code>numerator
5056: * % denominator</code>, this will always be non-negative.
5057: * @return the floor of the quotient.
5058: * @stable ICU 2.0
5059: */
5060: protected static final int floorDivide(long numerator,
5061: int denominator, int[] remainder) {
5062: if (numerator >= 0) {
5063: remainder[0] = (int) (numerator % denominator);
5064: return (int) (numerator / denominator);
5065: }
5066: int quotient = (int) (((numerator + 1) / denominator) - 1);
5067: remainder[0] = (int) (numerator - (quotient * denominator));
5068: return quotient;
5069: }
5070:
5071: private static final String[] FIELD_NAME = { "ERA", "YEAR",
5072: "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH",
5073: "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH",
5074: "AM_PM", "HOUR", "HOUR_OF_DAY", "MINUTE", "SECOND",
5075: "MILLISECOND", "ZONE_OFFSET", "DST_OFFSET", "YEAR_WOY",
5076: "DOW_LOCAL", "EXTENDED_YEAR", "JULIAN_DAY",
5077: "MILLISECONDS_IN_DAY", };
5078:
5079: /**
5080: * Return a string name for a field, for debugging and exceptions.
5081: * @stable ICU 2.0
5082: */
5083: protected String fieldName(int field) {
5084: try {
5085: return FIELD_NAME[field];
5086: } catch (ArrayIndexOutOfBoundsException e) {
5087: return "Field " + field;
5088: }
5089: }
5090:
5091: /**
5092: * Converts time as milliseconds to Julian day.
5093: * @param millis the given milliseconds.
5094: * @return the Julian day number.
5095: * @stable ICU 2.0
5096: */
5097: protected static final int millisToJulianDay(long millis) {
5098: return (int) (EPOCH_JULIAN_DAY + floorDivide(millis, ONE_DAY));
5099: }
5100:
5101: /**
5102: * Converts Julian day to time as milliseconds.
5103: * @param julian the given Julian day number.
5104: * @return time as milliseconds.
5105: * @stable ICU 2.0
5106: */
5107: protected static final long julianDayToMillis(int julian) {
5108: return (julian - EPOCH_JULIAN_DAY) * ONE_DAY;
5109: }
5110:
5111: /**
5112: * Return the day of week, from SUNDAY to SATURDAY, given a Julian day.
5113: * @stable ICU 2.0
5114: */
5115: protected static final int julianDayToDayOfWeek(int julian) {
5116: // If julian is negative, then julian%7 will be negative, so we adjust
5117: // accordingly. Julian day 0 is Monday.
5118: int dayOfWeek = (julian + MONDAY) % 7;
5119: if (dayOfWeek < SUNDAY) {
5120: dayOfWeek += 7;
5121: }
5122: return dayOfWeek;
5123: }
5124:
5125: /**
5126: * Return the current milliseconds without recomputing.
5127: * @stable ICU 2.0
5128: */
5129: protected final long internalGetTimeInMillis() {
5130: return time;
5131: }
5132:
5133: /**
5134: * Return the current Calendar type.
5135: * Note, in 3.0 this function will return 'gregorian' in Calendar to emulate legacy behavior
5136: * @return type of calendar (gregorian, etc)
5137: * @internal ICU 3.0
5138: * @deprecated This API is ICU internal only.
5139: */
5140: public String getType() {
5141: return "gregorian";
5142: }
5143:
5144: // -------- BEGIN ULocale boilerplate --------
5145:
5146: /**
5147: * Return the locale that was used to create this object, or null.
5148: * This may may differ from the locale requested at the time of
5149: * this object's creation. For example, if an object is created
5150: * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
5151: * drawn from <tt>en</tt> (the <i>actual</i> locale), and
5152: * <tt>en_US</tt> may be the most specific locale that exists (the
5153: * <i>valid</i> locale).
5154: *
5155: * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8
5156: * contains a partial preview implementation. The * <i>actual</i>
5157: * locale is returned correctly, but the <i>valid</i> locale is
5158: * not, in most cases.
5159: * @param type type of information requested, either {@link
5160: * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
5161: * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
5162: * @return the information specified by <i>type</i>, or null if
5163: * this object was not constructed from locale data.
5164: * @see com.ibm.icu.util.ULocale
5165: * @see com.ibm.icu.util.ULocale#VALID_LOCALE
5166: * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
5167: * @draft ICU 2.8 (retain)
5168: * @provisional This API might change or be removed in a future release.
5169: */
5170: public final ULocale getLocale(ULocale.Type type) {
5171: return type == ULocale.ACTUAL_LOCALE ? this .actualLocale
5172: : this .validLocale;
5173: }
5174:
5175: /**
5176: * Set information about the locales that were used to create this
5177: * object. If the object was not constructed from locale data,
5178: * both arguments should be set to null. Otherwise, neither
5179: * should be null. The actual locale must be at the same level or
5180: * less specific than the valid locale. This method is intended
5181: * for use by factories or other entities that create objects of
5182: * this class.
5183: * @param valid the most specific locale containing any resource
5184: * data, or null
5185: * @param actual the locale containing data used to construct this
5186: * object, or null
5187: * @see com.ibm.icu.util.ULocale
5188: * @see com.ibm.icu.util.ULocale#VALID_LOCALE
5189: * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
5190: * @internal
5191: */
5192: final void setLocale(ULocale valid, ULocale actual) {
5193: // Change the following to an assertion later
5194: if ((valid == null) != (actual == null)) {
5195: ///CLOVER:OFF
5196: throw new IllegalArgumentException();
5197: ///CLOVER:ON
5198: }
5199: // Another check we could do is that the actual locale is at
5200: // the same level or less specific than the valid locale.
5201: this .validLocale = valid;
5202: this .actualLocale = actual;
5203: }
5204:
5205: /**
5206: * The most specific locale containing any resource data, or null.
5207: * @see com.ibm.icu.util.ULocale
5208: * @internal
5209: */
5210: private ULocale validLocale;
5211:
5212: /**
5213: * The locale containing data used to construct this object, or
5214: * null.
5215: * @see com.ibm.icu.util.ULocale
5216: * @internal
5217: */
5218: private ULocale actualLocale;
5219:
5220: // -------- END ULocale boilerplate --------
5221: }
|