/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
/**
*******************************************************************************
* Copyright (C) 1996-2008, International Business Machines Corporation and    *
* others. All Rights Reserved.                                                *
*******************************************************************************
*/

package java.util;


import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;

// BEGIN android-note
// The class javadoc and some of the method descriptions are copied from ICU4J
// source files. Changes have been made to the copied descriptions.
// The icu license header was added to this file. 
// END android-note
/**
 * {@code Calendar} is an abstract base class for converting between a
 * {@code Date} object and a set of integer fields such as
 * {@code YEAR}, {@code MONTH}, {@code DAY},
 * {@code HOUR}, and so on. (A {@code Date} object represents a
 * specific instant in time with millisecond precision. See {@link Date} for
 * information about the {@code Date} class.)
 * 
 * <p>
 * Subclasses of {@code Calendar} interpret a {@code Date}
 * according to the rules of a specific calendar system.
 * 
 * <p>
 * Like other locale-sensitive classes, {@code Calendar} provides a class
 * method, {@code getInstance}, for getting a default instance of
 * this class for general use. {@code Calendar}'s {@code getInstance} method
 * returns a calendar whose locale is based on system settings and whose time fields
 * have been initialized with the current date and time: <blockquote>
 * 
 * <pre>Calendar rightNow = Calendar.getInstance()</pre>
 * 
 * </blockquote>
 * 
 * <p>
 * A {@code Calendar} object can produce all the time field values needed
 * to implement the date-time formatting for a particular language and calendar
 * style (for example, Japanese-Gregorian, Japanese-Traditional).
 * {@code Calendar} defines the range of values returned by certain
 * fields, as well as their meaning. For example, the first month of the year
 * has value {@code MONTH} == {@code JANUARY} for all calendars.
 * Other values are defined by the concrete subclass, such as {@code ERA}
 * and {@code YEAR}. See individual field documentation and subclass
 * documentation for details.
 * 
 * <p>
 * When a {@code Calendar} is <em>lenient</em>, it accepts a wider
 * range of field values than it produces. For example, a lenient
 * {@code GregorianCalendar} interprets {@code MONTH} ==
 * {@code JANUARY}, {@code DAY_OF_MONTH} == 32 as February 1. A
 * non-lenient {@code GregorianCalendar} throws an exception when given
 * out-of-range field settings. When calendars recompute field values for return
 * by {@code get()}, they normalize them. For example, a
 * {@code GregorianCalendar} always produces {@code DAY_OF_MONTH}
 * values between 1 and the length of the month.
 * 
 * <p>
 * {@code Calendar} defines a locale-specific seven day week using two
 * parameters: the first day of the week and the minimal days in first week
 * (from 1 to 7). These numbers are taken from the locale resource data when a
 * {@code Calendar} is constructed. They may also be specified explicitly
 * through the API.
 * 
 * <p>
 * When setting or getting the {@code WEEK_OF_MONTH} or
 * {@code WEEK_OF_YEAR} fields, {@code Calendar} must determine
 * the first week of the month or year as a reference point. The first week of a
 * month or year is defined as the earliest seven day period beginning on
 * {@code getFirstDayOfWeek()} and containing at least
 * {@code getMinimalDaysInFirstWeek()} days of that month or year. Weeks
 * numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow
 * it. Note that the normalized numbering returned by {@code get()} may
 * be different. For example, a specific {@code Calendar} subclass may
 * designate the week before week 1 of a year as week <em>n</em> of the
 * previous year.
 * 
 * <p>
 * When computing a {@code Date} from time fields, two special
 * circumstances may arise: there may be insufficient information to compute the
 * {@code Date} (such as only year and month but no day in the month), or
 * there may be inconsistent information (such as "Tuesday, July 15, 1996" --
 * July 15, 1996 is actually a Monday).
 * 
 * <p>
 * <strong>Insufficient information.</strong> The calendar will use default
 * information to specify the missing fields. This may vary by calendar; for the
 * Gregorian calendar, the default for a field is the same as that of the start
 * of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc.
 * 
 * <p>
 * <strong>Inconsistent information.</strong> If fields conflict, the calendar
 * will give preference to fields set more recently. For example, when
 * determining the day, the calendar will look for one of the following
 * combinations of fields. The most recent combination, as determined by the
 * most recently set single field, will be used.
 * 
 * <blockquote>
 * 
 * <pre>
 * MONTH + DAY_OF_MONTH
 * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
 * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
 * DAY_OF_YEAR
 * DAY_OF_WEEK + WEEK_OF_YEAR</pre>
 * 
 * </blockquote>
 * 
 * For the time of day:
 * 
 * <blockquote>
 * 
 * <pre>
 * HOUR_OF_DAY
 * AM_PM + HOUR</pre>
 * 
 * </blockquote>
 * 
 * <p>
 * <strong>Note:</strong> There are certain possible ambiguities in
 * interpretation of certain singular times, which are resolved in the following
 * ways:
 * <ol>
 * <li> 24:00:00 "belongs" to the following day. That is, 23:59 on Dec 31, 1969
 * &lt; 24:00 on Jan 1, 1970 &lt; 24:01:00 on Jan 1, 1970 form a sequence of 
 * three consecutive minutes in time. 
 * 
 * <li> Although historically not precise, midnight also belongs to "am", and
 * noon belongs to "pm", so on the same day, we have 12:00 am (midnight) &lt; 12:01 am,
 * and 12:00 pm (noon) &lt; 12:01 pm
 * </ol>
 * 
 * <p>
 * The date or time format strings are not part of the definition of a calendar,
 * as those must be modifiable or overridable by the user at runtime. Use
 * {@link java.text.DateFormat} to format dates.
 * 
 * <p>
 * <strong>Field manipulation methods</strong>
 * </p>
 * 
 * <p>
 * {@code Calendar} fields can be changed using three methods:
 * {@code set()}, {@code add()}, and {@code roll()}.
 * </p>
 * 
 * <p>
 * <strong>{@code set(f, value)}</strong> changes field {@code f}
 * to {@code value}. In addition, it sets an internal member variable to
 * indicate that field {@code f} has been changed. Although field
 * {@code f} is changed immediately, the calendar's milliseconds is not
 * recomputed until the next call to {@code get()},
 * {@code getTime()}, or {@code getTimeInMillis()} is made. Thus,
 * multiple calls to {@code set()} do not trigger multiple, unnecessary
 * computations. As a result of changing a field using {@code set()},
 * other fields may also change, depending on the field, the field value, and
 * the calendar system. In addition, {@code get(f)} will not necessarily
 * return {@code value} after the fields have been recomputed. The
 * specifics are determined by the concrete calendar class.
 * </p>
 * 
 * <p>
 * <em>Example</em>: Consider a {@code GregorianCalendar} originally
 * set to August 31, 1999. Calling <code>set(Calendar.MONTH,
 * Calendar.SEPTEMBER)</code>
 * sets the calendar to September 31, 1999. This is a temporary internal
 * representation that resolves to October 1, 1999 if {@code getTime()}is
 * then called. However, a call to {@code set(Calendar.DAY_OF_MONTH, 30)}
 * before the call to {@code getTime()} sets the calendar to September
 * 30, 1999, since no recomputation occurs after {@code set()} itself.
 * </p>
 * 
 * <p>
 * <strong>{@code add(f, delta)}</strong> adds {@code delta} to
 * field {@code f}. This is equivalent to calling <code>set(f,
 * get(f) + delta)</code>
 * with two adjustments:
 * </p>
 * 
 * <blockquote>
 * <p>
 * <strong>Add rule 1</strong>. The value of field {@code f} after the
 * call minus the value of field {@code f} before the call is
 * {@code delta}, modulo any overflow that has occurred in field
 * {@code f}. Overflow occurs when a field value exceeds its range and,
 * as a result, the next larger field is incremented or decremented and the
 * field value is adjusted back into its range.
 * </p>
 * 
 * <p>
 * <strong>Add rule 2</strong>. If a smaller field is expected to be invariant,
 * but &nbsp; it is impossible for it to be equal to its prior value because of
 * changes in its minimum or maximum after field {@code f} is changed,
 * then its value is adjusted to be as close as possible to its expected value.
 * A smaller field represents a smaller unit of time. {@code HOUR} is a
 * smaller field than {@code DAY_OF_MONTH}. No adjustment is made to
 * smaller fields that are not expected to be invariant. The calendar system
 * determines what fields are expected to be invariant.
 * </p>
 * </blockquote>
 * 
 * <p>
 * In addition, unlike {@code set()}, {@code add()} forces an
 * immediate recomputation of the calendar's milliseconds and all fields.
 * </p>
 * 
 * <p>
 * <em>Example</em>: Consider a {@code GregorianCalendar} originally
 * set to August 31, 1999. Calling {@code add(Calendar.MONTH, 13)} sets
 * the calendar to September 30, 2000. <strong>Add rule 1</strong> sets the
 * {@code MONTH} field to September, since adding 13 months to August
 * gives September of the next year. Since {@code DAY_OF_MONTH} cannot be
 * 31 in September in a {@code GregorianCalendar}, <strong>add rule 2</strong>
 * sets the {@code DAY_OF_MONTH} to 30, the closest possible value.
 * Although it is a smaller field, {@code DAY_OF_WEEK} is not adjusted by
 * rule 2, since it is expected to change when the month changes in a
 * {@code GregorianCalendar}.
 * </p>
 * 
 * <p>
 * <strong>{@code roll(f, delta)}</strong> adds {@code delta} to
 * field {@code f} without changing larger fields. This is equivalent to
 * calling {@code add(f, delta)} with the following adjustment:
 * </p>
 * 
 * <blockquote>
 * <p>
 * <strong>Roll rule</strong>. Larger fields are unchanged after the call. A
 * larger field represents a larger unit of time. {@code DAY_OF_MONTH} is
 * a larger field than {@code HOUR}.
 * </p>
 * </blockquote>
 * 
 * <p>
 * <em>Example</em>: Consider a {@code GregorianCalendar} originally
 * set to August 31, 1999. Calling <code>roll(Calendar.MONTH,
 * 8)</code> sets
 * the calendar to April 30, <strong>1999</strong>. Add rule 1 sets the
 * {@code MONTH} field to April. Using a {@code GregorianCalendar},
 * the {@code DAY_OF_MONTH} cannot be 31 in the month April. Add rule 2
 * sets it to the closest possible value, 30. Finally, the <strong>roll rule</strong>
 * maintains the {@code YEAR} field value of 1999.
 * </p>
 * 
 * <p>
 * <em>Example</em>: Consider a {@code GregorianCalendar} originally
 * set to Sunday June 6, 1999. Calling
 * {@code roll(Calendar.WEEK_OF_MONTH, -1)} sets the calendar to Tuesday
 * June 1, 1999, whereas calling {@code add(Calendar.WEEK_OF_MONTH, -1)}
 * sets the calendar to Sunday May 30, 1999. This is because the roll rule
 * imposes an additional constraint: The {@code MONTH} must not change
 * when the {@code WEEK_OF_MONTH} is rolled. Taken together with add rule
 * 1, the resultant date must be between Tuesday June 1 and Saturday June 5.
 * According to add rule 2, the {@code DAY_OF_WEEK}, an invariant when
 * changing the {@code WEEK_OF_MONTH}, is set to Tuesday, the closest
 * possible value to Sunday (where Sunday is the first day of the week).
 * </p>
 * 
 * <p>
 * <strong>Usage model</strong>. To motivate the behavior of {@code add()}
 * and {@code roll()}, consider a user interface component with
 * increment and decrement buttons for the month, day, and year, and an
 * underlying {@code GregorianCalendar}. If the interface reads January
 * 31, 1999 and the user presses the month increment button, what should it
 * read? If the underlying implementation uses {@code set()}, it might
 * read March 3, 1999. A better result would be February 28, 1999. Furthermore,
 * if the user presses the month increment button again, it should read March
 * 31, 1999, not March 28, 1999. By saving the original date and using either
 * {@code add()} or {@code roll()}, depending on whether larger
 * fields should be affected, the user interface can behave as most users will
 * intuitively expect.
 * </p>
 * 
 * <p>
 * <b>Note:</b> You should always use {@code roll} and {@code add} rather than
 * attempting to perform arithmetic operations directly on the fields of a
 * <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses
 * to have fields with non-linear behavior, for example missing months or days
 * during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt>
 * methods will take this into account, while simple arithmetic manipulations
 * may give invalid results.
 * 
 * @see Date
 * @see GregorianCalendar
 * @see TimeZone
 * @since Android 1.0
 */
public abstract class Calendar implements Serializable, Cloneable,
        Comparable<Calendar> {

    private static final long serialVersionUID = -1807547505821590642L;

    /**
     * Set to {@code true} when the calendar fields have been set from the time, set to
     * {@code false} when a field is changed and the fields must be recomputed.
     * 
     * @since Android 1.0
     */
    protected boolean areFieldsSet;

    /**
     * An integer array of calendar fields. The length is {@code FIELD_COUNT}.
     * 
     * @since Android 1.0
     */
    protected int[] fields;

    /**
     * A boolean array. Each element indicates if the corresponding field has
     * been set. The length is {@code FIELD_COUNT}.
     * 
     * @since Android 1.0
     */
    protected boolean[] isSet;

    /**
     * Set to {@code true} when the time has been set, set to {@code false} when a field is
     * changed and the time must be recomputed.
     * 
     * @since Android 1.0
     */
    protected boolean isTimeSet;

    /**
     * The time in milliseconds since January 1, 1970.
     * 
     * @since Android 1.0
     */
    protected long time;

    transient int lastTimeFieldSet;

    transient int lastDateFieldSet;

    private boolean lenient;

    private int firstDayOfWeek;

    private int minimalDaysInFirstWeek;

    private TimeZone zone;

    // BEGIN android-changed
    /**
     * Value of the {@code MONTH} field indicating the first month of the
     * year.
     * 
     * @since Android 1.0
     */
    public static final int JANUARY = 0;

    /**
     * Value of the {@code MONTH} field indicating the second month of
     * the year.
     * 
     * @since Android 1.0
     */
    public static final int FEBRUARY = 1;

    /**
     * Value of the {@code MONTH} field indicating the third month of the
     * year.
     * 
     * @since Android 1.0
     */
    public static final int MARCH = 2;

    /**
     * Value of the {@code MONTH} field indicating the fourth month of
     * the year.
     * 
     * @since Android 1.0
     */
    public static final int APRIL = 3;

    /**
     * Value of the {@code MONTH} field indicating the fifth month of the
     * year.
     * 
     * @since Android 1.0
     */
    public static final int MAY = 4;

    /**
     * Value of the {@code MONTH} field indicating the sixth month of the
     * year.
     * 
     * @since Android 1.0
     */
    public static final int JUNE = 5;

    /**
     * Value of the {@code MONTH} field indicating the seventh month of
     * the year.
     * 
     * @since Android 1.0
     */
    public static final int JULY = 6;

    /**
     * Value of the {@code MONTH} field indicating the eighth month of
     * the year.
     * 
     * @since Android 1.0
     */
    public static final int AUGUST = 7;

    /**
     * Value of the {@code MONTH} field indicating the ninth month of the
     * year.
     * 
     * @since Android 1.0
     */
    public static final int SEPTEMBER = 8;

    /**
     * Value of the {@code MONTH} field indicating the tenth month of the
     * year.
     * 
     * @since Android 1.0
     */
    public static final int OCTOBER = 9;

    /**
     * Value of the {@code MONTH} field indicating the eleventh month of
     * the year.
     * 
     * @since Android 1.0
     */
    public static final int NOVEMBER = 10;

    /**
     * Value of the {@code MONTH} field indicating the twelfth month of
     * the year.
     * 
     * @since Android 1.0
     */
    public static final int DECEMBER = 11;

    /**
     * Value of the {@code MONTH} field indicating the thirteenth month
     * of the year. Although {@code GregorianCalendar} does not use this
     * value, lunar calendars do.
     * 
     * @since Android 1.0
     */
    public static final int UNDECIMBER = 12;

    /**
     * Value of the {@code DAY_OF_WEEK} field indicating Sunday.
     * 
     * @since Android 1.0
     */
    public static final int SUNDAY = 1;

    /**
     * Value of the {@code DAY_OF_WEEK} field indicating Monday.
     * 
     * @since Android 1.0
     */
    public static final int MONDAY = 2;

    /**
     * Value of the {@code DAY_OF_WEEK} field indicating Tuesday.
     * 
     * @since Android 1.0
     */
    public static final int TUESDAY = 3;

    /**
     * Value of the {@code DAY_OF_WEEK} field indicating Wednesday.
     * 
     * @since Android 1.0
     */
    public static final int WEDNESDAY = 4;

    /**
     * Value of the {@code DAY_OF_WEEK} field indicating Thursday.
     * 
     * @since Android 1.0
     */
    public static final int THURSDAY = 5;

    /**
     * Value of the {@code DAY_OF_WEEK} field indicating Friday.
     * 
     * @since Android 1.0
     */
    public static final int FRIDAY = 6;

    /**
     * Value of the {@code DAY_OF_WEEK} field indicating Saturday.
     * 
     * @since Android 1.0
     */
    public static final int SATURDAY = 7;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific
     * value; see subclass documentation.
     * 
     * @see GregorianCalendar#AD
     * @see GregorianCalendar#BC
     * 
     * @since Android 1.0
     */
    public static final int ERA = 0;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * year. This is a calendar-specific value; see subclass documentation.
     * 
     * @since Android 1.0
     */
    public static final int YEAR = 1;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * month. This is a calendar-specific value. The first month of the year is
     * {@code JANUARY}; the last depends on the number of months in a
     * year.
     * 
     * @see #JANUARY
     * @see #FEBRUARY
     * @see #MARCH
     * @see #APRIL
     * @see #MAY
     * @see #JUNE
     * @see #JULY
     * @see #AUGUST
     * @see #SEPTEMBER
     * @see #OCTOBER
     * @see #NOVEMBER
     * @see #DECEMBER
     * @see #UNDECIMBER
     * 
     * @since Android 1.0
     */
    public static final int MONTH = 2;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * week number within the current year. The first week of the year, as
     * defined by {@code getFirstDayOfWeek()} and
     * {@code getMinimalDaysInFirstWeek()}, has value 1. Subclasses
     * define the value of {@code WEEK_OF_YEAR} for days before the first
     * week of the year.
     * 
     * @see #getFirstDayOfWeek
     * @see #getMinimalDaysInFirstWeek
     * 
     * @since Android 1.0
     */
    public static final int WEEK_OF_YEAR = 3;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * week number within the current month. The first week of the month, as
     * defined by {@code getFirstDayOfWeek()} and
     * {@code getMinimalDaysInFirstWeek()}, has value 1. Subclasses
     * define the value of {@code WEEK_OF_MONTH} for days before the
     * first week of the month.
     * 
     * @see #getFirstDayOfWeek
     * @see #getMinimalDaysInFirstWeek
     * 
     * @since Android 1.0
     */
    public static final int WEEK_OF_MONTH = 4;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * day of the month. This is a synonym for {@code DAY_OF_MONTH}. The
     * first day of the month has value 1.
     * 
     * @see #DAY_OF_MONTH
     * 
     * @since Android 1.0
     */
    public static final int DATE = 5;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * day of the month. This is a synonym for {@code DATE}. The first
     * day of the month has value 1.
     * 
     * @see #DATE
     * 
     * @since Android 1.0
     */
    public static final int DAY_OF_MONTH = 5;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * day number within the current year. The first day of the year has value
     * 1.
     * 
     * @since Android 1.0
     */
    public static final int DAY_OF_YEAR = 6;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * day of the week. This field takes values {@code SUNDAY},
     * {@code MONDAY}, {@code TUESDAY}, {@code WEDNESDAY},
     * {@code THURSDAY}, {@code FRIDAY}, and
     * {@code SATURDAY}.
     * 
     * @see #SUNDAY
     * @see #MONDAY
     * @see #TUESDAY
     * @see #WEDNESDAY
     * @see #THURSDAY
     * @see #FRIDAY
     * @see #SATURDAY
     * 
     * @since Android 1.0
     */
    public static final int DAY_OF_WEEK = 7;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * ordinal number of the day of the week within the current month. Together
     * with the {@code DAY_OF_WEEK} field, this uniquely specifies a day
     * within a month. Unlike {@code WEEK_OF_MONTH} and
     * {@code WEEK_OF_YEAR}, this field's value does <em>not</em>
     * depend on {@code getFirstDayOfWeek()} or
     * {@code getMinimalDaysInFirstWeek()}. {@code DAY_OF_MONTH 1}
     * through {@code 7} always correspond to <code>DAY_OF_WEEK_IN_MONTH
     * 1</code>;
     * {@code 8} through {@code 15} correspond to
     * {@code DAY_OF_WEEK_IN_MONTH 2}, and so on.
     * {@code DAY_OF_WEEK_IN_MONTH 0} indicates the week before
     * {@code DAY_OF_WEEK_IN_MONTH 1}. Negative values count back from
     * the end of the month, so the last Sunday of a month is specified as
     * {@code DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1}. Because
     * negative values count backward they will usually be aligned differently
     * within the month than positive values. For example, if a month has 31
     * days, {@code DAY_OF_WEEK_IN_MONTH -1} will overlap
     * {@code DAY_OF_WEEK_IN_MONTH 5} and the end of {@code 4}.
     * 
     * @see #DAY_OF_WEEK
     * @see #WEEK_OF_MONTH
     * 
     * @since Android 1.0
     */
    public static final int DAY_OF_WEEK_IN_MONTH = 8;

    /**
     * Field number for {@code get} and {@code set} indicating
     * whether the {@code HOUR} is before or after noon. E.g., at
     * 10:04:15.250 PM the {@code AM_PM} is {@code PM}.
     * 
     * @see #AM
     * @see #PM
     * @see #HOUR
     * 
     * @since Android 1.0
     */
    public static final int AM_PM = 9;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * hour of the morning or afternoon. {@code HOUR} is used for the
     * 12-hour clock. E.g., at 10:04:15.250 PM the {@code HOUR} is 10.
     * 
     * @see #AM_PM
     * @see #HOUR_OF_DAY
     * 
     * @since Android 1.0
     */
    public static final int HOUR = 10;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * hour of the day. {@code HOUR_OF_DAY} is used for the 24-hour
     * clock. E.g., at 10:04:15.250 PM the {@code HOUR_OF_DAY} is 22.
     * 
     * @see #HOUR
     * 
     * @since Android 1.0
     */
    public static final int HOUR_OF_DAY = 11;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * minute within the hour. E.g., at 10:04:15.250 PM the {@code MINUTE}
     * is 4.
     * 
     * @since Android 1.0
     */
    public static final int MINUTE = 12;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * second within the minute. E.g., at 10:04:15.250 PM the
     * {@code SECOND} is 15.
     * 
     * @since Android 1.0
     */
    public static final int SECOND = 13;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * millisecond within the second. E.g., at 10:04:15.250 PM the
     * {@code MILLISECOND} is 250.
     * 
     * @since Android 1.0
     */
    public static final int MILLISECOND = 14;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * raw offset from GMT in milliseconds.
     * 
     * @since Android 1.0
     */
    public static final int ZONE_OFFSET = 15;

    /**
     * Field number for {@code get} and {@code set} indicating the
     * daylight savings offset in milliseconds.
     * 
     * @since Android 1.0
     */
    public static final int DST_OFFSET = 16;

    /**
     * This is the total number of fields in this calendar.
     * 
     * @since Android 1.0
     */
    public static final int FIELD_COUNT = 17;

    /**
     * Value of the {@code AM_PM} field indicating the period of the day
     * from midnight to just before noon.
     * 
     * @since Android 1.0
     */
    public static final int AM = 0;

    /**
     * Value of the {@code AM_PM} field indicating the period of the day
     * from noon to just before midnight.
     * 
     * @since Android 1.0
     */
    public static final int PM = 1;
    // END android-changed

    private static String[] fieldNames = { "ERA=", "YEAR=", "MONTH=", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            "WEEK_OF_YEAR=", "WEEK_OF_MONTH=", "DAY_OF_MONTH=", "DAY_OF_YEAR=",  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
            "DAY_OF_WEEK=", "DAY_OF_WEEK_IN_MONTH=", "AM_PM=", "HOUR=",   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
            "HOUR_OF_DAY", "MINUTE=", "SECOND=", "MILLISECOND=", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
            "ZONE_OFFSET=", "DST_OFFSET=" }; //$NON-NLS-1$ //$NON-NLS-2$

    /**
     * Constructs a {@code Calendar} instance using the default {@code TimeZone} and {@code Locale}.
     * 
     * @since Android 1.0
     */
    protected Calendar() {
        this(TimeZone.getDefault(), Locale.getDefault());
    }

    Calendar(TimeZone timezone) {
        fields = new int[FIELD_COUNT];
        isSet = new boolean[FIELD_COUNT];
        areFieldsSet = isTimeSet = false;
        setLenient(true);
        setTimeZone(timezone);
    }

    /**
     * Constructs a {@code Calendar} instance using the specified {@code TimeZone} and {@code Locale}.
     * 
     * @param timezone
     *            the timezone.
     * @param locale
     *            the locale.
     * 
     * @since Android 1.0
     */
    protected Calendar(TimeZone timezone, Locale locale) {
        this(timezone);
        ResourceBundle bundle = Locale.getBundle("Locale", locale); //$NON-NLS-1$
        setFirstDayOfWeek(((Integer) bundle.getObject("First_Day")).intValue()); //$NON-NLS-1$
        setMinimalDaysInFirstWeek(((Integer) bundle.getObject("Minimal_Days")) //$NON-NLS-1$
                .intValue());
    }

    /**
     * Adds the specified amount to a {@code Calendar} field.
     * 
     * @param field
     *            the {@code Calendar} field to modify.
     * @param value
     *            the amount to add to the field.
     * @since Android 1.0
     */
    abstract public void add(int field, int value);

    /**
     * Returns whether the {@code Date} specified by this {@code Calendar} instance is after the {@code Date}
     * specified by the parameter. The comparison is not dependent on the time
     * zones of the {@code Calendar}.
     * 
     * @param calendar
     *            the {@code Calendar} instance to compare.
     * @return {@code true} when this Calendar is after calendar, {@code false} otherwise.
     * @since Android 1.0
     */
    public boolean after(Object calendar) {
        if (!(calendar instanceof Calendar)) {
            return false;
        }
        return getTimeInMillis() > ((Calendar) calendar).getTimeInMillis();
    }

    /**
     * Returns whether the {@code Date} specified by this {@code Calendar} instance is before the
     * {@code Date} specified by the parameter. The comparison is not dependent on the
     * time zones of the {@code Calendar}.
     * 
     * @param calendar
     *            the {@code Calendar} instance to compare.
     * @return {@code true} when this Calendar is before calendar, {@code false} otherwise.
     * @since Android 1.0
     */
    public boolean before(Object calendar) {
        if (!(calendar instanceof Calendar)) {
            return false;
        }
        return getTimeInMillis() < ((Calendar) calendar).getTimeInMillis();
    }

    /**
     * Clears all of the fields of this {@code Calendar}. All fields are initialized to
     * zero.
     * 
     * @since Android 1.0
     */
    public final void clear() {
        for (int i = 0; i < FIELD_COUNT; i++) {
            fields[i] = 0;
            isSet[i] = false;
        }
        areFieldsSet = isTimeSet = false;
    }

    /**
     * Clears the specified field to zero and sets the isSet flag to {@code false}.
     * 
     * @param field
     *            the field to clear.
     * @since Android 1.0
     */
    public final void clear(int field) {
        fields[field] = 0;
        isSet[field] = false;
        areFieldsSet = isTimeSet = false;
    }

    /**
     * Returns a new {@code Calendar} with the same properties.
     * 
     * @return a shallow copy of this {@code Calendar}.
     * 
     * @see java.lang.Cloneable
     * @since Android 1.0
     */
    @Override
    public Object clone() {
        try {
            Calendar clone = (Calendar) super.clone();
            clone.fields = fields.clone();
            clone.isSet = isSet.clone();
            clone.zone = (TimeZone) zone.clone();
            return clone;
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }

    /**
     * Computes the time from the fields if the time has not already been set.
     * Computes the fields from the time if the fields are not already set.
     * 
     * @exception IllegalArgumentException
     *                when the time is not set and the time cannot be computed
     *                from the current field values.
     * @since Android 1.0
     */
    protected void complete() {
        if (!isTimeSet) {
            computeTime();
            isTimeSet = true;
        }
        if (!areFieldsSet) {
            computeFields();
            areFieldsSet = true;
        }
    }

    /**
     * Computes the {@code Calendar} fields from {@code time}.
     * 
     * @since Android 1.0
     */
    protected abstract void computeFields();

    /**
     * Computes {@code time} from the Calendar fields.
     * 
     * @exception IllegalArgumentException
     *                when the time cannot be computed from the current field
     *                values.
     * @since Android 1.0
     */
    protected abstract void computeTime();

    /**
     * Compares the specified object to this {@code Calendar} and returns whether they are
     * equal. The object must be an instance of {@code Calendar} and have the same
     * properties.
     * 
     * @param object
     *            the object to compare with this object.
     * @return {@code true} if the specified object is equal to this {@code Calendar}, {@code false}
     *         otherwise.
     * @since Android 1.0
     */
    @Override
    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }
        if (!(object instanceof Calendar)) {
            return false;
        }
        Calendar cal = (Calendar) object;
        return getTimeInMillis() == cal.getTimeInMillis()
                && isLenient() == cal.isLenient()
                && getFirstDayOfWeek() == cal.getFirstDayOfWeek()
                && getMinimalDaysInFirstWeek() == cal
                        .getMinimalDaysInFirstWeek()
                && getTimeZone().equals(cal.getTimeZone());
    }

    /**
     * Gets the value of the specified field after computing the field values by
     * calling {@code complete()} first.
     * 
     * @param field
     *            the field to get.
     * @return the value of the specified field.
     * 
     * @exception IllegalArgumentException
     *                when the fields are not set, the time is not set, and the
     *                time cannot be computed from the current field values.
     * @exception ArrayIndexOutOfBoundsException
     *                if the field is not inside the range of possible fields.
     *                The range is starting at 0 up to {@code FIELD_COUNT}.
     * @since Android 1.0
     */
    public int get(int field) {
        complete();
        return fields[field];
    }

    /**
     * Gets the maximum value of the specified field for the current date.
     * 
     * @param field
     *            the field.
     * @return the maximum value of the specified field.
     * @since Android 1.0
     */
    public int getActualMaximum(int field) {
        int value, next;
        if (getMaximum(field) == (next = getLeastMaximum(field))) {
            return next;
        }
        complete();
        long orgTime = time;
        set(field, next);
        do {
            value = next;
            roll(field, true);
            next = get(field);
        } while (next > value);
        time = orgTime;
        areFieldsSet = false;
        return value;
    }

    /**
     * Gets the minimum value of the specified field for the current date.
     * 
     * @param field
     *            the field.
     * @return the minimum value of the specified field.
     * @since Android 1.0
     */
    public int getActualMinimum(int field) {
        int value, next;
        if (getMinimum(field) == (next = getGreatestMinimum(field))) {
            return next;
        }
        complete();
        long orgTime = time;
        set(field, next);
        do {
            value = next;
            roll(field, false);
            next = get(field);
        } while (next < value);
        time = orgTime;
        areFieldsSet = false;
        return value;
    }

    /**
     * Gets the list of installed {@code Locale}s which support {@code Calendar}.
     * 
     * @return an array of {@code Locale}.
     * @since Android 1.0
     */
    public static synchronized Locale[] getAvailableLocales() {
        return Locale.getAvailableLocales();
    }

    /**
     * Gets the first day of the week for this {@code Calendar}.
     * 
     * @return the first day of the week.
     * @since Android 1.0
     */
    public int getFirstDayOfWeek() {
        return firstDayOfWeek;
    }

    /**
     * Gets the greatest minimum value of the specified field. This is the
     * biggest value that {@code getActualMinimum} can return for any possible
     * time.
     * 
     * @param field
     *            the field.
     * @return the greatest minimum value of the specified field.
     * @since Android 1.0
     */
    abstract public int getGreatestMinimum(int field);

    /**
     * Constructs a new instance of the {@code Calendar} subclass appropriate for the
     * default {@code Locale}.
     * 
     * @return a {@code Calendar} subclass instance set to the current date and time in
     *         the default {@code Timezone}.
     * @since Android 1.0
     */
    public static synchronized Calendar getInstance() {
        return new GregorianCalendar();
    }

    /**
     * Constructs a new instance of the {@code Calendar} subclass appropriate for the
     * specified {@code Locale}.
     * 
     * @param locale
     *            the locale to use.
     * @return a {@code Calendar} subclass instance set to the current date and time.
     * @since Android 1.0
     */
    public static synchronized Calendar getInstance(Locale locale) {
        return new GregorianCalendar(locale);
    }

    /**
     * Constructs a new instance of the {@code Calendar} subclass appropriate for the
     * default {@code Locale}, using the specified {@code TimeZone}.
     * 
     * @param timezone
     *            the {@code TimeZone} to use.
     * @return a {@code Calendar} subclass instance set to the current date and time in
     *         the specified timezone.
     * @since Android 1.0
     */
    public static synchronized Calendar getInstance(TimeZone timezone) {
        return new GregorianCalendar(timezone);
    }

    /**
     * Constructs a new instance of the {@code Calendar} subclass appropriate for the
     * specified {@code Locale}.
     * 
     * @param timezone
     *            the {@code TimeZone} to use.
     * @param locale
     *            the {@code Locale} to use.
     * @return a {@code Calendar} subclass instance set to the current date and time in
     *         the specified timezone.
     * @since Android 1.0
     */
    public static synchronized Calendar getInstance(TimeZone timezone,
            Locale locale) {
        return new GregorianCalendar(timezone, locale);
    }

    /**
     * Gets the smallest maximum value of the specified field. This is the
     * smallest value that {@code getActualMaximum()} can return for any
     * possible time.
     * 
     * @param field
     *            the field number.
     * @return the smallest maximum value of the specified field.
     * @since Android 1.0
     */
    abstract public int getLeastMaximum(int field);

    /**
     * Gets the greatest maximum value of the specified field. This returns the
     * biggest value that {@code get} can return for the specified field.
     * 
     * @param field
     *            the field.
     * @return the greatest maximum value of the specified field.
     * @since Android 1.0
     */
    abstract public int getMaximum(int field);

    /**
     * Gets the minimal days in the first week of the year.
     * 
     * @return the minimal days in the first week of the year.
     * @since Android 1.0
     */
    public int getMinimalDaysInFirstWeek() {
        return minimalDaysInFirstWeek;
    }

    /**
     * Gets the smallest minimum value of the specified field. this returns the
     * smallest value thet {@code get} can return for the specified field.
     * 
     * @param field
     *            the field number.
     * @return the smallest minimum value of the specified field.
     * @since Android 1.0
     */
    abstract public int getMinimum(int field);

    /**
     * Gets the time of this {@code Calendar} as a {@code Date} object.
     * 
     * @return a new {@code Date} initialized to the time of this {@code Calendar}.
     * 
     * @exception IllegalArgumentException
     *                when the time is not set and the time cannot be computed
     *                from the current field values.
     * @since Android 1.0
     */
    public final Date getTime() {
        return new Date(getTimeInMillis());
    }

    /**
     * Computes the time from the fields if required and returns the time.
     * 
     * @return the time of this {@code Calendar}.
     * 
     * @exception IllegalArgumentException
     *                when the time is not set and the time cannot be computed
     *                from the current field values.
     * @since Android 1.0
     */
    public long getTimeInMillis() {
        if (!isTimeSet) {
            computeTime();
            isTimeSet = true;
        }
        return time;
    }

    /**
     * Gets the timezone of this {@code Calendar}.
     * 
     * @return the {@code TimeZone} used by this {@code Calendar}.
     * @since Android 1.0
     */
    public TimeZone getTimeZone() {
        return zone;
    }

    /**
     * Returns an integer hash code for the receiver. Objects which are equal
     * return the same value for this method.
     * 
     * @return the receiver's hash.
     * 
     * @see #equals
     * @since Android 1.0
     */
    @Override
    public int hashCode() {
        return (isLenient() ? 1237 : 1231) + getFirstDayOfWeek()
                + getMinimalDaysInFirstWeek() + getTimeZone().hashCode();
    }

    /**
     * Gets the value of the specified field without recomputing.
     * 
     * @param field
     *            the field.
     * @return the value of the specified field.
     * @since Android 1.0
     */
    protected final int internalGet(int field) {
        return fields[field];
    }

    /**
     * Returns if this {@code Calendar} accepts field values which are outside the valid
     * range for the field.
     * 
     * @return {@code true} if this {@code Calendar} is lenient, {@code false} otherwise.
     * @since Android 1.0
     */
    public boolean isLenient() {
        return lenient;
    }

    /**
     * Returns whether the specified field is set.
     * 
     * @param field
     *            a {@code Calendar} field number.
     * @return {@code true} if the specified field is set, {@code false} otherwise.
     * @since Android 1.0
     */
    public final boolean isSet(int field) {
        return isSet[field];
    }

    /**
     * Adds the specified amount to the specified field and wraps the value of
     * the field when it goes beyond the maximum or minimum value for the
     * current date. Other fields will be adjusted as required to maintain a
     * consistent date.
     * 
     * @param field
     *            the field to roll.
     * @param value
     *            the amount to add.
     * @since Android 1.0
     */
    public void roll(int field, int value) {
        boolean increment = value >= 0;
        int count = increment ? value : -value;
        for (int i = 0; i < count; i++) {
            roll(field, increment);
        }
    }

    /**
     * Increment or decrement the specified field and wrap the value of the
     * field when it goes beyond the maximum or minimum value for the current
     * date. Other fields will be adjusted as required to maintain a consistent
     * date.
     * 
     * @param field
     *            the number indicating the field to roll.
     * @param increment
     *            {@code true} to increment the field, {@code false} to decrement.
     * @since Android 1.0
     */
    abstract public void roll(int field, boolean increment);

    /**
     * Sets a field to the specified value.
     * 
     * @param field
     *            the code indicating the {@code Calendar} field to modify.
     * @param value
     *            the value.
     * @since Android 1.0
     */
    public void set(int field, int value) {
        fields[field] = value;
        isSet[field] = true;
        areFieldsSet = isTimeSet = false;
        if (field > MONTH && field < AM_PM) {
            lastDateFieldSet = field;
        }
        if (field == HOUR || field == HOUR_OF_DAY) {
            lastTimeFieldSet = field;
        }
        if (field == AM_PM) {
            lastTimeFieldSet = HOUR;
        }
    }

    /**
     * Sets the year, month and day of the month fields. Other fields are not
     * changed.
     * 
     * @param year
     *            the year.
     * @param month
     *            the month.
     * @param day
     *            the day of the month.
     * @since Android 1.0
     */
    public final void set(int year, int month, int day) {
        set(YEAR, year);
        set(MONTH, month);
        set(DATE, day);
    }

    /**
     * Sets the year, month, day of the month, hour of day and minute fields.
     * Other fields are not changed.
     * 
     * @param year
     *            the year.
     * @param month
     *            the month.
     * @param day
     *            the day of the month.
     * @param hourOfDay
     *            the hour of day.
     * @param minute
     *            the minute.
     * @since Android 1.0
     */
    public final void set(int year, int month, int day, int hourOfDay,
            int minute) {
        set(year, month, day);
        set(HOUR_OF_DAY, hourOfDay);
        set(MINUTE, minute);
    }

    /**
     * Sets the year, month, day of the month, hour of day, minute and second
     * fields. Other fields are not changed.
     * 
     * @param year
     *            the year.
     * @param month
     *            the month.
     * @param day
     *            the day of the month.
     * @param hourOfDay
     *            the hour of day.
     * @param minute
     *            the minute.
     * @param second
     *            the second.
     * @since Android 1.0
     */
    public final void set(int year, int month, int day, int hourOfDay,
            int minute, int second) {
        set(year, month, day, hourOfDay, minute);
        set(SECOND, second);
    }

    /**
     * Sets the first day of the week for this {@code Calendar}.
     * 
     * @param value
     *            a {@code Calendar} day of the week.
     * @since Android 1.0
     */
    public void setFirstDayOfWeek(int value) {
        firstDayOfWeek = value;
    }

    /**
     * Sets this {@code Calendar} to accept field values which are outside the valid
     * range for the field.
     * 
     * @param value
     *            a boolean value.
     * @since Android 1.0
     */
    public void setLenient(boolean value) {
        lenient = value;
    }

    /**
     * Sets the minimal days in the first week of the year.
     * 
     * @param value
     *            the minimal days in the first week of the year.
     * @since Android 1.0
     */
    public void setMinimalDaysInFirstWeek(int value) {
        minimalDaysInFirstWeek = value;
    }

    /**
     * Sets the time of this {@code Calendar}.
     * 
     * @param date
     *            a {@code Date} object.
     * @since Android 1.0
     */
    public final void setTime(Date date) {
        setTimeInMillis(date.getTime());
    }

    /**
     * Sets the time of this {@code Calendar}.
     * 
     * @param milliseconds
     *            the time as the number of milliseconds since Jan. 1, 1970.
     * @since Android 1.0
     */
    public void setTimeInMillis(long milliseconds) {
        time = milliseconds;
        isTimeSet = true;
        areFieldsSet = false;
        complete();
    }

    /**
     * Sets the {@code TimeZone} used by this Calendar.
     * 
     * @param timezone
     *            a {@code TimeZone}.
     * @since Android 1.0
     */
    public void setTimeZone(TimeZone timezone) {
        zone = timezone;
    }

    /**
     * Returns the string representation of this {@code Calendar}.
     * 
     * @return the string representation of this {@code Calendar}.
     * @since Android 1.0
     */
    @Override
    public String toString() {
        StringBuffer result = new StringBuffer(getClass().getName() + "[time=" //$NON-NLS-1$
                + (isTimeSet ? String.valueOf(time) : "?") + ",areFieldsSet="  //$NON-NLS-1$//$NON-NLS-2$
                + areFieldsSet +
                // ",areAllFieldsSet=" + areAllFieldsSet +
                ",lenient=" + lenient + ",zone=" + zone + ",firstDayOfWeek=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                + firstDayOfWeek + ",minimalDaysInFirstWeek=" //$NON-NLS-1$
                + minimalDaysInFirstWeek);
        for (int i = 0; i < FIELD_COUNT; i++) {
            result.append(',');
            result.append(fieldNames[i]);
            result.append('=');
            if (isSet[i]) {
                result.append(fields[i]);
            } else {
                result.append('?');
            }
        }
        result.append(']');
        return result.toString();
    }

    /**
     * Compares the times of the two {@code Calendar}, which represent the milliseconds
     * from the January 1, 1970 00:00:00.000 GMT (Gregorian).
     * 
     * @param anotherCalendar
     *            another calendar that this one is compared with.
     * @return 0 if the times of the two {@code Calendar}s are equal, -1 if the time of
     *         this {@code Calendar} is before the other one, 1 if the time of this
     *         {@code Calendar} is after the other one.
     * @throws NullPointerException
     *             if the argument is null.
     * @throws IllegalArgumentException
     *             if the argument does not include a valid time
     *             value.
     * @since Android 1.0
     */
    public int compareTo(Calendar anotherCalendar) {
        if (null == anotherCalendar) {
            throw new NullPointerException();
        }
        long timeInMillis = getTimeInMillis();
        long anotherTimeInMillis = anotherCalendar.getTimeInMillis();
        if (timeInMillis > anotherTimeInMillis) {
            return 1;
        }
        if (timeInMillis == anotherTimeInMillis) {
            return 0;
        }
        return -1;
    }

    private static final ObjectStreamField[] serialPersistentFields = {
            new ObjectStreamField("areFieldsSet", Boolean.TYPE), //$NON-NLS-1$
            new ObjectStreamField("fields", int[].class), //$NON-NLS-1$
            new ObjectStreamField("firstDayOfWeek", Integer.TYPE), //$NON-NLS-1$
            new ObjectStreamField("isSet", boolean[].class), //$NON-NLS-1$
            new ObjectStreamField("isTimeSet", Boolean.TYPE), //$NON-NLS-1$
            new ObjectStreamField("lenient", Boolean.TYPE), //$NON-NLS-1$
            new ObjectStreamField("minimalDaysInFirstWeek", Integer.TYPE), //$NON-NLS-1$
            new ObjectStreamField("nextStamp", Integer.TYPE), //$NON-NLS-1$
            new ObjectStreamField("serialVersionOnStream", Integer.TYPE), //$NON-NLS-1$
            new ObjectStreamField("time", Long.TYPE), //$NON-NLS-1$
            new ObjectStreamField("zone", TimeZone.class), }; //$NON-NLS-1$

    private void writeObject(ObjectOutputStream stream) throws IOException {
        complete();
        ObjectOutputStream.PutField putFields = stream.putFields();
        putFields.put("areFieldsSet", areFieldsSet); //$NON-NLS-1$
        putFields.put("fields", this.fields); //$NON-NLS-1$
        putFields.put("firstDayOfWeek", firstDayOfWeek); //$NON-NLS-1$
        putFields.put("isSet", isSet); //$NON-NLS-1$
        putFields.put("isTimeSet", isTimeSet); //$NON-NLS-1$
        putFields.put("lenient", lenient); //$NON-NLS-1$
        putFields.put("minimalDaysInFirstWeek", minimalDaysInFirstWeek); //$NON-NLS-1$
        putFields.put("nextStamp", 2 /* MINIMUM_USER_STAMP */); //$NON-NLS-1$
        putFields.put("serialVersionOnStream", 1); //$NON-NLS-1$
        putFields.put("time", time); //$NON-NLS-1$
        putFields.put("zone", zone); //$NON-NLS-1$
        stream.writeFields();
    }

    private void readObject(ObjectInputStream stream) throws IOException,
            ClassNotFoundException {
        ObjectInputStream.GetField readFields = stream.readFields();
        areFieldsSet = readFields.get("areFieldsSet", false); //$NON-NLS-1$
        this.fields = (int[]) readFields.get("fields", null); //$NON-NLS-1$
        firstDayOfWeek = readFields.get("firstDayOfWeek", Calendar.SUNDAY); //$NON-NLS-1$
        isSet = (boolean[]) readFields.get("isSet", null); //$NON-NLS-1$
        isTimeSet = readFields.get("isTimeSet", false); //$NON-NLS-1$
        lenient = readFields.get("lenient", true); //$NON-NLS-1$
        minimalDaysInFirstWeek = readFields.get("minimalDaysInFirstWeek", 1); //$NON-NLS-1$
        time = readFields.get("time", 0L); //$NON-NLS-1$
        zone = (TimeZone) readFields.get("zone", null); //$NON-NLS-1$
    }
}
