/*
 
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
 
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
*
 
* This code is free software; you can redistribute it and/or modify it
 
* under the terms of the GNU General Public License version 2 only, as
 
* published by the Free Software Foundation.
  
Oracle designates this
 
* particular file as subject to the "Classpath" exception as provided
 
* by Oracle in the LICENSE file that accompanied this code.
 
*
 
* This code is distributed in the hope that it will be useful, but WITHOUT
 
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
* FITNESS FOR A PARTICULAR PURPOSE.
  
See the GNU General Public License
 
* version 2 for more details (a copy is included in the LICENSE file that
 
* accompanied this code).
 
*
 
* You should have received a copy of the GNU General Public License version
 
* 2 along with this work; if not, write to the Free Software Foundation,
 
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 
*
 
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 
* or visit www.oracle.com if you need additional information or have any
 
* questions.
 
*/

/*
 
* (C) Copyright Taligent, Inc. 1996-1998 - All Rights Reserved
 
* (C) Copyright IBM Corp. 1996-1998 - All Rights Reserved
 
*
 
*
   
The original version of this source code and documentation is copyrighted
 
* and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
 
* materials are provided under terms of a License Agreement between Taligent
 
* and Sun. This technology is protected by multiple US and International
 
* patents. This notice and attribution to Taligent may not be removed.
 
*
   
Taligent is a registered trademark of Taligent, Inc.
 
*
 
*/


package java.util;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PermissionCollection;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.time.Instant;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import sun.util.BuddhistCalendar;
import sun.util.calendar.ZoneInfo;
import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.spi.CalendarProvider;

/**
 
* The <code>Calendar</code> class is an abstract class that provides methods
 
* for converting between a specific instant in time and a set of {@link
 
* #fields calendar fields} such as <code>YEAR</code>, <code>MONTH</code>,
 
* <code>DAY_OF_MONTH</code>, <code>HOUR</code>, and so on, and for
 
* manipulating the calendar fields, such as getting the date of the next
 
* week. An instant in time can be represented by a millisecond value that is
 
* an offset from the <a name="Epoch"><em>Epoch</em></a>, January 1, 1970
 
* 00:00:00.000 GMT (Gregorian).
 
*
 
* <p>The class also provides additional fields and methods for
 
* implementing a concrete calendar system outside the package. Those
 
* fields and methods are defined as <code>protected</code>.
 
*
 
* <p>
 
* Like other locale-sensitive classes, <code>Calendar</code> provides a
 
* class method, <code>getInstance</code>, for getting a generally useful
 
* object of this type. <code>Calendar</code>'s <code>getInstance</code> method
 
* returns a <code>Calendar</code> object whose
 
* calendar fields have been initialized with the current date and time:
 
* <blockquote>
 
* <pre>
 
*
     
Calendar rightNow = Calendar.getInstance();
 
* </pre>
 
* </blockquote>
 
*
 
* <p>A <code>Calendar</code> object can produce all the calendar field values
 
* needed to implement the date-time formatting for a particular language and
 
* calendar style (for example, Japanese-Gregorian, Japanese-Traditional).
 
* <code>Calendar</code> defines the range of values returned by
 
* certain calendar fields, as well as their meaning.
  
For example,
 
* the first month of the calendar system has value <code>MONTH ==
 
* JANUARY</code> for all calendars.
  
Other values are defined by the
 
* concrete subclass, such as <code>ERA</code>.
  
See individual field
 
* documentation and subclass documentation for details.
 
*
 
* <h3>Getting and Setting Calendar Field Values</h3>
 
*
 
* <p>The calendar field values can be set by calling the <code>set</code>
 
* methods. Any field values set in a <code>Calendar</code> will not be
 
* interpreted until it needs to calculate its time value (milliseconds from
 
* the Epoch) or values of the calendar fields. Calling the
 
* <code>get</code>, <code>getTimeInMillis</code>, <code>getTime</code>,
 
* <code>add</code> and <code>roll</code> involves such calculation.
 
*
 
* <h4>Leniency</h4>
 
*
 
* <p><code>Calendar</code> has two modes for interpreting the calendar
 
* fields, <em>lenient</em> and <em>non-lenient</em>.
  
When a
 
* <code>Calendar</code> is in lenient mode, it accepts a wider range of
 
* calendar field values than it produces.
  
When a <code>Calendar</code>
 
* recomputes calendar field values for return by <code>get()</code>, all of
 
* the calendar fields are normalized. For example, a lenient
 
* <code>GregorianCalendar</code> interprets <code>MONTH == JANUARY</code>,
 
* <code>DAY_OF_MONTH == 32</code> as February 1.

 
* <p>When a <code>Calendar</code> is in non-lenient mode, it throws an
 
* exception if there is any inconsistency in its calendar fields. For
 
* example, a <code>GregorianCalendar</code> always produces
 
* <code>DAY_OF_MONTH</code> values between 1 and the length of the month. A
 
* non-lenient <code>GregorianCalendar</code> throws an exception upon
 
* calculating its time or calendar field values if any out-of-range field
 
* value has been set.
 
*
 
* <h4><a name="first_week">First Week</a></h4>
 
*
 
* <code>Calendar</code> 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</code> is constructed.
  
They may also be specified explicitly
 
* through the methods for setting their values.
 
*
 
* <p>When setting or getting the <code>WEEK_OF_MONTH</code> or
 
* <code>WEEK_OF_YEAR</code> fields, <code>Calendar</code> 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()</code> and containing at least
 
* <code>getMinimalDaysInFirstWeek()</code> 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()</code> may be
 
* different.
  
For example, a specific <code>Calendar</code> subclass may
 
* designate the week before week 1 of a year as week <code><i>n</i></code> of
 
* the previous year.
 
*
 
* <h4>Calendar Fields Resolution</h4>
 
*
 
* When computing a date and time from the calendar fields, there
 
* may be insufficient information for the computation (such as only
 
* year and month with no day of month), or there may be inconsistent
 
* information (such as Tuesday, July 15, 1996 (Gregorian) -- July 15,
 
* 1996 is actually a Monday). <code>Calendar</code> will resolve
 
* calendar field values to determine the date and time in the
 
* following way.
 
*
 
* <p><a name="resolution">If there is any conflict in calendar field values,
 
* <code>Calendar</code> gives priorities to calendar fields that have been set
 
* more recently.</a> The following are the default combinations of the
 
* calendar fields. The most recent combination, as determined by the
 
* most recently set single field, will be used.
 
*
 
* <p><a name="date_resolution">For the date fields</a>:
 
* <blockquote>
 
* <pre>
 
* YEAR + MONTH + DAY_OF_MONTH
 
* YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
 
* YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
 
* YEAR + DAY_OF_YEAR
 
* YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
 
* </pre></blockquote>
 
*
 
* <a name="time_resolution">For the time of day fields</a>:
 
* <blockquote>
 
* <pre>
 
* HOUR_OF_DAY
 
* AM_PM + HOUR
 
* </pre></blockquote>
 
*
 
* <p>If there are any calendar fields whose values haven't been set in the selected
 
* field combination, <code>Calendar</code> uses their default values. The default
 
* value of each field may vary by concrete calendar systems. For example, in
 
* <code>GregorianCalendar</code>, the default of a field is the same as that
 
* of the start of the Epoch: i.e., <code>YEAR = 1970</code>, <code>MONTH =
 
* JANUARY</code>, <code>DAY_OF_MONTH = 1</code>, etc.
 
*
 
* <p>
 
* <strong>Note:</strong> There are certain possible ambiguities in
 
* interpretation of certain singular times, which are resolved in the
 
* following ways:
 
* <ol>
 
*
     
<li> 23:59 is the last minute of the day and 00:00 is the first
 
*
          
minute of the next day. Thus, 23:59 on Dec 31, 1999 &lt; 00:00 on
 
*
          
Jan 1, 2000 &lt; 00:01 on Jan 1, 2000.
 
*
 
*
     
<li> Although historically not precise, midnight also belongs to "am",
 
*
          
and noon belongs to "pm", so on the same day,
 
*
          
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 DateFormat}
 
* to format dates.
 
*
 
* <h4>Field Manipulation</h4>
 
*
 
* The calendar fields can be changed using three methods:
 
* <code>set()</code>, <code>add()</code>, and <code>roll()</code>.
 
*
 
* <p><strong><code>set(f, value)</code></strong> changes calendar field
 
* <code>f</code> to <code>value</code>.
  
In addition, it sets an
 
* internal member variable to indicate that calendar field <code>f</code> has
 
* been changed. Although calendar field <code>f</code> is changed immediately,
 
* the calendar's time value in milliseconds is not recomputed until the next call to
 
* <code>get()</code>, <code>getTime()</code>, <code>getTimeInMillis()</code>,
 
* <code>add()</code>, or <code>roll()</code> is made. Thus, multiple calls to
 
* <code>set()</code> do not trigger multiple, unnecessary
 
* computations. As a result of changing a calendar field using
 
* <code>set()</code>, other calendar fields may also change, depending on the
 
* calendar field, the calendar field value, and the calendar system. In addition,
 
* <code>get(f)</code> will not necessarily return <code>value</code> set by
 
* the call to the <code>set</code> method
 
* after the calendar fields have been recomputed. The specifics are determined by
 
* the concrete calendar class.</p>
 
*
 
* <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
 
* originally set to August 31, 1999. Calling <code>set(Calendar.MONTH,
 
* Calendar.SEPTEMBER)</code> sets the date to September 31,
 
* 1999. This is a temporary internal representation that resolves to
 
* October 1, 1999 if <code>getTime()</code>is then called. However, a
 
* call to <code>set(Calendar.DAY_OF_MONTH, 30)</code> before the call to
 
* <code>getTime()</code> sets the date to September 30, 1999, since
 
* no recomputation occurs after <code>set()</code> itself.</p>
 
*
 
* <p><strong><code>add(f, delta)</code></strong> adds <code>delta</code>
 
* to field <code>f</code>.
  
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</code>
 
*
   
after the call minus the value of field <code>f</code> before the
 
*
   
call is <code>delta</code>, modulo any overflow that has occurred in
 
*
   
field <code>f</code>. 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 it is impossible for it to be equal to its
 
*
   
prior value because of changes in its minimum or maximum after field
 
*
   
<code>f</code> is changed or other constraints, such as time zone
 
*
   
offset changes, 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</code> is a smaller field than
 
*
   
<code>DAY_OF_MONTH</code>. 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>, <code>add()</code> forces
 
* an immediate recomputation of the calendar's milliseconds and all
 
* fields.</p>
 
*
 
* <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
 
* originally set to August 31, 1999. Calling <code>add(Calendar.MONTH,
 
* 13)</code> sets the calendar to September 30, 2000. <strong>Add rule
 
* 1</strong> sets the <code>MONTH</code> field to September, since
 
* adding 13 months to August gives September of the next year. Since
 
* <code>DAY_OF_MONTH</code> cannot be 31 in September in a
 
* <code>GregorianCalendar</code>, <strong>add rule 2</strong> sets the
 
* <code>DAY_OF_MONTH</code> to 30, the closest possible value. Although
 
* it is a smaller field, <code>DAY_OF_WEEK</code> is not adjusted by
 
* rule 2, since it is expected to change when the month changes in a
 
* <code>GregorianCalendar</code>.</p>
 
*
 
* <p><strong><code>roll(f, delta)</code></strong> adds
 
* <code>delta</code> to field <code>f</code> without changing larger
 
* fields. This is equivalent to calling <code>add(f, delta)</code> 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</code> is a larger field than
 
*
   
<code>HOUR</code>.</p>
 
* </blockquote>
 
*
 
* <p><em>Example</em>: See {@link java.util.GregorianCalendar#roll(int, int)}.
 
*
 
* <p><strong>Usage model</strong>. To motivate the behavior of
 
* <code>add()</code> and <code>roll()</code>, consider a user interface
 
* component with increment and decrement buttons for the month, day, and
 
* year, and an underlying <code>GregorianCalendar</code>. 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()</code>, 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()</code> or <code>roll()</code>, depending on whether larger
 
* fields should be affected, the user interface can behave as most users
 
* will intuitively expect.</p>
 
*
 
* @see
          
java.lang.System#currentTimeMillis()
 
* @see
          
Date
 
* @see
          
GregorianCalendar
 
* @see
          
TimeZone
 
* @see
          
java.text.DateFormat
 
* @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu
 
* @since JDK1.1
 
*/

public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {

    
// Data flow in Calendar
    
// ---------------------

    
// The current time is represented in two ways by Calendar: as UTC
    
// milliseconds from the epoch (1 January 1970 0:00 UTC), and as local
    
// fields such as MONTH, HOUR, AM_PM, etc.
  
It is possible to compute the

    
// millis from the fields, and vice versa.
  
The data needed to do this
    
// conversion is encapsulated by a TimeZone object owned by the Calendar.
    
// The data provided by the TimeZone object may also be overridden if the
    
// user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class
    
// keeps track of what information was most recently set by the caller, and
    
// uses that to compute any other information as needed.

    
// If the user sets the fields using set(), the data flow is as follows.
    
// This is implemented by the Calendar subclass's computeTime() method.
    
// During this process, certain fields may be ignored.
  
The disambiguation

    
// algorithm for resolving which fields to pay attention to is described
    
// in the class documentation.

    
//
   
local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)

    
//
           
|
    
//
           
| Using Calendar-specific algorithm
    
//
           
V
    
//
   
local standard millis
    
//
           
|
    
//
           
| Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET

    
//
           
V
    
//
   
UTC millis (in time data member)

    
// If the user sets the UTC millis using setTime() or setTimeInMillis(),
    
// the data flow is as follows.
  
This is implemented by the Calendar
    
// subclass's computeFields() method.

    
//
   
UTC millis (in time data member)
    
//
           
|
    
//
           
| Using TimeZone getOffset()
    
//
           
V
    
//
   
local standard millis
    
//
           
|
    
//
           
| Using Calendar-specific algorithm
    
//
           
V
    
//
   
local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)


    
// In general, a round trip from fields, through local and UTC millis, and
    
// back out to fields is made when necessary.
  
This is implemented by the
    
// complete() method.
  
Resolving a partial set of fields into a UTC millis

    
// value allows all remaining fields to be generated from that value.
  
If

    
// the Calendar is lenient, the fields are also renormalized to standard
    
// ranges when they are regenerated.

    
/**
     
* Field number for <code>get</code> and <code>set</code> 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
     
*/

    
public final static int ERA = 0;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* year. This is a calendar-specific value; see subclass documentation.
     
*/

    
public final static int YEAR = 1;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* month. This is a calendar-specific value. The first month of
     
* the year in the Gregorian and Julian calendars is
     
* <code>JANUARY</code> which is 0; the last depends on the number
     
* of months in a year.
     
*
     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*/

    
public final static int MONTH = 2;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* week number within the current year.
  
The first week of the year, as
     
* defined by <code>getFirstDayOfWeek()</code> and
     
* <code>getMinimalDaysInFirstWeek()</code>, has value 1.
  
Subclasses define
     
* the value of <code>WEEK_OF_YEAR</code> for days before the first week of
     
* the year.
     
*
     
* @see #getFirstDayOfWeek
     
* @see #getMinimalDaysInFirstWeek
     
*/

    
public final static int WEEK_OF_YEAR = 3;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* week number within the current month.
  
The first week of the month, as
     
* defined by <code>getFirstDayOfWeek()</code> and
     
* <code>getMinimalDaysInFirstWeek()</code>, has value 1.
  
Subclasses define
     
* the value of <code>WEEK_OF_MONTH</code> for days before the first week of
     
* the month.
     
*
     
* @see #getFirstDayOfWeek
     
* @see #getMinimalDaysInFirstWeek
     
*/

    
public final static int WEEK_OF_MONTH = 4;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* day of the month. This is a synonym for <code>DAY_OF_MONTH</code>.
     
* The first day of the month has value 1.
     
*
     
*
 

     
*/

    
public final static int DATE = 5;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* day of the month. This is a synonym for <code>DATE</code>.
     
* The first day of the month has value 1.
     
*
     
*
 

     
*/

    
public final static int DAY_OF_MONTH = 5;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the day
     
* number within the current year.
  
The first day of the year has value 1.
     
*/

    
public final static int DAY_OF_YEAR = 6;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the day
     
* of the week.
  
This field takes values <code>SUNDAY</code>,
     
* <code>MONDAY</code>, <code>TUESDAY</code>, <code>WEDNESDAY</code>,
     
* <code>THURSDAY</code>, <code>FRIDAY</code>, and <code>SATURDAY</code>.
     
*
     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*/

    
public final static int DAY_OF_WEEK = 7;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* ordinal number of the day of the week within the current month. Together
     
* with the <code>DAY_OF_WEEK</code> field, this uniquely specifies a day
     
* within a month.
  
Unlike <code>WEEK_OF_MONTH</code> and
     
* <code>WEEK_OF_YEAR</code>, this field's value does <em>not</em> depend on
     
* <code>getFirstDayOfWeek()</code> or
     
* <code>getMinimalDaysInFirstWeek()</code>.
  
<code>DAY_OF_MONTH 1</code>
     
* through <code>7</code> always correspond to <code>DAY_OF_WEEK_IN_MONTH
     
* 1</code>; <code>8</code> through <code>14</code> correspond to
     
* <code>DAY_OF_WEEK_IN_MONTH 2</code>, and so on.
     
* <code>DAY_OF_WEEK_IN_MONTH 0</code> indicates the week before
     
* <code>DAY_OF_WEEK_IN_MONTH 1</code>.
  
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</code>.
  
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</code> will overlap
     
* <code>DAY_OF_WEEK_IN_MONTH 5</code> and the end of <code>4</code>.
     
*
     
*
 

     
*
 

     
*/

    
public final static int DAY_OF_WEEK_IN_MONTH = 8;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating
     
* whether the <code>HOUR</code> is before or after noon.
     
* E.g., at 10:04:15.250 PM the <code>AM_PM</code> is <code>PM</code>.
     
*
     
*
 

     
*
 

     
*
 

     
*/

    
public final static int AM_PM = 9;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* hour of the morning or afternoon. <code>HOUR</code> is used for the
     
* 12-hour clock (0 - 11). Noon and midnight are represented by 0, not by 12.
     
* E.g., at 10:04:15.250 PM the <code>HOUR</code> is 10.
     
*
     
*
 

     
*
 

     
*/

    
public final static int HOUR = 10;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* hour of the day. <code>HOUR_OF_DAY</code> is used for the 24-hour clock.
     
* E.g., at 10:04:15.250 PM the <code>HOUR_OF_DAY</code> is 22.
     
*
     
*
 

     
*/

    
public final static int HOUR_OF_DAY = 11;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* minute within the hour.
     
* E.g., at 10:04:15.250 PM the <code>MINUTE</code> is 4.
     
*/

    
public final static int MINUTE = 12;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* second within the minute.
     
* E.g., at 10:04:15.250 PM the <code>SECOND</code> is 15.
     
*/

    
public final static int SECOND = 13;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* millisecond within the second.
     
* E.g., at 10:04:15.250 PM the <code>MILLISECOND</code> is 250.
     
*/

    
public final static int MILLISECOND = 14;

    
/**
     
* Field number for <code>get</code> and <code>set</code>
     
* indicating the raw offset from GMT in milliseconds.
     
* <p>
     
* This field reflects the correct GMT offset value of the time
     
* zone of this <code>Calendar</code> if the
     
* <code>TimeZone</code> implementation subclass supports
     
* historical GMT offset changes.
     
*/

    
public final static int ZONE_OFFSET = 15;

    
/**
     
* Field number for <code>get</code> and <code>set</code> indicating the
     
* daylight saving offset in milliseconds.
     
* <p>
     
* This field reflects the correct daylight saving offset value of
     
* the time zone of this <code>Calendar</code> if the
     
* <code>TimeZone</code> implementation subclass supports
     
* historical Daylight Saving Time schedule changes.
     
*/

    
public final static int DST_OFFSET = 16;

    
/**
     
* The number of distinct fields recognized by <code>get</code> and <code>set</code>.
     
* Field numbers range from <code>0..FIELD_COUNT-1</code>.
     
*/

    
public final static int FIELD_COUNT = 17;

    
/**
     
* Value of the
 
 
field indicating
     
* Sunday.
     
*/

    
public final static int SUNDAY = 1;

    
/**
     
* Value of the
 
 
field indicating
     
* Monday.
     
*/

    
public final static int MONDAY = 2;

    
/**
     
* Value of the
 
 
field indicating
     
* Tuesday.
     
*/

    
public final static int TUESDAY = 3;

    
/**
     
* Value of the
 
 
field indicating
     
* Wednesday.
     
*/

    
public final static int WEDNESDAY = 4;

    
/**
     
* Value of the
 
 
field indicating
     
* Thursday.
     
*/

    
public final static int THURSDAY = 5;

    
/**
     
* Value of the
 
 
field indicating
     
* Friday.
     
*/

    
public final static int FRIDAY = 6;

    
/**
     
* Value of the
 
 
field indicating
     
* Saturday.
     
*/

    
public final static int SATURDAY = 7;

    
/**
     
* Value of the
 
 
field indicating the
     
* first month of the year in the Gregorian and Julian calendars.
     
*/

    
public final static int JANUARY = 0;

    
/**
     
* Value of the
 
 
field indicating the
     
* second month of the year in the Gregorian and Julian calendars.
     
*/

    
public final static int FEBRUARY = 1;

    
/**
     
* Value of the
 
 
field indicating the
     
* third month of the year in the Gregorian and Julian calendars.
     
*/

    
public final static int MARCH = 2;

    
/**
     
* Value of the
 
 
field indicating the
     
* fourth month of the year in the Gregorian and Julian calendars.
     
*/

    
public final static int APRIL = 3;

    
/**
     
* Value of the
 
 
field indicating the
     
* fifth month of the year in the Gregorian and Julian calendars.
     
*/

    
public final static int MAY = 4;

    
/**
     
* Value of the
 
 
field indicating the
     
* sixth month of the year in the Gregorian and Julian calendars.
     
*/

    
public final static int JUNE = 5;

    
/**
     
* Value of the
 
 
field indicating the
     
* seventh month of the year in the Gregorian and Julian calendars.
     
*/

    
public final static int JULY = 6;

    
/**
     
* Value of the
 
 
field indicating the
     
* eighth month of the year in the Gregorian and Julian calendars.
     
*/

    
public final static int AUGUST = 7;

    
/**
     
* Value of the
 
 
field indicating the
     
* ninth month of the year in the Gregorian and Julian calendars.
     
*/

    
public final static int SEPTEMBER = 8;

    
/**
     
* Value of the
 
 
field indicating the
     
* tenth month of the year in the Gregorian and Julian calendars.
     
*/

    
public final static int OCTOBER = 9;

    
/**
     
* Value of the
 
 
field indicating the
     
* eleventh month of the year in the Gregorian and Julian calendars.
     
*/

    
public final static int NOVEMBER = 10;

    
/**
     
* Value of the
 
 
field indicating the
     
* twelfth month of the year in the Gregorian and Julian calendars.
     
*/

    
public final static int DECEMBER = 11;

    
/**
     
* Value of the
 
 
field indicating the
     
* thirteenth month of the year. Although <code>GregorianCalendar</code>
     
* does not use this value, lunar calendars do.
     
*/

    
public final static int UNDECIMBER = 12;

    
/**
     
* Value of the
 
 
field indicating the
     
* period of the day from midnight to just before noon.
     
*/

    
public final static int AM = 0;

    
/**
     
* Value of the
 
 
field indicating the
     
* period of the day from noon to just before midnight.
     
*/

    
public final static int PM = 1;

    
/**
     
* A style specifier for {@link #getDisplayNames(int, int, Locale)
     
* getDisplayNames} indicating names in all styles, such as
     
* "January" and "Jan".
     
*
     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
*
 

     
* @since 1.6
     
*/

    
public static final int ALL_STYLES = 0;

    
static final int STANDALONE_MASK = 0x8000;

    
/**
     
* A style specifier for {@link #getDisplayName(int, int, Locale)
     
* getDisplayName} and {@link #getDisplayNames(int, int, Locale)
     
* getDisplayNames} equivalent to
 
.
     
*
     
*
 

     
*
 

     
* @since 1.6
     
*/

    
public static final int SHORT = 1;

    
/**
     
* A style specifier for {@link #getDisplayName(int, int, Locale)
     
* getDisplayName} and {@link #getDisplayNames(int, int, Locale)
     
* getDisplayNames} equivalent to
 
.
     
*
     
*
 

     
*
 

     
* @since 1.6
     
*/

    
public static final int LONG = 2;

    
/**
     
* A style specifier for {@link #getDisplayName(int, int, Locale)
     
* getDisplayName} and {@link #getDisplayNames(int, int, Locale)
     
* getDisplayNames} indicating a narrow name used for format. Narrow names
     
* are typically single character strings, such as "M" for Monday.
     
*
     
*
 

     
*
 

     
*
 

     
* @since 1.8
     
*/

    
public static final int NARROW_FORMAT = 4;

    
/**
     
* A style specifier for {@link #getDisplayName(int, int, Locale)
     
* getDisplayName} and {@link #getDisplayNames(int, int, Locale)
     
* getDisplayNames} indicating a narrow name independently. Narrow names
     
* are typically single character strings, such as "M" for Monday.
     
*
     
*
 

     
*
 

     
*
 

     
* @since 1.8
     
*/

    
public static final int NARROW_STANDALONE = NARROW_FORMAT | STANDALONE_MASK;

    
/**
     
* A style specifier for {@link #getDisplayName(int, int, Locale)
     
* getDisplayName} and {@link #getDisplayNames(int, int, Locale)
     
* getDisplayNames} indicating a short name used for format.
     
*
     
*
 

     
*
 

     
*
 

     
* @since 1.8
     
*/

    
public static final int SHORT_FORMAT = 1;

    
/**
     
* A style specifier for {@link #getDisplayName(int, int, Locale)
     
* getDisplayName} and {@link #getDisplayNames(int, int, Locale)
     
* getDisplayNames} indicating a long name used for format.
     
*
     
*
 

     
*
 

     
*
 

     
* @since 1.8
     
*/

    
public static final int LONG_FORMAT = 2;

    
/**
     
* A style specifier for {@link #getDisplayName(int, int, Locale)
     
* getDisplayName} and {@link #getDisplayNames(int, int, Locale)
     
* getDisplayNames} indicating a short name used independently,
     
* such as a month abbreviation as calendar headers.
     
*
     
*
 

     
*
 

     
*
 

     
* @since 1.8
     
*/

    
public static final int SHORT_STANDALONE = SHORT | STANDALONE_MASK;

    
/**
     
* A style specifier for {@link #getDisplayName(int, int, Locale)
     
* getDisplayName} and {@link #getDisplayNames(int, int, Locale)
     
* getDisplayNames} indicating a long name used independently,
     
* such as a month name as calendar headers.
     
*
     
*
 

     
*
 

     
*
 

     
* @since 1.8
     
*/

    
public static final int LONG_STANDALONE = LONG | STANDALONE_MASK;

    
// Internal notes:
    
// Calendar contains two kinds of time representations: current "time" in
    
// milliseconds, and a set of calendar "fields" representing the current time.
    
// The two representations are usually in sync, but can get out of sync
    
// as follows.
    
// 1. Initially, no fields are set, and the time is invalid.
    
// 2. If the time is set, all fields are computed and in sync.
    
// 3. If a single field is set, the time is invalid.
    
// Recomputation of the time and fields happens when the object needs
    
// to return a result to the user, or use a result for a computation.

    
/**
     
* The calendar field values for the currently set time for this calendar.
     
* This is an array of <code>FIELD_COUNT</code> integers, with index values
     
* <code>ERA</code> through <code>DST_OFFSET</code>.
     
* @serial
     
*/

    
@SuppressWarnings("ProtectedField")
    
protected int
           
fields[];

    
/**
     
* The flags which tell if a specified calendar field for the calendar is set.
     
* A new object has no fields set.
  
After the first call to a method
     
* which generates the fields, they all remain set after that.
     
* This is an array of <code>FIELD_COUNT</code> booleans, with index values
     
* <code>ERA</code> through <code>DST_OFFSET</code>.
     
* @serial
     
*/

    
@SuppressWarnings("ProtectedField")
    
protected boolean
       
isSet[];

    
/**
     
* Pseudo-time-stamps which specify when each field was set. There
     
* are two special values, UNSET and COMPUTED. Values from
     
* MINIMUM_USER_SET to Integer.MAX_VALUE are legal user set values.
     
*/

    
transient private int
   
stamp[];

    
/**
     
* The currently set time for this calendar, expressed in milliseconds after
     
* January 1, 1970, 0:00:00 GMT.
     
*
 

     
* @serial
     
*/

    
@SuppressWarnings("ProtectedField")
    
protected long
          
time;

    
/**
     
* True if then the value of <code>time</code> is valid.
     
* The time is made invalid by a change to an item of <code>field[]</code>.
     
*
 

     
* @serial
     
*/

    
@SuppressWarnings("ProtectedField")
    
protected boolean
       
isTimeSet;

    
/**
     
* True if <code>fields[]</code> are in sync with the currently set time.
     
* If false, then the next attempt to get the value of a field will
     
* force a recomputation of all fields from the current value of
     
* <code>time</code>.
     
* @serial
     
*/

    
@SuppressWarnings("ProtectedField")
    
protected boolean
       
areFieldsSet;

    
/**
     
* True if all fields have been set.
     
* @serial
     
*/
    
transient boolean
       
areAllFieldsSet;

    
/**
     
* <code>True</code> if this calendar allows out-of-range field values during computation
     
* of <code>time</code> from <code>fields[]</code>.
     
* @see #setLenient
     
* @see #isLenient
     
* @serial
     
*/

    
private boolean
         
lenient = true;

    
/**
     
* The <code>TimeZone</code> used by this calendar. <code>Calendar</code>
     
* uses the time zone data to translate between locale and GMT time.
     
* @serial
     
*/

    
private TimeZone
        
zone
;

    
/**
     
* <code>True</code> if zone references to a shared TimeZone object.
     
*/

    
transient private boolean sharedZone = false;

    
/**
     
* The first day of the week, with possible values <code>SUNDAY</code>,
     
* <code>MONDAY</code>, etc.
  
This is a locale-dependent value.
     
* @serial
     
*/

    
private int
             
firstDayOfWeek;

    
/**
     
* The number of days required for the first week in a month or year,
     
* with possible values from 1 to 7.
  
This is a locale-dependent value.
     
* @serial
     
*/

    
private int
             
minimalDaysInFirstWeek;

    
/**
     
* Cache to hold the firstDayOfWeek and minimalDaysInFirstWeek
     
* of a Locale.
     
*/
    
private static final ConcurrentMap<Locale, int[]> cachedLocaleData
        
= new ConcurrentHashMap<>(3);

    
// Special values of stamp[]
    
/**
     
* The corresponding fields[] has no value.
     
*/
    
private static final int
        
UNSET = 0;

    
/**
     
* The value of the corresponding fields[] has been calculated internally.
     
*/

    
private static final int
        
COMPUTED = 1;

    
/**
     
* The value of the corresponding fields[] has been set externally. Stamp
     
* values which are greater than 1 represents the (pseudo) time when the
     
* corresponding fields[] value was set.
     
*/

    
private static final int
        
MINIMUM_USER_STAMP = 2;

    
/**
     
* The mask value that represents all of the fields.
     
*/
    
static final int ALL_FIELDS = (1 << FIELD_COUNT) - 1;

    
/**
     
* The next available value for <code>stamp[]</code>, an internal array.
     
* This actually should not be written out to the stream, and will probably
     
* be removed from the stream in the near future.
  
In the meantime,
     
* a value of <code>MINIMUM_USER_STAMP</code> should be used.
     
* @serial
     
*/

    
private int
             
nextStamp = MINIMUM_USER_STAMP;

    
// the internal serial version which says which version was written
    
// - 0 (default) for version up to JDK 1.1.5
    
// - 1 for version from JDK 1.1.6, which writes a correct 'time' value
    
//
     
as well as compatible values for other fields.
  
This is a
    
//
     
transitional format.
    
// - 2 (not implemented yet) a future version, in which fields[],
    
//
     
areFieldsSet, and isTimeSet become transient, and isSet[] is

    
//
     
removed. In JDK 1.1.6 we write a format compatible with version 2.

    
static final int
        
currentSerialVersion = 1;

    
/**
     
* The version of the serialized data on the stream.
  
Possible values:
     
* <dl>
     
* <dt><b>0</b> or not present on stream</dt>
     
* <dd>
     
* JDK 1.1.5 or earlier.
     
* </dd>
     
* <dt><b>1</b></dt>
     
* <dd>
     
* JDK 1.1.6 or later.
  
Writes a correct 'time' value
     
* as well as compatible values for other fields.
  
This is a
     
* transitional format.
     
* </dd>
     
* </dl>
     
* When streaming out this class, the most recent format
     
* and the highest allowable <code>serialVersionOnStream</code>
     
* is written.
     
* @serial
     
* @since JDK1.1.6
     
*/

    
private int
             
serialVersionOnStream = currentSerialVersion;

    
// Proclaim serialization compatibility with JDK 1.1
    
static final long
       
serialVersionUID = -1807547505821590642L;

    
// Mask values for calendar fields
    
@SuppressWarnings("PointlessBitwiseExpression")
    
final static int ERA_MASK
           
= (1 << ERA);
    
final static int YEAR_MASK
          
= (1 << YEAR);
    
final static int MONTH_MASK
         
= (1 << MONTH);
    
final static int WEEK_OF_YEAR_MASK
  
= (1 << WEEK_OF_YEAR);
    
final static int WEEK_OF_MONTH_MASK = (1 << WEEK_OF_MONTH);
    
final static int DAY_OF_MONTH_MASK
  
= (1 << DAY_OF_MONTH);
    
final static int DATE_MASK
          
= DAY_OF_MONTH_MASK;
    
final static int DAY_OF_YEAR_MASK
   
= (1 << DAY_OF_YEAR);
    
final static int DAY_OF_WEEK_MASK
   
= (1 << DAY_OF_WEEK);
    
final static int DAY_OF_WEEK_IN_MONTH_MASK
  
= (1 << DAY_OF_WEEK_IN_MONTH);
    
final static int AM_PM_MASK
         
= (1 << AM_PM);
    
final static int HOUR_MASK
          
= (1 << HOUR);
    
final static int HOUR_OF_DAY_MASK
   
= (1 << HOUR_OF_DAY);
    
final static int MINUTE_MASK
        
= (1 << MINUTE);
    
final static int SECOND_MASK
        
= (1 << SECOND);
    
final static int MILLISECOND_MASK
   
= (1 << MILLISECOND);
    
final static int ZONE_OFFSET_MASK
   
= (1 << ZONE_OFFSET);
    
final static int DST_OFFSET_MASK
    
= (1 << DST_OFFSET);

    
/**
     
* {@code Calendar.Builder} is used for creating a {@code Calendar} from
     
* various date-time parameters.
     
*
     
* <p>There are two ways to set a {@code Calendar} to a date-time value. One
     
* is to set the instant parameter to a millisecond offset from the <a
     
* href="Calendar.html#Epoch">Epoch</a>. The other is to set individual
     
* field parameters, such as {@link Calendar#YEAR YEAR}, to their desired
     
* values. These two ways can't be mixed. Trying to set both the instant and
     
* individual fields will cause an {@link IllegalStateException} to be
     
* thrown. However, it is permitted to override previous values of the
     
* instant or field parameters.
     
*
     
* <p>If no enough field parameters are given for determining date and/or
     
* time, calendar specific default values are used when building a
     
* {@code Calendar}. For example, if the {@link Calendar#YEAR YEAR} value
     
* isn't given for the Gregorian calendar, 1970 will be used. If there are
     
* any conflicts among field parameters, the <a
     
* href="Calendar.html#resolution"> resolution rules</a> are applied.
     
* Therefore, the order of field setting matters.
     
*
     
* <p>In addition to the date-time parameters,
     
* the {@linkplain #setLocale(Locale) locale},
     
* {@linkplain #setTimeZone(TimeZone) time zone},
     
* {@linkplain #setWeekDefinition(int, int) week definition}, and
     
* {@linkplain #setLenient(boolean) leniency mode} parameters can be set.
     
*
     
* <p><b>Examples</b>
     
* <p>The following are sample usages. Sample code assumes that the
     
* {@code Calendar} constants are statically imported.
     
*
     
* <p>The following code produces a {@code Calendar} with date 2012-12-31
     
* (Gregorian) because Monday is the first day of a week with the <a
     
* href="GregorianCalendar.html#iso8601_compatible_setting"> ISO 8601
     
* compatible week parameters</a>.
     
* <pre>
     
*
   
Calendar cal = new Calendar.Builder().setCalendarType("iso8601")
     
*
                        
.setWeekDate(2013, 1, MONDAY).build();</pre>
     
* <p>The following code produces a Japanese {@code Calendar} with date
     
* 1989-01-08 (Gregorian), assuming that the default {@link Calendar#ERA ERA}
     
* is <em>Heisei</em> that started on that day.
     
* <pre>
     
*
   
Calendar cal = new Calendar.Builder().setCalendarType("japanese")
     
*
                        
.setFields(YEAR, 1, DAY_OF_YEAR, 1).build();</pre>
     
*
     
* @since 1.8
     
* @see Calendar#getInstance(TimeZone, Locale)
     
* @see Calendar#fields
     
*/

    
public static class Builder {
        
private static final int NFIELDS = FIELD_COUNT + 1; // +1 for WEEK_YEAR
        
private static final int WEEK_YEAR = FIELD_COUNT;

        
private long instant;
        
// Calendar.stamp[] (lower half) and Calendar.fields[] (upper half) combined
        
private int[] fields;
        
// Pseudo timestamp starting from MINIMUM_USER_STAMP.
        
// (COMPUTED is used to indicate that the instant has been set.)
        
private int nextStamp;
        
// maxFieldIndex keeps the max index of fields which have been set.
        
// (WEEK_YEAR is never included.)
        
private int maxFieldIndex;
        
private String type;
        
private TimeZone zone;
        
private boolean lenient = true;
        
private Locale locale;
        
private int firstDayOfWeek, minimalDaysInFirstWeek;

        
/**
         
* Constructs a {@code Calendar.Builder}.
         
*/
        
public Builder() {
        
}

        
/**
         
* Sets the instant parameter to the given {@code instant} value that is
         
* a millisecond offset from <a href="Calendar.html#Epoch">the
         
* Epoch</a>.
         
*
         
* @param instant a millisecond offset from the Epoch
         
* @return this {@code Calendar.Builder}
         
* @throws IllegalStateException if any of the field parameters have
         
*
                               
already been set
         
* @see Calendar#setTime(Date)
         
* @see Calendar#setTimeInMillis(long)
         
* @see Calendar#time
         
*/

        
public Builder setInstant(long instant) {
            
if (fields != null) {
                
throw new IllegalStateException();
            
}
            
this.instant = instant;
            
nextStamp = COMPUTED;
            
return this;
        
}

        
/**
         
* Sets the instant parameter to the {@code instant} value given by a
         
* {@link Date}. This method is equivalent to a call to
         
* {@link #setInstant(long) setInstant(instant.getTime())}.
         
*
         
* @param instant a {@code Date} representing a millisecond offset from
         
*
                
the Epoch
         
* @return this {@code Calendar.Builder}
         
* @throws NullPointerException
  
if {@code instant} is {@code null}
         
* @throws IllegalStateException if any of the field parameters have
         
*
                               
already been set
         
* @see Calendar#setTime(Date)
         
* @see Calendar#setTimeInMillis(long)
         
* @see Calendar#time
         
*/

        
public Builder setInstant(Date instant) {
            
return setInstant(instant.getTime()); // NPE if instant == null
        
}

        
/**
         
* Sets the {@code field} parameter to the given {@code value}.
         
* {@code field} is an index to the {@link Calendar#fields}, such as
         
* {@link Calendar#DAY_OF_MONTH DAY_OF_MONTH}. Field value validation is
         
* not performed in this method. Any out of range values are either
         
* normalized in lenient mode or detected as an invalid value in
         
* non-lenient mode when building a {@code Calendar}.
         
*
         
* @param field an index to the {@code Calendar} fields
         
* @param value the field value
         
* @return this {@code Calendar.Builder}
         
* @throws IllegalArgumentException if {@code field} is invalid
         
* @throws IllegalStateException if the instant value has already been set,
         
*
                      
or if fields have been set too many
         
*
                      
(approximately {@link Integer#MAX_VALUE}) times.
         
* @see Calendar#set(int, int)
         
*/

        
public Builder set(int field, int value) {
            
// Note: WEEK_YEAR can't be set with this method.
            
if (field < 0 || field >= FIELD_COUNT) {
                
throw new IllegalArgumentException("field is invalid");
            
}
            
if (isInstantSet()) {
                
throw new IllegalStateException("instant has been set");
            
}
            
allocateFields();
            
internalSet(field, value);
            
return this;
        
}

        
/**
         
* Sets field parameters to their values given by
         
* {@code fieldValuePairs} that are pairs of a field and its value.
         
* For example,
         
* <pre>
         
*
   
setFeilds(Calendar.YEAR, 2013,
         
*
             
Calendar.MONTH, Calendar.DECEMBER,
         
*
             
Calendar.DAY_OF_MONTH, 23);</pre>
         
* is equivalent to the sequence of the following
         
* {@link #set(int, int) set} calls:
         
* <pre>
         
*
   
set(Calendar.YEAR, 2013)
         
*
   
.set(Calendar.MONTH, Calendar.DECEMBER)
         
*
   
.set(Calendar.DAY_OF_MONTH, 23);</pre>
         
*
         
* @param fieldValuePairs field-value pairs
         
* @return this {@code Calendar.Builder}
         
* @throws NullPointerException if {@code fieldValuePairs} is {@code null}
         
* @throws IllegalArgumentException if any of fields are invalid,
         
*
             
or if {@code fieldValuePairs.length} is an odd number.
         
* @throws IllegalStateException
    
if the instant value has been set,
         
*
             
or if fields have been set too many (approximately
         
*
             
{@link Integer#MAX_VALUE}) times.
         
*/

        
public Builder setFields(int... fieldValuePairs) {
            
int len = fieldValuePairs.length;
            
if ((len % 2) != 0) {
                
throw new IllegalArgumentException();
            
}
            
if (isInstantSet()) {
                
throw new IllegalStateException("instant has been set");
            
}
            
if ((nextStamp + len / 2) < 0) {
                
throw new IllegalStateException("stamp counter overflow");
            
}
            
allocateFields();
            
for (int i = 0; i < len; ) {
                
int field = fieldValuePairs[i++];
                
// Note: WEEK_YEAR can't be set with this method.
                
if (field < 0 || field >= FIELD_COUNT) {
                    
throw new IllegalArgumentException("field is invalid");
                
}
                
internalSet(field, fieldValuePairs[i++]);
            
}
            
return this;
        
}

        
/**
         
* Sets the date field parameters to the values given by {@code year},
         
* {@code month}, and {@code dayOfMonth}. This method is equivalent to
         
* a call to:
         
* <pre>
         
*
   
setFields(Calendar.YEAR, year,
         
*
             
Calendar.MONTH, month,
         
*
             
Calendar.DAY_OF_MONTH, dayOfMonth);</pre>
         
*
         
* @param year
       
the {@link Calendar#YEAR YEAR} value
         
* @param month
      
the {@link Calendar#MONTH MONTH} value
         
*
                   
(the month numbering is <em>0-based</em>).
         
* @param dayOfMonth the {@link Calendar#DAY_OF_MONTH DAY_OF_MONTH} value
         
* @return this {@code Calendar.Builder}
         
*/

        
public Builder setDate(int year, int month, int dayOfMonth) {
            
return setFields(YEAR, year, MONTH, month, DAY_OF_MONTH, dayOfMonth);
        
}

        
/**
         
* Sets the time of day field parameters to the values given by
         
* {@code hourOfDay}, {@code minute}, and {@code second}. This method is
         
* equivalent to a call to:
         
* <pre>
         
*
   
setTimeOfDay(hourOfDay, minute, second, 0);</pre>
         
*
         
* @param hourOfDay the {@link Calendar#HOUR_OF_DAY HOUR_OF_DAY} value
         
*
                  
(24-hour clock)
         
* @param minute
    
the {@link Calendar#MINUTE MINUTE} value
         
* @param second
    
the {@link Calendar#SECOND SECOND} value
         
* @return this {@code Calendar.Builder}
         
*/

        
public Builder setTimeOfDay(int hourOfDay, int minute, int second) {
            
return setTimeOfDay(hourOfDay, minute, second, 0);
        
}

        
/**
         
* Sets the time of day field parameters to the values given by
         
* {@code hourOfDay}, {@code minute}, {@code second}, and
         
* {@code millis}. This method is equivalent to a call to:
         
* <pre>
         
*
   
setFields(Calendar.HOUR_OF_DAY, hourOfDay,
         
*
             
Calendar.MINUTE, minute,
         
*
             
Calendar.SECOND, second,
         
*
             
Calendar.MILLISECOND, millis);</pre>
         
*
         
* @param hourOfDay the {@link Calendar#HOUR_OF_DAY HOUR_OF_DAY} value
         
*
                  
(24-hour clock)
         
* @param minute
    
the {@link Calendar#MINUTE MINUTE} value
         
* @param second
    
the {@link Calendar#SECOND SECOND} value
         
* @param millis
    
the {@link Calendar#MILLISECOND MILLISECOND} value
         
* @return this {@code Calendar.Builder}
         
*/

        
public Builder setTimeOfDay(int hourOfDay, int minute, int second, int millis) {
            
return setFields(HOUR_OF_DAY, hourOfDay, MINUTE, minute,
                             
SECOND, second, MILLISECOND, millis);
        
}

        
/**
         
* Sets the week-based date parameters to the values with the given
         
* date specifiers - week year, week of year, and day of week.
         
*
         
* <p>If the specified calendar doesn't support week dates, the
         
* {@link #build() build} method will throw an {@link IllegalArgumentException}.
         
*
         
* @param weekYear
   
the week year
         
* @param weekOfYear the week number based on {@code weekYear}
         
* @param dayOfWeek
  
the day of week value: one of the constants
         
*
     
for the {@link Calendar#DAY_OF_WEEK DAY_OF_WEEK} field:
         
*
     
{@link Calendar#SUNDAY SUNDAY}, ..., {@link Calendar#SATURDAY SATURDAY}.
         
* @return this {@code Calendar.Builder}
         
* @see Calendar#setWeekDate(int, int, int)
         
* @see Calendar#isWeekDateSupported()
         
*/

        
public Builder setWeekDate(int weekYear, int weekOfYear, int dayOfWeek) {
            
allocateFields();
            
internalSet(WEEK_YEAR, weekYear);
            
internalSet(WEEK_OF_YEAR, weekOfYear);
            
internalSet(DAY_OF_WEEK, dayOfWeek);
            
return this;
        
}

        
/**
         
* Sets the time zone parameter to the given {@code zone}. If no time
         
* zone parameter is given to this {@code Caledar.Builder}, the
         
* {@linkplain TimeZone#getDefault() default
         
* <code>TimeZone</code>} will be used in the {@link #build() build}
         
* method.
         
*
         
* @param zone the {@link TimeZone}
         
* @return this {@code Calendar.Builder}
         
* @throws NullPointerException if {@code zone} is {@code null}
         
* @see Calendar#setTimeZone(TimeZone)
         
*/

        
public Builder setTimeZone(TimeZone zone) {
            
if (zone == null) {
                
throw new NullPointerException();
            
}
            
this.zone = zone;
            
return this;
        
}

        
/**
         
* Sets the lenient mode parameter to the value given by {@code lenient}.
         
* If no lenient parameter is given to this {@code Calendar.Builder},
         
* lenient mode will be used in the {@link #build() build} method.
         
*
         
* @param lenient {@code true} for lenient mode;
         
*
                
{@code false} for non-lenient mode
         
* @return this {@code Calendar.Builder}
         
* @see Calendar#setLenient(boolean)
         
*/

        
public Builder setLenient(boolean lenient) {
            
this.lenient = lenient;
            
return this;
        
}

        
/**
         
* Sets the calendar type parameter to the given {@code type}. The
         
* calendar type given by this method has precedence over any explicit
         
* or implicit calendar type given by the
         
* {@linkplain #setLocale(Locale) locale}.
         
*
         
* <p>In addition to the available calendar types returned by the
         
* {@link Calendar#getAvailableCalendarTypes() Calendar.getAvailableCalendarTypes}
         
* method, {@code "gregorian"} and {@code "iso8601"} as aliases of
         
* {@code "gregory"} can be used with this method.
         
*
         
* @param type the calendar type
         
* @return this {@code Calendar.Builder}
         
* @throws NullPointerException if {@code type} is {@code null}
         
* @throws IllegalArgumentException if {@code type} is unknown
         
* @throws IllegalStateException if another calendar type has already been set
         
* @see Calendar#getCalendarType()
         
* @see Calendar#getAvailableCalendarTypes()
         
*/

        
public Builder setCalendarType(String type) {
            
if (type.equals("gregorian")) { // NPE if type == null
                
type = "gregory";
            
}
            
if (!Calendar.getAvailableCalendarTypes().contains(type)
                    
&& !type.equals("iso8601")) {
                
throw new IllegalArgumentException("unknown calendar type: " + type);
            
}
            
if (this.type == null) {
                
this.type = type;
            
} else {
                
if (!this.type.equals(type)) {
                    
throw new IllegalStateException("calendar type override");
                
}
            
}
            
return this;
        
}

        
/**
         
* Sets the locale parameter to the given {@code locale}. If no locale
         
* is given to this {@code Calendar.Builder}, the {@linkplain
         
* Locale#getDefault(Locale.Category) default <code>Locale</code>}
         
* for {@link Locale.Category#FORMAT} will be used.
         
*
         
* <p>If no calendar type is explicitly given by a call to the
         
* {@link #setCalendarType(String) setCalendarType} method,
         
* the {@code Locale} value is used to determine what type of
         
* {@code Calendar} to be built.
         
*
         
* <p>If no week definition parameters are explicitly given by a call to
         
* the {@link #setWeekDefinition(int,int) setWeekDefinition} method, the
         
* {@code Locale}'s default values are used.
         
*
         
* @param locale the {@link Locale}
         
* @throws NullPointerException if {@code locale} is {@code null}
         
* @return this {@code Calendar.Builder}
         
* @see Calendar#getInstance(Locale)
         
*/

        
public Builder setLocale(Locale locale) {
            
if (locale == null) {
                
throw new NullPointerException();
            
}
            
this.locale = locale;
            
return this;
        
}

        
/**
         
* Sets the week definition parameters to the values given by
         
* {@code firstDayOfWeek} and {@code minimalDaysInFirstWeek} that are
         
* used to determine the <a href="Calendar.html#First_Week">first
         
* week</a> of a year. The parameters given by this method have
         
* precedence over the default values given by the
         
* {@linkplain #setLocale(Locale) locale}.
         
*
         
* @param firstDayOfWeek the first day of a week; one of
         
*
                       
{@link Calendar#SUNDAY} to {@link Calendar#SATURDAY}
         
* @param minimalDaysInFirstWeek the minimal number of days in the first
         
*
                               
week (1..7)
         
* @return this {@code Calendar.Builder}
         
* @throws IllegalArgumentException if {@code firstDayOfWeek} or
         
*
                                  
{@code minimalDaysInFirstWeek} is invalid
         
* @see Calendar#getFirstDayOfWeek()
         
* @see Calendar#getMinimalDaysInFirstWeek()
         
*/

        
public Builder setWeekDefinition(int firstDayOfWeek, int minimalDaysInFirstWeek) {
            
if (!isValidWeekParameter(firstDayOfWeek)
                    
|| !isValidWeekParameter(minimalDaysInFirstWeek)) {
                
throw new IllegalArgumentException();
            
}
            
this.firstDayOfWeek = firstDayOfWeek;
            
this.minimalDaysInFirstWeek = minimalDaysInFirstWeek;
            
return this;
        
}

        
/**
         
* Returns a {@code Calendar} built from the parameters set by the
         
* setter methods. The calendar type given by the {@link #setCalendarType(String)
         
* setCalendarType} method or the {@linkplain #setLocale(Locale) locale} is
         
* used to determine what {@code Calendar} to be created. If no explicit
         
* calendar type is given, the locale's default calendar is created.
         
*
         
* <p>If the calendar type is {@code "iso8601"}, the
         
* {@linkplain GregorianCalendar#setGregorianChange(Date) Gregorian change date}
         
* of a {@link GregorianCalendar} is set to {@code Date(Long.MIN_VALUE)}
         
* to be the <em>proleptic</em> Gregorian calendar. Its week definition
         
* parameters are also set to be <a
         
* href="GregorianCalendar.html#iso8601_compatible_setting">compatible
         
* with the ISO 8601 standard</a>. Note that the
         
* {@link GregorianCalendar#getCalendarType() getCalendarType} method of
         
* a {@code GregorianCalendar} created with {@code "iso8601"} returns
         
* {@code "gregory"}.
         
*
         
* <p>The default values are used for locale and time zone if these
         
* parameters haven't been given explicitly.
         
*
         
* <p>Any out of range field values are either normalized in lenient
         
* mode or detected as an invalid value in non-lenient mode.
         
*
         
* @return a {@code Calendar} built with parameters of this {@code
         
*Calendar.Builder}
         
* @throws IllegalArgumentException if the calendar type is unknown, or
         
*
             
if any invalid field values are given in non-lenient mode, or
         
*
             
if a week date is given for the calendar type that doesn't
         
*
             
support week dates.
         
* @see Calendar#getInstance(TimeZone, Locale)
         
* @see Locale#getDefault(Locale.Category)
         
* @see TimeZone#getDefault()
         
*/

        
public Calendar build() {
            
if (locale == null) {
                
locale = Locale.getDefault();
            
}
            
if (zone == null) {
                
zone = TimeZone.getDefault();
            
}
            
Calendar cal;
            
if (type == null) {
                
type = locale.getUnicodeLocaleType("ca");
            
}
            
if (type == null) {
                
if (locale.getCountry() == "TH"
                    
&& locale.getLanguage() == "th") {
                    
type = "buddhist";
                
} else {
                    
type = "gregory";
                
}
            
}
            
switch (type) {
            
case "gregory":
                
cal = new GregorianCalendar(zone, locale, true);
                
break;
            
case "iso8601":
                
GregorianCalendar gcal = new GregorianCalendar(zone, locale, true);
                
// make gcal a proleptic Gregorian
                
gcal.setGregorianChange(new Date(Long.MIN_VALUE));
                
// and week definition to be compatible with ISO 8601
                
setWeekDefinition(MONDAY, 4);
                
cal = gcal;
                
break;
            
case "buddhist":
                
cal = new BuddhistCalendar(zone, locale);
                
cal.clear();
                
break;
            
case "japanese":
                
cal = new JapaneseImperialCalendar(zone, locale, true);
                
break;
            
default:
                
throw new IllegalArgumentException("unknown calendar type: " + type);
            
}
            
cal.setLenient(lenient);
            
if (firstDayOfWeek != 0) {
                
cal.setFirstDayOfWeek(firstDayOfWeek);
                
cal.setMinimalDaysInFirstWeek(minimalDaysInFirstWeek);
            
}
            
if (isInstantSet()) {
                
cal.setTimeInMillis(instant);
                
cal.complete();
                
return cal;
            
}

            
if (fields != null) {
                
boolean weekDate = isSet(WEEK_YEAR)
                                       
&& fields[WEEK_YEAR] > fields[YEAR];
                
if (weekDate && !cal.isWeekDateSupported()) {
                    
throw new IllegalArgumentException("week date is unsupported by " + type);
                
}

                
// Set the fields from the min stamp to the max stamp so that
                
// the fields resolution works in the Calendar.
                
for (int stamp = MINIMUM_USER_STAMP; stamp < nextStamp; stamp++) {
                    
for (int index = 0; index <= maxFieldIndex; index++) {
                        
if (fields[index] == stamp) {
                            
cal.set(index, fields[NFIELDS + index]);
                            
break;
                        
}
                    
}
                
}

                
if (weekDate) {
                    
int weekOfYear = isSet(WEEK_OF_YEAR) ? fields[NFIELDS + WEEK_OF_YEAR] : 1;
                    
int dayOfWeek = isSet(DAY_OF_WEEK)
                                    
? fields[NFIELDS + DAY_OF_WEEK] : cal.getFirstDayOfWeek();
                    
cal.setWeekDate(fields[NFIELDS + WEEK_YEAR], weekOfYear, dayOfWeek);
                
}
                
cal.complete();
            
}

            
return cal;
        
}

        
private void allocateFields() {
            
if (fields == null) {
                
fields = new int[NFIELDS * 2];
                
nextStamp = MINIMUM_USER_STAMP;
                
maxFieldIndex = -1;
            
}
        
}

        
private void internalSet(int field, int value) {
            
fields[field] = nextStamp++;
            
if (nextStamp < 0) {
                
throw new IllegalStateException("stamp counter overflow");
            
}
            
fields[NFIELDS + field] = value;
            
if (field > maxFieldIndex && field < WEEK_YEAR) {
                
maxFieldIndex = field;
            
}
        
}

        
private boolean isInstantSet() {
            
return nextStamp == COMPUTED;
        
}

        
private boolean isSet(int index) {
            
return fields != null && fields[index] > UNSET;
        
}

        
private boolean isValidWeekParameter(int value) {
            
return value > 0 && value <= 7;
        
}
    
}

    
/**
     
* Constructs a Calendar with the default time zone
     
* and the default {@link java.util.Locale.Category#FORMAT FORMAT}
     
* locale.
     
* @seeTimeZone#getDefault
     
*/

    
protected Calendar()
    
{
        
this(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));
        
sharedZone = true;
    
}

    
/**
     
* Constructs a calendar with the specified time zone and locale.
     
*
     
* @param zone the time zone to use
     
* @param aLocale the locale for the week data
     
*/

    
protected Calendar(TimeZone zone, Locale aLocale)
    
{
        
fields = new int[FIELD_COUNT];
        
isSet = new boolean[FIELD_COUNT];
        
stamp = new int[FIELD_COUNT];

        
this.zone = zone;
        
setWeekCountData(aLocale);
    
}

    
/**
     
* Gets a calendar using the default time zone and locale. The
     
* <code>Calendar</code> returned is based on the current time
     
* in the default time zone with the default
     
* {@link Locale.Category#FORMAT FORMAT} locale.
     
*
     
* @return a Calendar.
     
*/

    
public static Calendar getInstance()
    
{
        
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
    
}

    
/**
     
* Gets a calendar using the specified time zone and default locale.
     
* The <code>Calendar</code> returned is based on the current time
     
* in the given time zone with the default
     
* {@link Locale.Category#FORMAT FORMAT} locale.
     
*
     
* @param zone the time zone to use
     
* @return a Calendar.
     
*/

    
public static Calendar getInstance(TimeZone zone)
    
{
        
return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT));
    
}

    
/**
     
* Gets a calendar using the default time zone and specified locale.
     
* The <code>Calendar</code> returned is based on the current time
     
* in the default time zone with the given locale.
     
*
     
* @param aLocale the locale for the week data
     
* @return a Calendar.
     
*/

    
public static Calendar getInstance(Locale aLocale)
    
{
        
return createCalendar(TimeZone.getDefault(), aLocale);
    
}

    
/**
     
* Gets a calendar with the specified time zone and locale.
     
* The <code>Calendar</code> returned is based on the current time
     
* in the given time zone with the given locale.
     
*
     
* @param zone the time zone to use
     
* @param aLocale the locale for the week data
     
* @return a Calendar.
     
*/

    
public static Calendar getInstance(TimeZone zone,