home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / util / Calendar.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  44.7 KB  |  1,259 lines

  1. /*
  2.  * @(#)Calendar.java    1.31 98/03/18
  3.  *
  4.  * (C) Copyright Taligent, Inc. 1996-1997 - All Rights Reserved
  5.  * (C) Copyright IBM Corp. 1996-1997 - All Rights Reserved
  6.  *
  7.  * Portions copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
  8.  *
  9.  *   The original version of this source code and documentation is copyrighted
  10.  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  11.  * materials are provided under terms of a License Agreement between Taligent
  12.  * and Sun. This technology is protected by multiple US and International
  13.  * patents. This notice and attribution to Taligent may not be removed.
  14.  *   Taligent is a registered trademark of Taligent, Inc.
  15.  *
  16.  * Permission to use, copy, modify, and distribute this software
  17.  * and its documentation for NON-COMMERCIAL purposes and without
  18.  * fee is hereby granted provided that this copyright notice
  19.  * appears in all copies. Please refer to the file "copyright.html"
  20.  * for further important copyright and licensing information.
  21.  *
  22.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  23.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  24.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  25.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  26.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  27.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  28.  *
  29.  */
  30.  
  31. package java.util;
  32. import java.io.IOException;
  33. import java.io.ObjectInputStream;
  34. import java.io.ObjectOutputStream;
  35. import java.io.Serializable;
  36. import java.text.DateFormat;
  37.  
  38. /**
  39.  * <code>Calendar</code> is an abstract base class for converting between
  40.  * a <code>Date</code> object and a set of integer fields such as
  41.  * <code>YEAR</code>, <code>MONTH</code>, <code>DAY</code>, <code>HOUR</code>,
  42.  * and so on. (A <code>Date</code> object represents a specific instant in
  43.  * time with millisecond precision. See
  44.  * <a href="java.util.Date.html"><code>java.util.Date</code></a>
  45.  * for information about the <code>Date</code> class.)
  46.  *
  47.  * <p>
  48.  * Subclasses of <code>Calendar</code> interpret a <code>Date</code>
  49.  * according to the rules of a specific calendar system. The JDK
  50.  * provides one concrete subclass of <code>Calendar</code>:
  51.  * <code>GregorianCalendar</code>. Future subclasses could represent
  52.  * the various types of lunar calendars in use in many parts of the world.
  53.  *
  54.  * <p>
  55.  * Like other locale-sensitive classes, <code>Calendar</code> provides a
  56.  * class method, <code>getInstance</code>, for getting a generally useful
  57.  * object of this type. <code>Calendar</code>'s <code>getInstance</code> method
  58.  * returns a <code>GregorianCalendar</code> object whose
  59.  * time fields have been initialized with the current date and time:
  60.  * <blockquote>
  61.  * <pre>
  62.  * Calendar rightNow = Calendar.getInstance();
  63.  * </pre>
  64.  * </blockquote>
  65.  *
  66.  * <p>
  67.  * A <code>Calendar</code> object can produce all the time field values
  68.  * needed to implement the date-time formatting for a particular language
  69.  * and calendar style (for example, Japanese-Gregorian, Japanese-Traditional).
  70.  *
  71.  * <p>
  72.  * When computing a <code>Date</code> from time fields, two special circumstances
  73.  * may arise: there may be insufficient information to compute the
  74.  * <code>Date</code> (such as only year and month but no day in the month),
  75.  * or there may be inconsistent information (such as "Tuesday, July 15, 1996"
  76.  * -- July 15, 1996 is actually a Monday).
  77.  *
  78.  * <p>
  79.  * <strong>Insufficient information.</strong> The calendar will use default
  80.  * information to specify the missing fields. This may vary by calendar; for
  81.  * the Gregorian calendar, the default for a field is the same as that of the
  82.  * start of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc.
  83.  *
  84.  * <p>
  85.  * <strong>Inconsistent information.</strong> If fields conflict, the calendar
  86.  * will give preference to fields set more recently. For example, when
  87.  * determining the day, the calendar will look for one of the following
  88.  * combinations of fields.  The most recent combination, as determined by the
  89.  * most recently set single field, will be used.
  90.  *
  91.  * <blockquote>
  92.  * <pre>
  93.  * MONTH + DAY_OF_MONTH
  94.  * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
  95.  * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
  96.  * DAY_OF_YEAR
  97.  * DAY_OF_WEEK + WEEK_OF_YEAR
  98.  * </pre>
  99.  * </blockquote>
  100.  *
  101.  * For the time of day:
  102.  *
  103.  * <blockquote>
  104.  * <pre>
  105.  * HOUR_OF_DAY
  106.  * AM_PM + HOUR
  107.  * </pre>
  108.  * </blockquote>
  109.  *
  110.  * <p>
  111.  * <strong>Note:</strong> for some non-Gregorian calendars, different
  112.  * fields may be necessary for complete disambiguation. For example, a full
  113.  * specification of the historial Arabic astronomical calendar requires year,
  114.  * month, day-of-month <em>and</em> day-of-week in some cases.
  115.  *
  116.  * <p>
  117.  * <strong>Note:</strong> There are certain possible ambiguities in
  118.  * interpretation of certain singular times, which are resolved in the
  119.  * following ways:
  120.  * <ol>
  121.  *     <li> 24:00:00 "belongs" to the following day. That is,
  122.  *          23:59 on Dec 31, 1969 < 24:00 on Jan 1, 1970 < 24:01:00 on Jan 1, 1970
  123.  *
  124.  *     <li> Although historically not precise, midnight also belongs to "am",
  125.  *          and noon belongs to "pm", so on the same day,
  126.  *          12:00 am (midnight) < 12:01 am, and 12:00 pm (noon) < 12:01 pm
  127.  * </ol>
  128.  *
  129.  * <p>
  130.  * The date or time format strings are not part of the definition of a
  131.  * calendar, as those must be modifiable or overridable by the user at
  132.  * runtime. Use <a href="java.text.DateFormat.html">java.text.DateFormat</a>
  133.  * to format dates.
  134.  *
  135.  * <p>
  136.  * <code>Calendar</code> provides an API for field "rolling", where fields
  137.  * can be incremented or decremented, but wrap around. For example, rolling the
  138.  * month up in the date "September 12, 1996" results in "October 12, 1996".
  139.  *
  140.  * <p>
  141.  * <code>Calendar</code> also provides a date arithmetic function for
  142.  * adding the specified (signed) amount of time to a particular time field.
  143.  * For example, subtracting 5 days from the date "September 12, 1996" results
  144.  * in "September 7, 1996".
  145.  *
  146.  * @see          Date
  147.  * @see          GregorianCalendar
  148.  * @see          TimeZone
  149.  * @see          java.text.DateFormat
  150.  * @version      1.17 06 Jan 1997
  151.  * @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu
  152.  */
  153. public abstract class Calendar implements Serializable, Cloneable {
  154.  
  155.     // Data flow in Calendar
  156.     // ---------------------
  157.  
  158.     // The current time is represented in two ways by Calendar: as UTC
  159.     // milliseconds from the epoch start (1 January 1970 0:00 UTC), and as local
  160.     // fields such as MONTH, HOUR, AM_PM, etc.  It is possible to compute the
  161.     // millis from the fields, and vice versa.  The data needed to do this
  162.     // conversion is encapsulated by a TimeZone object owned by the Calendar.
  163.     // The data provided by the TimeZone object may also be overridden if the
  164.     // user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class
  165.     // keeps track of what information was most recently set by the caller, and
  166.     // uses that to compute any other information as needed.
  167.  
  168.     // If the user sets the fields using set(), the data flow is as follows.
  169.     // This is implemented by the Calendar subclass's computeTime() method.
  170.     // During this process, certain fields may be ignored.  The disambiguation
  171.     // algorithm for resolving which fields to pay attention to is described
  172.     // above.
  173.  
  174.     //   local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
  175.     //           |
  176.     //           | Using Calendar-specific algorithm
  177.     //           V
  178.     //   local standard millis
  179.     //           |
  180.     //           | Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET
  181.     //           V
  182.     //   UTC millis (in time data member)
  183.  
  184.     // If the user sets the UTC millis using setTime(), the data flow is as
  185.     // follows.  This is implemented by the Calendar subclass's computeFields()
  186.     // method.
  187.  
  188.     //   UTC millis (in time data member)
  189.     //           |
  190.     //           | Using TimeZone getOffset()
  191.     //           V
  192.     //   local standard millis
  193.     //           |
  194.     //           | Using Calendar-specific algorithm
  195.     //           V
  196.     //   local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
  197.  
  198.     // In general, a round trip from fields, through local and UTC millis, and
  199.     // back out to fields is made when necessary.  This is implemented by the
  200.     // complete() method.  Resolving a partial set of fields into a UTC millis
  201.     // value allows all remaining fields to be generated from that value.  If
  202.     // the Calendar is lenient, the fields are also renormalized to standard
  203.     // ranges when they are regenerated.
  204.  
  205.     /**
  206.      * Useful constant for date and time. Used in time fields.
  207.      * ERA is calendar specific.
  208.      */
  209.     public final static int ERA = 0;
  210.     /**
  211.      * Useful constant for date and time. Used in time fields.
  212.      */
  213.     public final static int YEAR = 1;
  214.     /**
  215.      * Useful constant for date and time. Used in time fields.
  216.      */
  217.     public final static int MONTH = 2;
  218.     /**
  219.      * Useful constant for date and time. Used in time fields.
  220.      */
  221.     public final static int WEEK_OF_YEAR = 3;
  222.     /**
  223.      * Useful constant for date and time. Used in time fields.
  224.      */
  225.     public final static int WEEK_OF_MONTH = 4;
  226.     /**
  227.      * Useful constant for date and time. Used in time fields.
  228.      * This is a synonym for DAY_OF_MONTH.
  229.      */
  230.     public final static int DATE = 5;
  231.     /**
  232.      * Useful constant for date and time. Used in time fields.
  233.      * This is a synonym for DATE.
  234.      */
  235.     public final static int DAY_OF_MONTH = 5;
  236.     /**
  237.      * Useful constant for date and time. Used in time fields.
  238.      */
  239.     public final static int DAY_OF_YEAR = 6;
  240.     /**
  241.      * Useful constant for date and time. Used in time fields.
  242.      */
  243.     public final static int DAY_OF_WEEK = 7;
  244.     /**
  245.      * Useful constant for date and time. Used in time fields.
  246.      */
  247.     public final static int DAY_OF_WEEK_IN_MONTH = 8;
  248.     /**
  249.      * Useful constant for date and time. Used in time fields.
  250.      */
  251.     public final static int AM_PM = 9;
  252.     /**
  253.      * Useful constant for date and time. Used in time fields.
  254.      * HOUR is used for the 12-hour clock.
  255.      */
  256.     public final static int HOUR = 10;
  257.     /**
  258.      * Useful constant for date and time. Used in time fields.
  259.      * HOUR_OF_DAY is used for the 24-hour clock.
  260.      */
  261.     public final static int HOUR_OF_DAY = 11;
  262.     /**
  263.      * Useful constant for date and time. Used in time fields.
  264.      */
  265.     public final static int MINUTE = 12;
  266.     /**
  267.      * Useful constant for date and time. Used in time fields.
  268.      */
  269.     public final static int SECOND = 13;
  270.     /**
  271.      * Useful constant for date and time. Used in time fields.
  272.      */
  273.     public final static int MILLISECOND = 14;
  274.     /**
  275.      * Useful constant for date and time. Used in time fields.
  276.      */
  277.     public final static int ZONE_OFFSET = 15;
  278.     /**
  279.      * Useful constant for date and time. Used in time fields.
  280.      */
  281.     public final static int DST_OFFSET = 16;
  282.     /**
  283.      * Useful constant for date and time.
  284.      * FIELD_COUNT is used for the time field array creation.
  285.      */
  286.     public final static int FIELD_COUNT = 17;
  287.  
  288.     /**
  289.      * Useful constant for days of week. Used in GregorianCalendar.
  290.      */
  291.     public final static int SUNDAY = 1;
  292.     /**
  293.      * Useful constant for days of week. Used in GregorianCalendar.
  294.      */
  295.     public final static int MONDAY = 2;
  296.     /**
  297.      * Useful constant for days of week. Used in GregorianCalendar.
  298.      */
  299.     public final static int TUESDAY = 3;
  300.     /**
  301.      * Useful constant for days of week. Used in GregorianCalendar.
  302.      */
  303.     public final static int WEDNESDAY = 4;
  304.     /**
  305.      * Useful constant for days of week. Used in GregorianCalendar.
  306.      */
  307.     public final static int THURSDAY = 5;
  308.     /**
  309.      * Useful constant for days of week. Used in GregorianCalendar.
  310.      */
  311.     public final static int FRIDAY = 6;
  312.     /**
  313.      * Useful constant for days of week. Used in GregorianCalendar.
  314.      */
  315.     public final static int SATURDAY = 7;
  316.     /**
  317.      * Useful constant for month. Used in GregorianCalendar.
  318.      * Note: Calendar month is now 0-based.
  319.      */
  320.     public final static int JANUARY = 0;
  321.     /**
  322.      * Useful constant for month. Used in GregorianCalendar.
  323.      */
  324.     public final static int FEBRUARY = 1;
  325.     /**
  326.      * Useful constant for month. Used in GregorianCalendar.
  327.      */
  328.     public final static int MARCH = 2;
  329.     /**
  330.      * Useful constant for month. Used in GregorianCalendar.
  331.      */
  332.     public final static int APRIL = 3;
  333.     /**
  334.      * Useful constant for month. Used in GregorianCalendar.
  335.      */
  336.     public final static int MAY = 4;
  337.     /**
  338.      * Useful constant for month. Used in GregorianCalendar.
  339.      */
  340.     public final static int JUNE = 5;
  341.     /**
  342.      * Useful constant for month. Used in GregorianCalendar.
  343.      */
  344.     public final static int JULY = 6;
  345.     /**
  346.      * Useful constant for month. Used in GregorianCalendar.
  347.      */
  348.     public final static int AUGUST = 7;
  349.     /**
  350.      * Useful constant for month. Used in GregorianCalendar.
  351.      */
  352.     public final static int SEPTEMBER = 8;
  353.     /**
  354.      * Useful constant for month. Used in GregorianCalendar.
  355.      */
  356.     public final static int OCTOBER = 9;
  357.     /**
  358.      * Useful constant for month. Used in GregorianCalendar.
  359.      */
  360.     public final static int NOVEMBER = 10;
  361.     /**
  362.      * Useful constant for month. Used in GregorianCalendar.
  363.      */
  364.     public final static int DECEMBER = 11;
  365.     /**
  366.      * Useful constant for month. Used in GregorianCalendar.
  367.      * UNDECIMBER is an artifical name. This 13th month is for lunar
  368.      * calendars.
  369.      */
  370.     public final static int UNDECIMBER = 12;
  371.     /**
  372.      * Useful constant for hour in 12-hour clock. Used in GregorianCalendar.
  373.      */
  374.     public final static int AM = 0;
  375.     /**
  376.      * Useful constant for hour in 12-hour clock. Used in GregorianCalendar.
  377.      */
  378.     public final static int PM = 1;
  379.  
  380.     // Internal notes:
  381.     // Calendar contains two kinds of time representations: current "time" in
  382.     // milliseconds, and a set of time "fields" representing the current time.
  383.     // The two representations are usually in sync, but can get out of sync
  384.     // as follows.
  385.     // 1. Initially, no fields are set, and the time is invalid.
  386.     // 2. If the time is set, all fields are computed and in sync.
  387.     // 3. If a single field is set, the time is invalid.
  388.     // Recomputation of the time and fields happens when the object needs
  389.     // to return a result to the user, or use a result for a computation.
  390.  
  391.     /**
  392.      * The time fields containing values into which the millis is computed.
  393.      */
  394.     protected int           fields[]; // NOTE: Make transient when possible
  395.  
  396.     /**
  397.      * The flags which tell if a specified time field for the calendar is set.
  398.      * A new object has no fields set.  After the first call to a method
  399.      * which generates the fields, they all remain set after that.
  400.      */
  401.     protected boolean       isSet[]; // NOTE: Remove when possible
  402.  
  403.     /**
  404.      * Pseudo-time-stamps which specify when each field was set. There
  405.      * are two special values, UNSET and INTERNALLY_SET. Values from
  406.      * MINIMUM_USER_SET to Integer.MAX_VALUE are legal user set values.
  407.      */
  408.     transient int           stamp[];
  409.  
  410.     /**
  411.      * The current time set for the calendar.
  412.      */
  413.     protected long          time;
  414.  
  415.     /**
  416.      * The flag which indicates if the current time is set for the calendar.
  417.      * The time is made invalid by the user setting an individual field.
  418.      */
  419.     protected boolean       isTimeSet; // NOTE: Make transient when possible
  420.  
  421.     /**
  422.      * True if the fields are in sync with the currently set time of this Calendar.
  423.      * If false, then the next attempt to get the value of a field will
  424.      * force a recomputation of all fields from the current value of the time
  425.      * field.
  426.      *
  427.      * This should really be named areFieldsInSync, but the old name is retained
  428.      * for backward compatibility.
  429.      */
  430.     protected boolean       areFieldsSet; // NOTE: Make transient when possible
  431.  
  432.     /**
  433.      * True if all fields have been set.
  434.      *
  435.      * NOTE: MAKE PROTECTED AT NEXT API CHANGE, or ADD ACCESSOR METHODS.
  436.      */
  437.     transient boolean       areAllFieldsSet;
  438.  
  439.     /**
  440.      * @see #setLenient
  441.      */
  442.     private boolean         lenient = true;
  443.  
  444.     /**
  445.      * Time zone affects the time calculation done by Calendar. Calendar uses
  446.      * the time zone data to produce the local time. Both firstDayOfWeek
  447.      * and minimalDaysInFirstWeek are locale-dependent. For example,
  448.      * in US locale, firstDayOfWeek is SUNDAY; minimalDaysInFirstWeek is 1.
  449.      * They are used to figure out the week count for a specific date for
  450.      * a given locale. These must be set when a Calendar is constructed.
  451.      */
  452.     private TimeZone        zone;
  453.     private int             firstDayOfWeek;
  454.     private int             minimalDaysInFirstWeek;
  455.  
  456.     /**
  457.      * Cache to hold the firstDayOfWeek and minimalDaysInFirstWeek
  458.      * of a Locale.
  459.      */
  460.     private static Hashtable cachedLocaleData = new Hashtable(3);
  461.  
  462.     // Special values of stamp[]
  463.     static final int        UNSET = 0;
  464.     static final int        INTERNALLY_SET = 1;
  465.     static final int        MINIMUM_USER_STAMP = 2;
  466.  
  467.     // The next available value for stampp[]
  468.     private int             nextStamp = MINIMUM_USER_STAMP;
  469.  
  470.     // the internal serial version which says which version was written
  471.     // - 0 (default) for version up to JDK 1.1.5
  472.     // - 1 for version from JDK 1.1.6, which writes a correct 'time' value
  473.     //     as well as compatible values for other fields.  This is a
  474.     //     transitional format.
  475.     // - 2 (not implemented yet) a future version, in which fields[],
  476.     //     areFieldsSet, and isTimeSet become transient, and isSet[] is
  477.     //     removed. In JDK 1.1.6 we write a format compatible with version 2.
  478.     static final int        currentSerialVersion = 1;
  479.     private int             serialVersionOnStream = currentSerialVersion;
  480.  
  481.     // Proclaim serialization compatibility with JDK 1.1
  482.     static final long       serialVersionUID = -1807547505821590642L;
  483.  
  484.     /**
  485.      * Constructs a Calendar with the default time zone as returned
  486.      * by TimeZone.getDefault(), and the default locale.
  487.      * @see     TimeZone#getDefault
  488.      */
  489.     protected Calendar()
  490.     {
  491.         this(TimeZone.getDefault(), Locale.getDefault());
  492.     }
  493.  
  494.     /**
  495.      * Constructs a Calendar with the given time zone and locale.
  496.      * @param zone the given time zone.
  497.      */
  498.     protected Calendar(TimeZone zone, Locale aLocale)
  499.     {
  500.         fields = new int[FIELD_COUNT];
  501.         isSet = new boolean[FIELD_COUNT];
  502.         stamp = new int[FIELD_COUNT];
  503.  
  504.         this.zone = zone;
  505.         setWeekCountData(aLocale);
  506.     }
  507.  
  508.     /**
  509.      * Gets a Calendar using the default timezone and locale.
  510.      * @return a Calendar.
  511.      */
  512.     public static synchronized Calendar getInstance()
  513.     {
  514.         return new GregorianCalendar();
  515.     }
  516.  
  517.     /**
  518.      * Gets a Calendar using the given timezone and default locale.
  519.      * @param zone the given timezone.
  520.      * @return a Calendar.
  521.      */
  522.     public static synchronized Calendar getInstance(TimeZone zone)
  523.     {
  524.         return new GregorianCalendar(zone, Locale.getDefault());
  525.     }
  526.  
  527.     /**
  528.      * Gets a Calendar using the default timezone and given locale.
  529.      * @param aLocale the given locale.
  530.      * @return a Calendar.
  531.      */
  532.     public static synchronized Calendar getInstance(Locale aLocale)
  533.     {
  534.         return new GregorianCalendar(TimeZone.getDefault(), aLocale);
  535.     }
  536.  
  537.     /**
  538.      * Gets a Calendar using the given timezone and given locale.
  539.      * @param zone the given timezone.
  540.      * @param aLocale the given locale.
  541.      * @return a Calendar.
  542.      */
  543.     public static synchronized Calendar getInstance(TimeZone zone,
  544.                                                     Locale aLocale)
  545.     {
  546.         return new GregorianCalendar(zone, aLocale);
  547.     }
  548.  
  549.     /**
  550.      * Gets the set of locales for which Calendars are installed.
  551.      * @return the set of locales for which Calendars are installed.
  552.      */
  553.     public static synchronized Locale[] getAvailableLocales()
  554.     {
  555.         return DateFormat.getAvailableLocales();
  556.     }
  557.  
  558.     /**
  559.      * Converts Calendar's time field values to UTC as milliseconds.
  560.      */
  561.     protected abstract void computeTime();
  562.  
  563.     /**
  564.      * Converts UTC as milliseconds to time field values.
  565.      * This allows you to sync up the time field values with
  566.      * a new time that is set for the calendar.  The time is <em>not</em>
  567.      * recomputed first; to recompute the time, then the fields, call the
  568.      * <code>complete</code> method.
  569.      * @see #complete
  570.      */
  571.     protected abstract void computeFields();
  572.  
  573.     /**
  574.      * Gets this Calendar's current time.
  575.      * @return the current time.
  576.      */
  577.     public final Date getTime() {
  578.         return new Date( getTimeInMillis() );
  579.     }
  580.  
  581.     /**
  582.      * Sets this Calendar's current time with the given Date.
  583.      * @param date the given Date.
  584.      */
  585.     public final void setTime(Date date) {
  586.         setTimeInMillis( date.getTime() );
  587.     }
  588.  
  589.     /**
  590.      * Gets this Calendar's current time as a long.
  591.      * @return the current time as UTC milliseconds from the epoch.
  592.      */
  593.     protected long getTimeInMillis() {
  594.         if (!isTimeSet) updateTime();
  595.         return time;
  596.     }
  597.  
  598.     /**
  599.      * Sets this Calendar's current time from the given long value.
  600.      * @param date the new time in UTC milliseconds from the epoch.
  601.      */
  602.     protected void setTimeInMillis( long millis ) {
  603.         isTimeSet = true;
  604.         time = millis;
  605.         areFieldsSet = false;
  606.         if (!areFieldsSet) {
  607.             computeFields();
  608.             areFieldsSet = true;
  609.             areAllFieldsSet = true;
  610.         }
  611.     }
  612.  
  613.     /**
  614.      * Gets the value for a given time field.
  615.      * @param field the given time field.
  616.      * @return the value for the given time field.
  617.      */
  618.     public final int get(int field)
  619.     {
  620.         complete();
  621.         return fields[field];
  622.     }
  623.  
  624.     /**
  625.      * Gets the value for a given time field. This is an internal
  626.      * fast time field value getter for the subclasses.
  627.      * @param field the given time field.
  628.      * @return the value for the given time field.
  629.      */
  630.     protected final int internalGet(int field)
  631.     {
  632.         return fields[field];
  633.     }
  634.  
  635.     /**
  636.      * Sets the value for the given time field.  This is an internal
  637.      * fast setter for subclasses.  It does not affect the areFieldsSet, isTimeSet,
  638.      * or areAllFieldsSet flags.
  639.      */
  640.     final void internalSet(int field, int value)
  641.     {
  642.         fields[field] = value;
  643.     }
  644.  
  645.     /**
  646.      * Sets the time field with the given value.
  647.      * @param field the given time field.
  648.      * @param value the value to be set for the given time field.
  649.      */
  650.     public final void set(int field, int value)
  651.     {
  652.         isTimeSet = false;
  653.         fields[field] = value;
  654.         stamp[field] = nextStamp++;
  655.         areFieldsSet = false;
  656.         isSet[field] = true; // Remove later
  657.     }
  658.  
  659.     /**
  660.      * Sets the values for the fields year, month, and date.
  661.      * Previous values of other fields are retained.  If this is not desired,
  662.      * call <code>clear</code> first.
  663.      * @param year the value used to set the YEAR time field.
  664.      * @param month the value used to set the MONTH time field.
  665.      * Month value is 0-based. e.g., 0 for January.
  666.      * @param date the value used to set the DATE time field.
  667.      */
  668.     public final void set(int year, int month, int date)
  669.     {
  670.         set(YEAR, year);
  671.         set(MONTH, month);
  672.         set(DATE, date);
  673.     }
  674.  
  675.     /**
  676.      * Sets the values for the fields year, month, date, hour, and minute.
  677.      * Previous values of other fields are retained.  If this is not desired,
  678.      * call <code>clear</code> first.
  679.      * @param year the value used to set the YEAR time field.
  680.      * @param month the value used to set the MONTH time field.
  681.      * Month value is 0-based. e.g., 0 for January.
  682.      * @param date the value used to set the DATE time field.
  683.      * @param hour the value used to set the HOUR_OF_DAY time field.
  684.      * @param minute the value used to set the MINUTE time field.
  685.      */
  686.     public final void set(int year, int month, int date, int hour, int minute)
  687.     {
  688.         set(YEAR, year);
  689.         set(MONTH, month);
  690.         set(DATE, date);
  691.         set(HOUR_OF_DAY, hour);
  692.         set(MINUTE, minute);
  693.     }
  694.  
  695.     /**
  696.      * Sets the values for the fields year, month, date, hour, minute, and second.
  697.      * Previous values of other fields are retained.  If this is not desired,
  698.      * call <code>clear</code> first.
  699.      * @param year the value used to set the YEAR time field.
  700.      * @param month the value used to set the MONTH time field.
  701.      * Month value is 0-based. e.g., 0 for January.
  702.      * @param date the value used to set the DATE time field.
  703.      * @param hour the value used to set the HOUR_OF_DAY time field.
  704.      * @param minute the value used to set the MINUTE time field.
  705.      * @param second the value used to set the SECOND time field.
  706.      */
  707.     public final void set(int year, int month, int date, int hour, int minute,
  708.                           int second)
  709.     {
  710.         set(YEAR, year);
  711.         set(MONTH, month);
  712.         set(DATE, date);
  713.         set(HOUR_OF_DAY, hour);
  714.         set(MINUTE, minute);
  715.         set(SECOND, second);
  716.     }
  717.  
  718.     /**
  719.      * Clears the values of all the time fields.
  720.      */
  721.     public final void clear()
  722.     {
  723.         fields = new int[FIELD_COUNT];
  724.         stamp = new int[FIELD_COUNT];
  725.         areFieldsSet = false;
  726.         areAllFieldsSet = false;
  727.         isSet = new boolean[FIELD_COUNT]; // Remove later
  728.     }
  729.  
  730.     /**
  731.      * Clears the value in the given time field.
  732.      * @param field the time field to be cleared.
  733.      */
  734.     public final void clear(int field)
  735.     {
  736.         fields[field] = 0;
  737.         stamp[field] = UNSET;
  738.         areFieldsSet = false;
  739.         areAllFieldsSet = false;
  740.         isSet[field] = false; // Remove later
  741.     }
  742.  
  743.     /**
  744.      * Determines if the given time field has a value set.
  745.      * @return true if the given time field has a value set; false otherwise.
  746.      */
  747.     public final boolean isSet(int field)
  748.     {
  749.         return stamp[field] != UNSET;
  750.         // return isSet[field];
  751.     }
  752.  
  753.     /**
  754.      * Fills in any unset fields in the time field list.
  755.      */
  756.     protected void complete()
  757.     {
  758.         if (!isTimeSet) updateTime();
  759.         if (!areFieldsSet) {
  760.             computeFields(); // fills in unset fields
  761.             areFieldsSet = true;
  762.             areAllFieldsSet = true;
  763.         }
  764.     }
  765.  
  766.     /**
  767.      * Compares this calendar to the specified object.
  768.      * The result is <code>true</code> if and only if the argument is
  769.      * not <code>null</code> and is a <code>Calendar</code> object that
  770.      * represents the same calendar as this object.
  771.      * @param obj the object to compare with.
  772.      * @return <code>true</code> if the objects are the same;
  773.      * <code>false</code> otherwise.
  774.      */
  775.     public boolean equals(Object obj) {
  776.         if (this == obj)
  777.             return true;
  778.         if (!(obj instanceof Calendar))
  779.             return false;
  780.  
  781.         Calendar that = (Calendar)obj;
  782.  
  783.         return getTimeInMillis() == that.getTimeInMillis() &&
  784.             lenient == that.lenient &&
  785.             firstDayOfWeek == that.firstDayOfWeek &&
  786.             minimalDaysInFirstWeek == that.minimalDaysInFirstWeek &&
  787.             zone.equals(that.zone);
  788.     }
  789.  
  790.     /**
  791.      * Compares the time field records.
  792.      * Equivalent to comparing result of conversion to UTC.
  793.      * @param when the Calendar to be compared with this Calendar.
  794.      * @return true if the current time of this Calendar is before
  795.      * the time of Calendar when; false otherwise.
  796.      */
  797.     public boolean before(Object when) {
  798.         return when instanceof Calendar &&
  799.             getTimeInMillis() < ((Calendar) when).getTimeInMillis();
  800.     }
  801.  
  802.     /**
  803.      * Compares the time field records.
  804.      * Equivalent to comparing result of conversion to UTC.
  805.      * @param when the Calendar to be compared with this Calendar.
  806.      * @return true if the current time of this Calendar is after
  807.      * the time of Calendar when; false otherwise.
  808.      */
  809.     public boolean after(Object when) {
  810.         return when instanceof Calendar &&
  811.             getTimeInMillis() > ((Calendar) when).getTimeInMillis();
  812.     }
  813.  
  814.     /**
  815.      * Date Arithmetic function.
  816.      * Adds the specified (signed) amount of time to the given time field,
  817.      * based on the calendar's rules. For example, to subtract 5 days from
  818.      * the current time of the calendar, you can achieve it by calling:
  819.      * <p>add(Calendar.DATE, -5).
  820.      * @param field the time field.
  821.      * @param amount the amount of date or time to be added to the field.
  822.      */
  823.     abstract public void add(int field, int amount);
  824.  
  825.     /**
  826.      * Time Field Rolling function.
  827.      * Rolls (up/down) a single unit of time on the given time field. For
  828.      * example, to roll the current date up by one day, you can achieve it
  829.      * by calling:
  830.      * <p>roll(Calendar.DATE, true).
  831.      * When rolling on the year or Calendar.YEAR field, it will roll the year
  832.      * value in the range between 1 and the value returned by calling
  833.      * getMaximum(Calendar.YEAR).
  834.      * When rolling on the month or Calendar.MONTH field, other fields like
  835.      * date might conflict and, need to be changed. For instance,
  836.      * rolling the month on the date 01/31/96 will result in 03/02/96.
  837.      * When rolling on the hour-in-day or Calendar.HOUR_OF_DAY field, it will
  838.      * roll the hour value in the range between 0 and 23, which is zero-based.
  839.      * @param field the time field.
  840.      * @param up indicates if the value of the specified time field is to be
  841.      * rolled up or rolled down. Use true if rolling up, false otherwise.
  842.      */
  843.     abstract public void roll(int field, boolean up);
  844.  
  845.     /**
  846.      * Time Field Rolling function.
  847.      * Rolls up or down the specified number of units on the given time field.
  848.      * (A negative roll amount means to roll down.)
  849.      * [NOTE:  This default implementation on Calendar just repeatedly calls the
  850.      * version of roll() that takes a boolean and rolls by one unit.  This may not
  851.      * always do the right thing.  For example, if the DAY_OF_MONTH field is 31,
  852.      * rolling through February will leave it set to 28.  The GregorianCalendar
  853.      * version of this function takes care of this problem.  Other subclasses
  854.      * should also provide overrides of this function that do the right thing.
  855.      */
  856.     public void roll(int field, int amount)
  857.     {
  858.         while (amount > 0) {
  859.             roll(field, true);
  860.             amount--;
  861.         }
  862.         while (amount < 0) {
  863.             roll(field, false);
  864.             amount++;
  865.         }
  866.     }
  867.  
  868.     /**
  869.      * Sets the time zone with the given time zone value.
  870.      * @param value the given time zone.
  871.      */
  872.     public void setTimeZone(TimeZone value)
  873.     {
  874.         zone = value;
  875.     }
  876.  
  877.     /**
  878.      * Gets the time zone.
  879.      * @return the time zone object associated with this calendar.
  880.      */
  881.     public TimeZone getTimeZone()
  882.     {
  883.         return zone;
  884.     }
  885.  
  886.     /**
  887.      * Specify whether or not date/time interpretation is to be lenient.  With
  888.      * lenient interpretation, a date such as "February 942, 1996" will be
  889.      * treated as being equivalent to the 941st day after February 1, 1996.
  890.      * With strict interpretation, such dates will cause an exception to be
  891.      * thrown.
  892.      *
  893.      * @see java.text.DateFormat#setLenient
  894.      */
  895.     public void setLenient(boolean lenient)
  896.     {
  897.         this.lenient = lenient;
  898.     }
  899.  
  900.     /**
  901.      * Tell whether date/time interpretation is to be lenient.
  902.      */
  903.     public boolean isLenient()
  904.     {
  905.         return lenient;
  906.     }
  907.  
  908.     /**
  909.      * Sets what the first day of the week is; e.g., Sunday in US,
  910.      * Monday in France.
  911.      * @param value the given first day of the week.
  912.      */
  913.     public void setFirstDayOfWeek(int value)
  914.     {
  915.         firstDayOfWeek = value;
  916.     }
  917.  
  918.     /**
  919.      * Gets what the first day of the week is; e.g., Sunday in US,
  920.      * Monday in France.
  921.      * @return the first day of the week.
  922.      */
  923.     public int getFirstDayOfWeek()
  924.     {
  925.         return firstDayOfWeek;
  926.     }
  927.  
  928.     /**
  929.      * Sets what the minimal days required in the first week of the year are;
  930.      * For example, if the first week is defined as one that contains the first
  931.      * day of the first month of a year, call the method with value 1. If it
  932.      * must be a full week, use value 7.
  933.      * @param value the given minimal days required in the first week
  934.      * of the year.
  935.      */
  936.     public void setMinimalDaysInFirstWeek(int value)
  937.     {
  938.         minimalDaysInFirstWeek = value;
  939.     }
  940.  
  941.     /**
  942.      * Gets what the minimal days required in the first week of the year are;
  943.      * e.g., if the first week is defined as one that contains the first day
  944.      * of the first month of a year, getMinimalDaysInFirstWeek returns 1. If
  945.      * the minimal days required must be a full week, getMinimalDaysInFirstWeek
  946.      * returns 7.
  947.      * @return the minimal days required in the first week of the year.
  948.      */
  949.     public int getMinimalDaysInFirstWeek()
  950.     {
  951.         return minimalDaysInFirstWeek;
  952.     }
  953.  
  954.     /**
  955.      * Gets the minimum value for the given time field.
  956.      * e.g., for Gregorian DAY_OF_MONTH, 1.
  957.      * @param field the given time field.
  958.      * @return the minimum value for the given time field.
  959.      */
  960.     abstract public int getMinimum(int field);
  961.  
  962.     /**
  963.      * Gets the maximum value for the given time field.
  964.      * e.g. for Gregorian DAY_OF_MONTH, 31.
  965.      * @param field the given time field.
  966.      * @return the maximum value for the given time field.
  967.      */
  968.     abstract public int getMaximum(int field);
  969.  
  970.     /**
  971.      * Gets the highest minimum value for the given field if varies.
  972.      * Otherwise same as getMinimum(). For Gregorian, no difference.
  973.      * @param field the given time field.
  974.      * @return the highest minimum value for the given time field.
  975.      */
  976.     abstract public int getGreatestMinimum(int field);
  977.  
  978.     /**
  979.      * Gets the lowest maximum value for the given field if varies.
  980.      * Otherwise same as getMaximum(). e.g., for Gregorian DAY_OF_MONTH, 28.
  981.      * @param field the given time field.
  982.      * @return the lowest maximum value for the given time field.
  983.      */
  984.     abstract public int getLeastMaximum(int field);
  985.  
  986.     /**
  987.      * Return the minimum value that this field could have, given the current date.
  988.      * For the Gregorian calendar, this is the same as getMinimum() and getGreatestMinimum().
  989.      *
  990.      * The version of this function on Calendar uses an iterative algorithm to determine the
  991.      * actual minimum value for the field.  There is almost always a more efficient way to
  992.      * accomplish this (in most cases, you can simply return getMinimum()).  GregorianCalendar
  993.      * overrides this function with a more efficient implementation.
  994.      */
  995. // function made package private pending API-change approval
  996.     /*public*/ int getActualMinimum(int field)
  997.     {
  998.         // if we know that the minimum value is always the same, just return it
  999.         if (getMinimum(field) == getGreatestMinimum(field))
  1000.             return getMinimum(field);
  1001.  
  1002.         // make sure all the fields are filled in
  1003.         complete();
  1004.  
  1005.         // clone the calendar so we don't mess with the real one, and set it to
  1006.         // accept anything for the field values
  1007.         Calendar work = (Calendar)this.clone();
  1008.         work.setLenient(true);
  1009.  
  1010.         // now try each value from getLeastMaximum() to getMaximum() one by one until
  1011.         // we get a value that normalizes to another value.  The last value that
  1012.         // normalizes to itself is the actual minimum for the current date
  1013.         int result = work.getGreatestMinimum(field);
  1014.         boolean found = false;
  1015.         int fieldValue = result;
  1016.         int endValue = work.getMinimum(field);
  1017.  
  1018.         do {
  1019.             work.set(field, fieldValue);
  1020.             work.complete();
  1021.             if (work.get(field) != fieldValue)
  1022.                 found = true;
  1023.             else {
  1024.                 result = fieldValue;
  1025.                 fieldValue--;
  1026.             }
  1027.         } while (!found && fieldValue >= endValue);
  1028.  
  1029.         return result;
  1030.     }
  1031.  
  1032.     /**
  1033.      * Return the maximum value that this field could have, given the current date.
  1034.      * For example, with the date "Feb 3, 1997" and the DAY_OF_MONTH field, the actual
  1035.      * maximum would be 28; for "Feb 3, 1996" it s 29.  Similarly for a Hebrew calendar,
  1036.      * for some years the actual maximum for MONTH is 12, and for others 13.
  1037.      *
  1038.      * The version of this function on Calendar uses an iterative algorithm to determine the
  1039.      * actual maximum value for the field.  There is almost always a more efficient way to
  1040.      * accomplish this (in most cases, you can simply return getMaximum()).  GregorianCalendar
  1041.      * overrides this function with a more efficient implementation.
  1042.      */
  1043. // function made package private pending API-change approval
  1044.     /*public*/ int getActualMaximum(int field)
  1045.     {
  1046.         // if we know that the maximum value is always the same, just return it
  1047.         if (getMaximum(field) == getLeastMaximum(field))
  1048.             return getMaximum(field);
  1049.  
  1050.         // make sure all the fields are filled in
  1051.         complete();
  1052.  
  1053.         // clone the calendar so we don't mess with the real one, and set it to
  1054.         // accept anything for the field values
  1055.         Calendar work = (Calendar)this.clone();
  1056.         work.setLenient(true);
  1057.  
  1058.         // if we're counting weeks, set the day of the week to Sunday.  We know the
  1059.         // last week of a month or year will contain a Sunday
  1060.         if (field == WEEK_OF_YEAR || field == WEEK_OF_MONTH)
  1061.             work.set(DAY_OF_WEEK, SUNDAY);
  1062.  
  1063.         // now try each value from getLeastMaximum() to getMaximum() one by one until
  1064.         // we get a value that normalizes to another value.  The last value that
  1065.         // normalizes to itself is the actual maximum for the current date
  1066.         int result = work.getLeastMaximum(field);
  1067.         boolean found = false;
  1068.         int fieldValue = result;
  1069.         int endValue = work.getMaximum(field);
  1070.  
  1071.         do {
  1072.             work.set(field, fieldValue);
  1073.             work.complete();
  1074.             if (work.get(field) != fieldValue)
  1075.                 found = true;
  1076.             else {
  1077.                 result = fieldValue;
  1078.                 fieldValue++;
  1079.             }
  1080.         } while (!found && fieldValue <= endValue);
  1081.  
  1082.         return result;
  1083.     }
  1084.  
  1085.     /**
  1086.      * Overrides Cloneable
  1087.      */
  1088.     public Object clone()
  1089.     {
  1090.         try {
  1091.             Calendar other = (Calendar) super.clone();
  1092.  
  1093.             other.fields = new int[FIELD_COUNT];
  1094.             other.isSet = new boolean[FIELD_COUNT];
  1095.             other.stamp = new int[FIELD_COUNT];
  1096.             System.arraycopy(this.fields, 0, other.fields, 0, FIELD_COUNT);
  1097.             System.arraycopy(this.isSet, 0, other.isSet, 0, FIELD_COUNT);
  1098.             System.arraycopy(this.stamp, 0, other.stamp, 0, FIELD_COUNT);
  1099.  
  1100.             other.zone = (TimeZone) zone.clone();
  1101.             return other;
  1102.         }
  1103.         catch (CloneNotSupportedException e) {
  1104.             // this shouldn't happen, since we are Cloneable
  1105.             throw new InternalError();
  1106.         }
  1107.     }
  1108.  
  1109.     private static final String[] FIELD_NAME = {
  1110.         ",ERA=", ",YEAR=", ",MONTH=", ",WEEK_OF_YEAR=", ",WEEK_OF_MONTH=", ",DAY_OF_MONTH=",
  1111.         ",DAY_OF_YEAR=", ",DAY_OF_WEEK=", ",DAY_OF_WEEK_IN_MONTH=", ",AM_PM=", ",HOUR=",
  1112.         ",HOUR_OF_DAY=", ",MINUTE=", ",SECOND=", ",MILLISECOND=", ",ZONE_OFFSET=",
  1113.         ",DST_OFFSET="
  1114.     };
  1115.  
  1116.     /**
  1117.      * Return a string representation of this calendar.
  1118.      * @return  a string representation of this calendar.
  1119.      */
  1120.     public String toString() {
  1121.         StringBuffer buffer = new StringBuffer();
  1122.         buffer.append(getClass().getName());
  1123.         buffer.append("[time=");
  1124.         buffer.append(isTimeSet ? String.valueOf(time) : "?");
  1125.         buffer.append(",areFieldsSet=");
  1126.         buffer.append(areFieldsSet);
  1127.         buffer.append(",areAllFieldsSet=");
  1128.         buffer.append(areAllFieldsSet);
  1129.         buffer.append(",lenient=");
  1130.         buffer.append(lenient);
  1131.         buffer.append(",zone=");
  1132.         buffer.append(zone);
  1133.         buffer.append(",firstDayOfWeek=");
  1134.         buffer.append(firstDayOfWeek);
  1135.         buffer.append(",minimalDaysInFirstWeek=");
  1136.         buffer.append(minimalDaysInFirstWeek);
  1137.         for (int i=0; i<FIELD_COUNT; ++i) {
  1138.             buffer.append(FIELD_NAME[i]);
  1139.             buffer.append(isSet(i) ? String.valueOf(fields[i]) : "?");
  1140.         }
  1141.         buffer.append(']');
  1142.         return buffer.toString();
  1143.     }
  1144.  
  1145.     // =======================privates===============================
  1146.  
  1147.     /**
  1148.      * Both firstDayOfWeek and minimalDaysInFirstWeek are locale-dependent.
  1149.      * They are used to figure out the week count for a specific date for
  1150.      * a given locale. These must be set when a Calendar is constructed.
  1151.      * @param desiredLocale the given locale.
  1152.      */
  1153.     private void setWeekCountData(Locale desiredLocale)
  1154.     {
  1155.     /* try to get the Locale data from the cache */
  1156.     int[] data = (int[]) cachedLocaleData.get(desiredLocale);
  1157.     if (data == null) {  /* cache miss */
  1158.         ResourceBundle resource
  1159.         = ResourceBundle.getBundle("java.text.resources.LocaleElements",
  1160.                        desiredLocale);
  1161.         String[] dateTimePatterns =
  1162.         resource.getStringArray("DateTimeElements");
  1163.         data = new int[2];
  1164.         data[0] = Integer.parseInt(dateTimePatterns[0]);
  1165.         data[1] = Integer.parseInt(dateTimePatterns[1]);
  1166.         /* cache update */
  1167.         cachedLocaleData.put(desiredLocale, data);
  1168.     }
  1169.     firstDayOfWeek = data[0];
  1170.     minimalDaysInFirstWeek = data[1];
  1171.     }
  1172.  
  1173.     /**
  1174.      * Recompute the time and update the status fields isTimeSet
  1175.      * and areFieldsSet.  Callers should check isTimeSet and only
  1176.      * call this method if isTimeSet is false.
  1177.      */
  1178.     private void updateTime() {
  1179.         computeTime();
  1180.         // If we are lenient, we need to recompute the fields to normalize
  1181.         // the values.  Also, if we haven't set all the fields yet (i.e.,
  1182.         // in a newly-created object), we need to fill in the fields. [LIU]
  1183.         if (isLenient() || !areAllFieldsSet) areFieldsSet = false;
  1184.         isTimeSet = true;
  1185.     }
  1186.  
  1187.     /**
  1188.      * Write object out to a serialization stream.
  1189.      */
  1190.     private void writeObject(ObjectOutputStream stream)
  1191.          throws IOException
  1192.     {
  1193.         /*
  1194.          * Calendar has many private fields that are not marked transient, such
  1195.          * as fields[], isTimeSet, and areFieldsSet.  In addition, it has a
  1196.          * field which is obsolete, isSet[]. These fields should not be part of
  1197.          * the persistent state. Unfortunately, this bug didn't get fixed before
  1198.          * JDK 1.1 shipped. This means that any fix has to be done in a way that
  1199.          * doesn't break serialization compatibility with 1.1. Fields in later
  1200.          * versions can only be removed from the serialized format (i.e., made
  1201.          * transient) if it can be shown that the Calendar implementation in 1.1
  1202.          * (and possibly modified versions in later releases) can function
  1203.          * correctly if all the removed fields are initialized to their default
  1204.          * values (0, null, false).
  1205.          *
  1206.          * If that's not possible, it might be possible that we'll declare for
  1207.          * some release that it's no longer two-way serialization compatible,
  1208.          * i.e., data can move from older to newer versions, but not back, or
  1209.          * back only to a specified release. To make that possible, we implement
  1210.          * a special form of serialization for now, such that (a) it works
  1211.          * correctly if fields that we intend to remove are initialized to their
  1212.          * default values and (b) the fields that we intend to keep are written
  1213.          * to streams with complete and up-to-date information so that the other
  1214.          * fields are not necessary. In other words, we write all fields, but on
  1215.          * reading ignore those that we intend to remove.
  1216.          */
  1217.  
  1218.         // Try to compute the time correctly, for the future (stream
  1219.         // version 2) in which we don't write out fields[] or isSet[].
  1220.         if (!isTimeSet) {
  1221.             try {
  1222.                 updateTime();
  1223.             }
  1224.             catch (IllegalArgumentException e) {}
  1225.         }
  1226.  
  1227.         // Write out the 1.1 FCS object.
  1228.         stream.defaultWriteObject();
  1229.     }
  1230.  
  1231.     /**
  1232.      * Read this object out to a serialization stream.
  1233.      */
  1234.     private void readObject(ObjectInputStream stream)
  1235.          throws IOException, ClassNotFoundException
  1236.     {
  1237.         stream.defaultReadObject();
  1238.  
  1239.         stamp = new int[FIELD_COUNT];
  1240.  
  1241.         // Starting with version 2 (not implemented yet), we expect that
  1242.         // fields[], isSet[], isTimeSet, and areFieldsSet may not be
  1243.         // streamed out anymore.  We expect 'time' to be correct.
  1244.         if (serialVersionOnStream >= 2)
  1245.         {
  1246.             isTimeSet = true;
  1247.             if (fields == null) fields = new int[FIELD_COUNT];
  1248.             if (isSet == null) isSet = new boolean[FIELD_COUNT];
  1249.         }
  1250.         else if (serialVersionOnStream == 0)
  1251.         {
  1252.             for (int i=0; i<FIELD_COUNT; ++i)
  1253.                 stamp[i] = isSet[i] ? INTERNALLY_SET : UNSET;
  1254.         }
  1255.  
  1256.         serialVersionOnStream = currentSerialVersion;
  1257.     }
  1258. }
  1259.