src/share/classes/java/util/Calendar.java

Print this page
rev 5696 : 6336885: RFE: Locale Data Deployment Enhancements
4609153: Provide locale data for Indic locales
5104387: Support for gl_ES locale (galician language)
6337471: desktop/system locale preferences support
7056139: (cal) SPI support for locale-dependent Calendar parameters
7058206: Provide CalendarData SPI for week params and display field value names
7073852: Support multiple scripts for digits and decimal symbols per locale
7079560: [Fmt-Da] Context dependent month names support in SimpleDateFormat
7171324: getAvailableLocales() of locale sensitive services should return the actual availability of locales
7151414: (cal) Support calendar type identification
7168528: LocaleServiceProvider needs to be aware of Locale extensions
7171372: (cal) locale's default Calendar should be created if unknown calendar is specified
Summary: JEP 127: Improve Locale Data Packaging and Adopt Unicode CLDR Data (part 1 w/o packaging changes. by Naoto Sato and Masayoshi Okutsu)


  36  *
  37  */
  38 
  39 package java.util;
  40 
  41 import java.io.IOException;
  42 import java.io.ObjectInputStream;
  43 import java.io.ObjectOutputStream;
  44 import java.io.OptionalDataException;
  45 import java.io.Serializable;
  46 import java.security.AccessControlContext;
  47 import java.security.AccessController;
  48 import java.security.PermissionCollection;
  49 import java.security.PrivilegedActionException;
  50 import java.security.PrivilegedExceptionAction;
  51 import java.security.ProtectionDomain;
  52 import java.text.DateFormat;
  53 import java.text.DateFormatSymbols;
  54 import java.util.concurrent.ConcurrentHashMap;
  55 import java.util.concurrent.ConcurrentMap;

  56 import sun.util.BuddhistCalendar;

  57 import sun.util.calendar.ZoneInfo;
  58 import sun.util.resources.LocaleData;
  59 
  60 /**
  61  * The <code>Calendar</code> class is an abstract class that provides methods
  62  * for converting between a specific instant in time and a set of {@link
  63  * #fields calendar fields} such as <code>YEAR</code>, <code>MONTH</code>,
  64  * <code>DAY_OF_MONTH</code>, <code>HOUR</code>, and so on, and for
  65  * manipulating the calendar fields, such as getting the date of the next
  66  * week. An instant in time can be represented by a millisecond value that is
  67  * an offset from the <a name="Epoch"><em>Epoch</em></a>, January 1, 1970
  68  * 00:00:00.000 GMT (Gregorian).
  69  *
  70  * <p>The class also provides additional fields and methods for
  71  * implementing a concrete calendar system outside the package. Those
  72  * fields and methods are defined as <code>protected</code>.
  73  *
  74  * <p>
  75  * Like other locale-sensitive classes, <code>Calendar</code> provides a
  76  * class method, <code>getInstance</code>, for getting a generally useful
  77  * object of this type. <code>Calendar</code>'s <code>getInstance</code> method
  78  * returns a <code>Calendar</code> object whose


 690      */
 691     public final static int UNDECIMBER = 12;
 692 
 693     /**
 694      * Value of the {@link #AM_PM} field indicating the
 695      * period of the day from midnight to just before noon.
 696      */
 697     public final static int AM = 0;
 698 
 699     /**
 700      * Value of the {@link #AM_PM} field indicating the
 701      * period of the day from noon to just before midnight.
 702      */
 703     public final static int PM = 1;
 704 
 705     /**
 706      * A style specifier for {@link #getDisplayNames(int, int, Locale)
 707      * getDisplayNames} indicating names in all styles, such as
 708      * "January" and "Jan".
 709      *




 710      * @see #SHORT
 711      * @see #LONG
 712      * @since 1.6
 713      */
 714     public static final int ALL_STYLES = 0;
 715 


 716     /**
 717      * A style specifier for {@link #getDisplayName(int, int, Locale)
 718      * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
 719      * getDisplayNames} indicating a short name, such as "Jan".
 720      *

 721      * @see #LONG
 722      * @since 1.6
 723      */
 724     public static final int SHORT = 1;
 725 
 726     /**
 727      * A style specifier for {@link #getDisplayName(int, int, Locale)
 728      * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
 729      * getDisplayNames} indicating a long name, such as "January".
 730      *

 731      * @see #SHORT
 732      * @since 1.6
 733      */
 734     public static final int LONG = 2;
 735 


















































 736     // Internal notes:
 737     // Calendar contains two kinds of time representations: current "time" in
 738     // milliseconds, and a set of calendar "fields" representing the current time.
 739     // The two representations are usually in sync, but can get out of sync
 740     // as follows.
 741     // 1. Initially, no fields are set, and the time is invalid.
 742     // 2. If the time is set, all fields are computed and in sync.
 743     // 3. If a single field is set, the time is invalid.
 744     // Recomputation of the time and fields happens when the object needs
 745     // to return a result to the user, or use a result for a computation.
 746 
 747     /**
 748      * The calendar field values for the currently set time for this calendar.
 749      * This is an array of <code>FIELD_COUNT</code> integers, with index values
 750      * <code>ERA</code> through <code>DST_OFFSET</code>.
 751      * @serial
 752      */

 753     protected int           fields[];
 754 
 755     /**
 756      * The flags which tell if a specified calendar field for the calendar is set.
 757      * A new object has no fields set.  After the first call to a method
 758      * which generates the fields, they all remain set after that.
 759      * This is an array of <code>FIELD_COUNT</code> booleans, with index values
 760      * <code>ERA</code> through <code>DST_OFFSET</code>.
 761      * @serial
 762      */

 763     protected boolean       isSet[];
 764 
 765     /**
 766      * Pseudo-time-stamps which specify when each field was set. There
 767      * are two special values, UNSET and COMPUTED. Values from
 768      * MINIMUM_USER_SET to Integer.MAX_VALUE are legal user set values.
 769      */
 770     transient private int   stamp[];
 771 
 772     /**
 773      * The currently set time for this calendar, expressed in milliseconds after
 774      * January 1, 1970, 0:00:00 GMT.
 775      * @see #isTimeSet
 776      * @serial
 777      */

 778     protected long          time;
 779 
 780     /**
 781      * True if then the value of <code>time</code> is valid.
 782      * The time is made invalid by a change to an item of <code>field[]</code>.
 783      * @see #time
 784      * @serial
 785      */

 786     protected boolean       isTimeSet;
 787 
 788     /**
 789      * True if <code>fields[]</code> are in sync with the currently set time.
 790      * If false, then the next attempt to get the value of a field will
 791      * force a recomputation of all fields from the current value of
 792      * <code>time</code>.
 793      * @serial
 794      */

 795     protected boolean       areFieldsSet;
 796 
 797     /**
 798      * True if all fields have been set.
 799      * @serial
 800      */
 801     transient boolean       areAllFieldsSet;
 802 
 803     /**
 804      * <code>True</code> if this calendar allows out-of-range field values during computation
 805      * of <code>time</code> from <code>fields[]</code>.
 806      * @see #setLenient
 807      * @see #isLenient
 808      * @serial
 809      */
 810     private boolean         lenient = true;
 811 
 812     /**
 813      * The <code>TimeZone</code> used by this calendar. <code>Calendar</code>
 814      * uses the time zone data to translate between locale and GMT time.


 893      * </dd>
 894      * <dt><b>1</b></dt>
 895      * <dd>
 896      * JDK 1.1.6 or later.  Writes a correct 'time' value
 897      * as well as compatible values for other fields.  This is a
 898      * transitional format.
 899      * </dd>
 900      * </dl>
 901      * When streaming out this class, the most recent format
 902      * and the highest allowable <code>serialVersionOnStream</code>
 903      * is written.
 904      * @serial
 905      * @since JDK1.1.6
 906      */
 907     private int             serialVersionOnStream = currentSerialVersion;
 908 
 909     // Proclaim serialization compatibility with JDK 1.1
 910     static final long       serialVersionUID = -1807547505821590642L;
 911 
 912     // Mask values for calendar fields

 913     final static int ERA_MASK           = (1 << ERA);
 914     final static int YEAR_MASK          = (1 << YEAR);
 915     final static int MONTH_MASK         = (1 << MONTH);
 916     final static int WEEK_OF_YEAR_MASK  = (1 << WEEK_OF_YEAR);
 917     final static int WEEK_OF_MONTH_MASK = (1 << WEEK_OF_MONTH);
 918     final static int DAY_OF_MONTH_MASK  = (1 << DAY_OF_MONTH);
 919     final static int DATE_MASK          = DAY_OF_MONTH_MASK;
 920     final static int DAY_OF_YEAR_MASK   = (1 << DAY_OF_YEAR);
 921     final static int DAY_OF_WEEK_MASK   = (1 << DAY_OF_WEEK);
 922     final static int DAY_OF_WEEK_IN_MONTH_MASK  = (1 << DAY_OF_WEEK_IN_MONTH);
 923     final static int AM_PM_MASK         = (1 << AM_PM);
 924     final static int HOUR_MASK          = (1 << HOUR);
 925     final static int HOUR_OF_DAY_MASK   = (1 << HOUR_OF_DAY);
 926     final static int MINUTE_MASK        = (1 << MINUTE);
 927     final static int SECOND_MASK        = (1 << SECOND);
 928     final static int MILLISECOND_MASK   = (1 << MILLISECOND);
 929     final static int ZONE_OFFSET_MASK   = (1 << ZONE_OFFSET);
 930     final static int DST_OFFSET_MASK    = (1 << DST_OFFSET);
 931 
 932     /**


1001     /**
1002      * Gets a calendar with the specified time zone and locale.
1003      * The <code>Calendar</code> returned is based on the current time
1004      * in the given time zone with the given locale.
1005      *
1006      * @param zone the time zone to use
1007      * @param aLocale the locale for the week data
1008      * @return a Calendar.
1009      */
1010     public static Calendar getInstance(TimeZone zone,
1011                                        Locale aLocale)
1012     {
1013         return createCalendar(zone, aLocale);
1014     }
1015 
1016     private static Calendar createCalendar(TimeZone zone,
1017                                            Locale aLocale)
1018     {
1019         Calendar cal = null;
1020 

1021         String caltype = aLocale.getUnicodeLocaleType("ca");
1022         if (caltype == null) {
1023             // Calendar type is not specified.
1024             // If the specified locale is a Thai locale,
1025             // returns a BuddhistCalendar instance.
1026             if ("th".equals(aLocale.getLanguage())
1027                     && ("TH".equals(aLocale.getCountry()))) {
1028                 cal = new BuddhistCalendar(zone, aLocale);
1029             } else {




1030                 cal = new GregorianCalendar(zone, aLocale);

1031             }
1032         } else if (caltype.equals("japanese")) {
1033             cal = new JapaneseImperialCalendar(zone, aLocale);
1034         } else if (caltype.equals("buddhist")) {







1035             cal = new BuddhistCalendar(zone, aLocale);



1036         } else {
1037             // Unsupported calendar type.
1038             // Use Gregorian calendar as a fallback.
1039             cal = new GregorianCalendar(zone, aLocale);
1040         }
1041 
1042         return cal;
1043     }
1044 
1045     /**
1046      * Returns an array of all locales for which the <code>getInstance</code>
1047      * methods of this class can return localized instances.
1048      * The array returned must contain at least a <code>Locale</code>
1049      * instance equal to {@link java.util.Locale#US Locale.US}.
1050      *
1051      * @return An array of locales for which localized
1052      *         <code>Calendar</code> instances are available.
1053      */
1054     public static synchronized Locale[] getAvailableLocales()
1055     {
1056         return DateFormat.getAvailableLocales();
1057     }
1058 
1059     /**
1060      * Converts the current calendar field values in {@link #fields fields[]}
1061      * to the millisecond time value


1376      * {@link Calendar#get(int) get(field)} to get the calendar
1377      * <code>field</code> value if the string representation is
1378      * applicable to the given calendar <code>field</code>.
1379      *
1380      * <p>For example, if this <code>Calendar</code> is a
1381      * <code>GregorianCalendar</code> and its date is 2005-01-01, then
1382      * the string representation of the {@link #MONTH} field would be
1383      * "January" in the long style in an English locale or "Jan" in
1384      * the short style. However, no string representation would be
1385      * available for the {@link #DAY_OF_MONTH} field, and this method
1386      * would return <code>null</code>.
1387      *
1388      * <p>The default implementation supports the calendar fields for
1389      * which a {@link DateFormatSymbols} has names in the given
1390      * <code>locale</code>.
1391      *
1392      * @param field
1393      *        the calendar field for which the string representation
1394      *        is returned
1395      * @param style
1396      *        the style applied to the string representation; one of
1397      *        {@link #SHORT} or {@link #LONG}.

1398      * @param locale
1399      *        the locale for the string representation

1400      * @return the string representation of the given
1401      *        <code>field</code> in the given <code>style</code>, or
1402      *        <code>null</code> if no string representation is
1403      *        applicable.
1404      * @exception IllegalArgumentException
1405      *        if <code>field</code> or <code>style</code> is invalid,
1406      *        or if this <code>Calendar</code> is non-lenient and any
1407      *        of the calendar fields have invalid values
1408      * @exception NullPointerException
1409      *        if <code>locale</code> is null
1410      * @since 1.6
1411      */
1412     public String getDisplayName(int field, int style, Locale locale) {
1413         if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale,
1414                                     ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
1415             return null;
1416         }
1417 







1418         DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale);
1419         String[] strings = getFieldStrings(field, style, symbols);
1420         if (strings != null) {
1421             int fieldValue = get(field);
1422             if (fieldValue < strings.length) {
1423                 return strings[fieldValue];
1424             }
1425         }
1426         return null;
1427     }
1428 
1429     /**
1430      * Returns a <code>Map</code> containing all names of the calendar
1431      * <code>field</code> in the given <code>style</code> and
1432      * <code>locale</code> and their corresponding field values. For
1433      * example, if this <code>Calendar</code> is a {@link
1434      * GregorianCalendar}, the returned map would contain "Jan" to
1435      * {@link #JANUARY}, "Feb" to {@link #FEBRUARY}, and so on, in the
1436      * {@linkplain #SHORT short} style in an English locale.
1437      *
1438      * <p>The values of other calendar fields may be taken into
1439      * account to determine a set of display names. For example, if
1440      * this <code>Calendar</code> is a lunisolar calendar system and
1441      * the year value given by the {@link #YEAR} field has a leap
1442      * month, this method would return month names containing the leap
1443      * month name, and month names are mapped to their values specific
1444      * for the year.
1445      *
1446      * <p>The default implementation supports display names contained in
1447      * a {@link DateFormatSymbols}. For example, if <code>field</code>
1448      * is {@link #MONTH} and <code>style</code> is {@link
1449      * #ALL_STYLES}, this method returns a <code>Map</code> containing
1450      * all strings returned by {@link DateFormatSymbols#getShortMonths()}
1451      * and {@link DateFormatSymbols#getMonths()}.
1452      *
1453      * @param field
1454      *        the calendar field for which the display names are returned
1455      * @param style
1456      *        the style applied to the display names; one of {@link
1457      *        #SHORT}, {@link #LONG}, or {@link #ALL_STYLES}.

1458      * @param locale
1459      *        the locale for the display names
1460      * @return a <code>Map</code> containing all display names in
1461      *        <code>style</code> and <code>locale</code> and their
1462      *        field values, or <code>null</code> if no display names
1463      *        are defined for <code>field</code>
1464      * @exception IllegalArgumentException
1465      *        if <code>field</code> or <code>style</code> is invalid,
1466      *        or if this <code>Calendar</code> is non-lenient and any
1467      *        of the calendar fields have invalid values
1468      * @exception NullPointerException
1469      *        if <code>locale</code> is null
1470      * @since 1.6
1471      */
1472     public Map<String, Integer> getDisplayNames(int field, int style, Locale locale) {
1473         if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale,
1474                                     ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
1475             return null;
1476         }
1477 
1478         // ALL_STYLES
1479         if (style == ALL_STYLES) {
1480             Map<String,Integer> shortNames = getDisplayNamesImpl(field, SHORT, locale);
1481             if (field == ERA || field == AM_PM) {
1482                 return shortNames;
1483             }
1484             Map<String,Integer> longNames = getDisplayNamesImpl(field, LONG, locale);
1485             if (shortNames == null) {
1486                 return longNames;
1487             }
1488             if (longNames != null) {
1489                 shortNames.putAll(longNames);
1490             }
1491             return shortNames;
1492         }
1493 
1494         // SHORT or LONG
1495         return getDisplayNamesImpl(field, style, locale);
1496     }
1497 
1498     private Map<String,Integer> getDisplayNamesImpl(int field, int style, Locale locale) {
1499         DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale);
1500         String[] strings = getFieldStrings(field, style, symbols);
1501         if (strings != null) {
1502             Map<String,Integer> names = new HashMap<>();
1503             for (int i = 0; i < strings.length; i++) {
1504                 if (strings[i].length() == 0) {
1505                     continue;
1506                 }
1507                 names.put(strings[i], i);
1508             }
1509             return names;
1510         }
1511         return null;
1512     }
1513 
1514     boolean checkDisplayNameParams(int field, int style, int minStyle, int maxStyle,
1515                                    Locale locale, int fieldMask) {

1516         if (field < 0 || field >= fields.length ||
1517             style < minStyle || style > maxStyle) {
1518             throw new IllegalArgumentException();
1519         }
1520         if (locale == null) {
1521             throw new NullPointerException();
1522         }
1523         return isFieldSet(fieldMask, field);
1524     }
1525 
1526     private String[] getFieldStrings(int field, int style, DateFormatSymbols symbols) {

1527         String[] strings = null;
1528         switch (field) {
1529         case ERA:
1530             strings = symbols.getEras();
1531             break;
1532 
1533         case MONTH:
1534             strings = (style == LONG) ? symbols.getMonths() : symbols.getShortMonths();
1535             break;
1536 
1537         case DAY_OF_WEEK:
1538             strings = (style == LONG) ? symbols.getWeekdays() : symbols.getShortWeekdays();
1539             break;
1540 
1541         case AM_PM:
1542             strings = symbols.getAmPmStrings();
1543             break;
1544         }
1545         return strings;
1546     }
1547 
1548     /**
1549      * Fills in any unset fields in the calendar fields. First, the {@link
1550      * #computeTime()} method is called if the time value (millisecond offset
1551      * from the <a href="#Epoch">Epoch</a>) has not been calculated from
1552      * calendar field values. Then, the {@link #computeFields()} method is
1553      * called to calculate all calendar field values.
1554      */
1555     protected void complete()
1556     {
1557         if (!isTimeSet)
1558             updateTime();

1559         if (!areFieldsSet || !areAllFieldsSet) {
1560             computeFields(); // fills in unset fields
1561             areAllFieldsSet = areFieldsSet = true;
1562         }
1563     }
1564 
1565     /**
1566      * Returns whether the value of the specified calendar field has been set
1567      * externally by calling one of the setter methods rather than by the
1568      * internal time calculation.
1569      *
1570      * @return <code>true</code> if the field has been set externally,
1571      * <code>false</code> otherwise.
1572      * @exception IndexOutOfBoundsException if the specified
1573      *                <code>field</code> is out of range
1574      *               (<code>field &lt; 0 || field &gt;= FIELD_COUNT</code>).
1575      * @see #selectFields()
1576      * @see #setFieldsComputed(int)
1577      */
1578     final boolean isExternallySet(int field) {


1672 
1673     /**
1674      * Returns whether the calendar fields are fully in sync with the time
1675      * value.
1676      */
1677     final boolean isFullyNormalized() {
1678         return areFieldsSet && areAllFieldsSet;
1679     }
1680 
1681     /**
1682      * Marks this Calendar as not sync'd.
1683      */
1684     final void setUnnormalized() {
1685         areFieldsSet = areAllFieldsSet = false;
1686     }
1687 
1688     /**
1689      * Returns whether the specified <code>field</code> is on in the
1690      * <code>fieldMask</code>.
1691      */
1692     static final boolean isFieldSet(int fieldMask, int field) {
1693         return (fieldMask & (1 << field)) != 0;
1694     }
1695 
1696     /**
1697      * Returns a field mask indicating which calendar field values
1698      * to be used to calculate the time value. The calendar fields are
1699      * returned as a bit mask, each bit of which corresponds to a field, i.e.,
1700      * the mask value of <code>field</code> is <code>(1 &lt;&lt;
1701      * field)</code>. For example, 0x26 represents the <code>YEAR</code>,
1702      * <code>MONTH</code>, and <code>DAY_OF_MONTH</code> fields (i.e., 0x26 is
1703      * equal to
1704      * <code>(1&lt;&lt;YEAR)|(1&lt;&lt;MONTH)|(1&lt;&lt;DAY_OF_MONTH))</code>.
1705      *
1706      * <p>This method supports the calendar fields resolution as described in
1707      * the class description. If the bit mask for a given field is on and its
1708      * field has not been set (i.e., <code>isSet(field)</code> is
1709      * <code>false</code>), then the default value of the field has to be
1710      * used, which case means that the field has been selected because the
1711      * selected combination involves the field.
1712      *


1848         }
1849         if (stamp[MINUTE] != UNSET) {
1850             fieldMask |= MINUTE_MASK;
1851         }
1852         if (stamp[SECOND] != UNSET) {
1853             fieldMask |= SECOND_MASK;
1854         }
1855         if (stamp[MILLISECOND] != UNSET) {
1856             fieldMask |= MILLISECOND_MASK;
1857         }
1858         if (stamp[ZONE_OFFSET] >= MINIMUM_USER_STAMP) {
1859                 fieldMask |= ZONE_OFFSET_MASK;
1860         }
1861         if (stamp[DST_OFFSET] >= MINIMUM_USER_STAMP) {
1862             fieldMask |= DST_OFFSET_MASK;
1863         }
1864 
1865         return fieldMask;
1866     }
1867 








1868     /**
1869      * Returns the pseudo-time-stamp for two fields, given their
1870      * individual pseudo-time-stamps.  If either of the fields
1871      * is unset, then the aggregate is unset.  Otherwise, the
1872      * aggregate is the later of the two stamps.
1873      */
1874     private static final int aggregateStamp(int stamp_a, int stamp_b) {
1875         if (stamp_a == UNSET || stamp_b == UNSET) {
1876             return UNSET;
1877         }
1878         return (stamp_a > stamp_b) ? stamp_a : stamp_b;
1879     }
1880 
1881     /**





















1882      * Compares this <code>Calendar</code> to the specified
1883      * <code>Object</code>.  The result is <code>true</code> if and only if
1884      * the argument is a <code>Calendar</code> object of the same calendar
1885      * system that represents the same time value (millisecond offset from the
1886      * <a href="#Epoch">Epoch</a>) under the same
1887      * <code>Calendar</code> parameters as this object.
1888      *
1889      * <p>The <code>Calendar</code> parameters are the values represented
1890      * by the <code>isLenient</code>, <code>getFirstDayOfWeek</code>,
1891      * <code>getMinimalDaysInFirstWeek</code> and <code>getTimeZone</code>
1892      * methods. If there is any difference in those parameters
1893      * between the two <code>Calendar</code>s, this method returns
1894      * <code>false</code>.
1895      *
1896      * <p>Use the {@link #compareTo(Calendar) compareTo} method to
1897      * compare only the time values.
1898      *
1899      * @param obj the object to compare with.
1900      * @return <code>true</code> if this object is equal to <code>obj</code>;
1901      * <code>false</code> otherwise.
1902      */


1903     public boolean equals(Object obj) {
1904         if (this == obj)
1905             return true;

1906         try {
1907             Calendar that = (Calendar)obj;
1908             return compareTo(getMillisOf(that)) == 0 &&
1909                 lenient == that.lenient &&
1910                 firstDayOfWeek == that.firstDayOfWeek &&
1911                 minimalDaysInFirstWeek == that.minimalDaysInFirstWeek &&
1912                 zone.equals(that.zone);
1913         } catch (Exception e) {
1914             // Note: GregorianCalendar.computeTime throws
1915             // IllegalArgumentException if the ERA value is invalid
1916             // even it's in lenient mode.
1917         }
1918         return false;
1919     }
1920 
1921     /**
1922      * Returns a hash code for this calendar.
1923      *
1924      * @return a hash code value for this object.
1925      * @since 1.2
1926      */

1927     public int hashCode() {
1928         // 'otheritems' represents the hash code for the previous versions.
1929         int otheritems = (lenient ? 1 : 0)
1930             | (firstDayOfWeek << 1)
1931             | (minimalDaysInFirstWeek << 4)
1932             | (zone.hashCode() << 7);
1933         long t = getMillisOf(this);
1934         return (int) t ^ (int)(t >> 32) ^ otheritems;
1935     }
1936 
1937     /**
1938      * Returns whether this <code>Calendar</code> represents a time
1939      * before the time represented by the specified
1940      * <code>Object</code>. This method is equivalent to:
1941      * <pre><blockquote>
1942      *         compareTo(when) < 0
1943      * </blockquote></pre>
1944      * if and only if <code>when</code> is a <code>Calendar</code>
1945      * instance. Otherwise, the method returns <code>false</code>.
1946      *


1978 
1979     /**
1980      * Compares the time values (millisecond offsets from the <a
1981      * href="#Epoch">Epoch</a>) represented by two
1982      * <code>Calendar</code> objects.
1983      *
1984      * @param anotherCalendar the <code>Calendar</code> to be compared.
1985      * @return the value <code>0</code> if the time represented by the argument
1986      * is equal to the time represented by this <code>Calendar</code>; a value
1987      * less than <code>0</code> if the time of this <code>Calendar</code> is
1988      * before the time represented by the argument; and a value greater than
1989      * <code>0</code> if the time of this <code>Calendar</code> is after the
1990      * time represented by the argument.
1991      * @exception NullPointerException if the specified <code>Calendar</code> is
1992      *            <code>null</code>.
1993      * @exception IllegalArgumentException if the time value of the
1994      * specified <code>Calendar</code> object can't be obtained due to
1995      * any invalid calendar values.
1996      * @since   1.5
1997      */

1998     public int compareTo(Calendar anotherCalendar) {
1999         return compareTo(getMillisOf(anotherCalendar));
2000     }
2001 
2002     /**
2003      * Adds or subtracts the specified amount of time to the given calendar field,
2004      * based on the calendar's rules. For example, to subtract 5 days from
2005      * the current time of the calendar, you can achieve it by calling:
2006      * <p><code>add(Calendar.DAY_OF_MONTH, -5)</code>.
2007      *
2008      * @param field the calendar field.
2009      * @param amount the amount of date or time to be added to the field.
2010      * @see #roll(int,int)
2011      * @see #set(int,int)
2012      */
2013     abstract public void add(int field, int amount);
2014 
2015     /**
2016      * Adds or subtracts (up/down) a single unit of time on the given time
2017      * field without changing larger fields. For example, to roll the current


2451      * @see #getLeastMaximum(int)
2452      * @see #getActualMinimum(int)
2453      * @since 1.2
2454      */
2455     public int getActualMaximum(int field) {
2456         int fieldValue = getLeastMaximum(field);
2457         int endValue = getMaximum(field);
2458 
2459         // if we know that the maximum value is always the same, just return it.
2460         if (fieldValue == endValue) {
2461             return fieldValue;
2462         }
2463 
2464         // clone the calendar so we don't mess with the real one, and set it to
2465         // accept anything for the field values.
2466         Calendar work = (Calendar)this.clone();
2467         work.setLenient(true);
2468 
2469         // if we're counting weeks, set the day of the week to Sunday.  We know the
2470         // last week of a month or year will contain the first day of the week.
2471         if (field == WEEK_OF_YEAR || field == WEEK_OF_MONTH)
2472             work.set(DAY_OF_WEEK, firstDayOfWeek);

2473 
2474         // now try each value from getLeastMaximum() to getMaximum() one by one until
2475         // we get a value that normalizes to another value.  The last value that
2476         // normalizes to itself is the actual maximum for the current date
2477         int result = fieldValue;
2478 
2479         do {
2480             work.set(field, fieldValue);
2481             if (work.get(field) != fieldValue) {
2482                 break;
2483             } else {
2484                 result = fieldValue;
2485                 fieldValue++;
2486             }
2487         } while (fieldValue <= endValue);
2488 
2489         return result;
2490     }
2491 
2492     /**
2493      * Creates and returns a copy of this object.
2494      *
2495      * @return a copy of this object.
2496      */

2497     public Object clone()
2498     {
2499         try {
2500             Calendar other = (Calendar) super.clone();
2501 
2502             other.fields = new int[FIELD_COUNT];
2503             other.isSet = new boolean[FIELD_COUNT];
2504             other.stamp = new int[FIELD_COUNT];
2505             for (int i = 0; i < FIELD_COUNT; i++) {
2506                 other.fields[i] = fields[i];
2507                 other.stamp[i] = stamp[i];
2508                 other.isSet[i] = isSet[i];
2509             }
2510             other.zone = (TimeZone) zone.clone();
2511             return other;
2512         }
2513         catch (CloneNotSupportedException e) {
2514             // this shouldn't happen, since we are Cloneable
2515             throw new InternalError(e);
2516         }
2517     }
2518 
2519     private static final String[] FIELD_NAME = {
2520         "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH",
2521         "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR",
2522         "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",
2523         "DST_OFFSET"
2524     };
2525 
2526     /**
2527      * Returns the name of the specified calendar field.
2528      *
2529      * @param field the calendar field
2530      * @return the calendar field name
2531      * @exception IndexOutOfBoundsException if <code>field</code> is negative,
2532      * equal to or greater then <code>FIELD_COUNT</code>.
2533      */
2534     static final String getFieldName(int field) {
2535         return FIELD_NAME[field];
2536     }
2537 
2538     /**
2539      * Return a string representation of this calendar. This method
2540      * is intended to be used only for debugging purposes, and the
2541      * format of the returned string may vary between implementations.
2542      * The returned string may be empty but may not be <code>null</code>.
2543      *
2544      * @return  a string representation of this calendar.
2545      */

2546     public String toString() {
2547         // NOTE: BuddhistCalendar.toString() interprets the string
2548         // produced by this method so that the Gregorian year number
2549         // is substituted by its B.E. year value. It relies on
2550         // "...,YEAR=<year>,..." or "...,YEAR=?,...".
2551         StringBuilder buffer = new StringBuilder(800);
2552         buffer.append(getClass().getName()).append('[');
2553         appendValue(buffer, "time", isTimeSet, time);
2554         buffer.append(",areFieldsSet=").append(areFieldsSet);
2555         buffer.append(",areAllFieldsSet=").append(areAllFieldsSet);
2556         buffer.append(",lenient=").append(lenient);
2557         buffer.append(",zone=").append(zone);
2558         appendValue(buffer, ",firstDayOfWeek", true, (long) firstDayOfWeek);
2559         appendValue(buffer, ",minimalDaysInFirstWeek", true, (long) minimalDaysInFirstWeek);
2560         for (int i = 0; i < FIELD_COUNT; ++i) {
2561             buffer.append(',');
2562             appendValue(buffer, FIELD_NAME[i], isSet(i), (long) fields[i]);
2563         }
2564         buffer.append(']');
2565         return buffer.toString();
2566     }
2567 
2568     // =======================privates===============================
2569 
2570     private static final void appendValue(StringBuilder sb, String item, boolean valid, long value) {
2571         sb.append(item).append('=');
2572         if (valid) {
2573             sb.append(value);
2574         } else {
2575             sb.append('?');
2576         }
2577     }
2578 
2579     /**
2580      * Both firstDayOfWeek and minimalDaysInFirstWeek are locale-dependent.
2581      * They are used to figure out the week count for a specific date for
2582      * a given locale. These must be set when a Calendar is constructed.
2583      * @param desiredLocale the given locale.
2584      */
2585     private void setWeekCountData(Locale desiredLocale)
2586     {
2587         /* try to get the Locale data from the cache */
2588         int[] data = cachedLocaleData.get(desiredLocale);
2589         if (data == null) {  /* cache miss */
2590             ResourceBundle bundle = LocaleData.getCalendarData(desiredLocale);

2591             data = new int[2];
2592             data[0] = Integer.parseInt(bundle.getString("firstDayOfWeek"));
2593             data[1] = Integer.parseInt(bundle.getString("minimalDaysInFirstWeek"));

2594             cachedLocaleData.putIfAbsent(desiredLocale, data);
2595         }
2596         firstDayOfWeek = data[0];
2597         minimalDaysInFirstWeek = data[1];
2598     }
2599 
2600     /**
2601      * Recomputes the time and updates the status fields isTimeSet
2602      * and areFieldsSet.  Callers should check isTimeSet and only
2603      * call this method if isTimeSet is false.
2604      */
2605     private void updateTime() {
2606         computeTime();
2607         // The areFieldsSet and areAllFieldsSet values are no longer
2608         // controlled here (as of 1.5).
2609         isTimeSet = true;
2610     }
2611 
2612     private int compareTo(long t) {
2613         long thisTime = getMillisOf(this);
2614         return (thisTime > t) ? 1 : (thisTime == t) ? 0 : -1;
2615     }
2616 
2617     private static final long getMillisOf(Calendar calendar) {
2618         if (calendar.isTimeSet) {
2619             return calendar.time;
2620         }
2621         Calendar cal = (Calendar) calendar.clone();
2622         cal.setLenient(true);
2623         return cal.getTimeInMillis();
2624     }
2625 
2626     /**
2627      * Adjusts the stamp[] values before nextStamp overflow. nextStamp
2628      * is set to the next stamp value upon the return.
2629      */
2630     private final void adjustStamp() {
2631         int max = MINIMUM_USER_STAMP;
2632         int newStamp = MINIMUM_USER_STAMP;
2633 
2634         for (;;) {
2635             int min = Integer.MAX_VALUE;
2636             for (int i = 0; i < stamp.length; i++) {
2637                 int v = stamp[i];
2638                 if (v >= newStamp && min > v) {
2639                     min = v;
2640                 }
2641                 if (max < v) {
2642                     max = v;
2643                 }
2644             }
2645             if (max != min && min == Integer.MAX_VALUE) {
2646                 break;
2647             }
2648             for (int i = 0; i < stamp.length; i++) {
2649                 if (stamp[i] == min) {
2650                     stamp[i] = newStamp;


2735 
2736         // Write out the ZoneInfo object
2737         // 4802409: we write out even if it is null, a temporary workaround
2738         // the real fix for bug 4844924 in corba-iiop
2739         stream.writeObject(savedZone);
2740         if (savedZone != null) {
2741             zone = savedZone;
2742         }
2743     }
2744 
2745     private static class CalendarAccessControlContext {
2746         private static final AccessControlContext INSTANCE;
2747         static {
2748             RuntimePermission perm = new RuntimePermission("accessClassInPackage.sun.util.calendar");
2749             PermissionCollection perms = perm.newPermissionCollection();
2750             perms.add(perm);
2751             INSTANCE = new AccessControlContext(new ProtectionDomain[] {
2752                                                     new ProtectionDomain(null, perms)
2753                                                 });
2754         }

2755     }

2756 
2757     /**
2758      * Reconstitutes this object from a stream (i.e., deserialize it).
2759      */
2760     private void readObject(ObjectInputStream stream)
2761          throws IOException, ClassNotFoundException
2762     {
2763         final ObjectInputStream input = stream;
2764         input.defaultReadObject();
2765 
2766         stamp = new int[FIELD_COUNT];
2767 
2768         // Starting with version 2 (not implemented yet), we expect that
2769         // fields[], isSet[], isTimeSet, and areFieldsSet may not be
2770         // streamed out anymore.  We expect 'time' to be correct.
2771         if (serialVersionOnStream >= 2)
2772         {
2773             isTimeSet = true;
2774             if (fields == null) fields = new int[FIELD_COUNT];
2775             if (isSet == null) isSet = new boolean[FIELD_COUNT];
2776         }




2777         else if (serialVersionOnStream >= 0)
2778         {
2779             for (int i=0; i<FIELD_COUNT; ++i)
2780                 stamp[i] = isSet[i] ? COMPUTED : UNSET;
2781         }

2782 
2783         serialVersionOnStream = currentSerialVersion;
2784 
2785         // If there's a ZoneInfo object, use it for zone.
2786         ZoneInfo zi = null;
2787         try {
2788             zi = AccessController.doPrivileged(
2789                     new PrivilegedExceptionAction<ZoneInfo>() {

2790                         public ZoneInfo run() throws Exception {
2791                             return (ZoneInfo) input.readObject();
2792                         }
2793                     },
2794                     CalendarAccessControlContext.INSTANCE);
2795         } catch (PrivilegedActionException pae) {
2796             Exception e = pae.getException();
2797             if (!(e instanceof OptionalDataException)) {
2798                 if (e instanceof RuntimeException) {
2799                     throw (RuntimeException) e;
2800                 } else if (e instanceof IOException) {
2801                     throw (IOException) e;
2802                 } else if (e instanceof ClassNotFoundException) {
2803                     throw (ClassNotFoundException) e;
2804                 }
2805                 throw new RuntimeException(e);
2806             }
2807         }
2808         if (zi != null) {
2809             zone = zi;


  36  *
  37  */
  38 
  39 package java.util;
  40 
  41 import java.io.IOException;
  42 import java.io.ObjectInputStream;
  43 import java.io.ObjectOutputStream;
  44 import java.io.OptionalDataException;
  45 import java.io.Serializable;
  46 import java.security.AccessControlContext;
  47 import java.security.AccessController;
  48 import java.security.PermissionCollection;
  49 import java.security.PrivilegedActionException;
  50 import java.security.PrivilegedExceptionAction;
  51 import java.security.ProtectionDomain;
  52 import java.text.DateFormat;
  53 import java.text.DateFormatSymbols;
  54 import java.util.concurrent.ConcurrentHashMap;
  55 import java.util.concurrent.ConcurrentMap;
  56 import java.util.spi.CalendarDataProvider;
  57 import sun.util.BuddhistCalendar;
  58 import sun.util.locale.provider.LocaleProviderAdapter;
  59 import sun.util.calendar.ZoneInfo;
  60 import sun.util.locale.provider.CalendarDataUtility;
  61 
  62 /**
  63  * The <code>Calendar</code> class is an abstract class that provides methods
  64  * for converting between a specific instant in time and a set of {@link
  65  * #fields calendar fields} such as <code>YEAR</code>, <code>MONTH</code>,
  66  * <code>DAY_OF_MONTH</code>, <code>HOUR</code>, and so on, and for
  67  * manipulating the calendar fields, such as getting the date of the next
  68  * week. An instant in time can be represented by a millisecond value that is
  69  * an offset from the <a name="Epoch"><em>Epoch</em></a>, January 1, 1970
  70  * 00:00:00.000 GMT (Gregorian).
  71  *
  72  * <p>The class also provides additional fields and methods for
  73  * implementing a concrete calendar system outside the package. Those
  74  * fields and methods are defined as <code>protected</code>.
  75  *
  76  * <p>
  77  * Like other locale-sensitive classes, <code>Calendar</code> provides a
  78  * class method, <code>getInstance</code>, for getting a generally useful
  79  * object of this type. <code>Calendar</code>'s <code>getInstance</code> method
  80  * returns a <code>Calendar</code> object whose


 692      */
 693     public final static int UNDECIMBER = 12;
 694 
 695     /**
 696      * Value of the {@link #AM_PM} field indicating the
 697      * period of the day from midnight to just before noon.
 698      */
 699     public final static int AM = 0;
 700 
 701     /**
 702      * Value of the {@link #AM_PM} field indicating the
 703      * period of the day from noon to just before midnight.
 704      */
 705     public final static int PM = 1;
 706 
 707     /**
 708      * A style specifier for {@link #getDisplayNames(int, int, Locale)
 709      * getDisplayNames} indicating names in all styles, such as
 710      * "January" and "Jan".
 711      *
 712      * @see #SHORT_FORMAT
 713      * @see #LONG_FORMAT
 714      * @see #SHORT_STANDALONE
 715      * @see #LONG_STANDALONE
 716      * @see #SHORT
 717      * @see #LONG
 718      * @since 1.6
 719      */
 720     public static final int ALL_STYLES = 0;
 721 
 722     static final int STANDALONE_MASK = 0x8000;
 723 
 724     /**
 725      * A style specifier for {@link #getDisplayName(int, int, Locale)
 726      * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
 727      * getDisplayNames} equivalent to {@link #SHORT_FORMAT}.
 728      *
 729      * @see #SHORT_STANDALONE
 730      * @see #LONG
 731      * @since 1.6
 732      */
 733     public static final int SHORT = 1;
 734 
 735     /**
 736      * A style specifier for {@link #getDisplayName(int, int, Locale)
 737      * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
 738      * getDisplayNames} equivalent to {@link #LONG_FORMAT}.
 739      *
 740      * @see #LONG_STANDALONE
 741      * @see #SHORT
 742      * @since 1.6
 743      */
 744     public static final int LONG = 2;
 745 
 746     /**
 747      * A style specifier for {@link #getDisplayName(int, int, Locale)
 748      * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
 749      * getDisplayNames} indicating a short name used for format.
 750      *
 751      * @see #SHORT_STANDALONE
 752      * @see #LONG_FORMAT
 753      * @see #LONG_STANDALONE
 754      * @since 1.8
 755      */
 756     public static final int SHORT_FORMAT = 1;
 757 
 758     /**
 759      * A style specifier for {@link #getDisplayName(int, int, Locale)
 760      * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
 761      * getDisplayNames} indicating a long name used for format.
 762      *
 763      * @see #LONG_STANDALONE
 764      * @see #SHORT_FORMAT
 765      * @see #SHORT_STANDALONE
 766      * @since 1.8
 767      */
 768     public static final int LONG_FORMAT = 2;
 769 
 770     /**
 771      * A style specifier for {@link #getDisplayName(int, int, Locale)
 772      * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
 773      * getDisplayNames} indicating a short name used independently,
 774      * such as a month abbreviation as calendar headers.
 775      *
 776      * @see #SHORT_FORMAT
 777      * @see #LONG_FORMAT
 778      * @see #LONG_STANDALONE
 779      * @since 1.8
 780      */
 781     public static final int SHORT_STANDALONE = SHORT | STANDALONE_MASK;
 782 
 783     /**
 784      * A style specifier for {@link #getDisplayName(int, int, Locale)
 785      * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
 786      * getDisplayNames} indicating a long name used independently,
 787      * such as a month name as calendar headers.
 788      *
 789      * @see #LONG_FORMAT
 790      * @see #SHORT_FORMAT
 791      * @see #SHORT_STANDALONE
 792      * @since 1.8
 793      */
 794     public static final int LONG_STANDALONE = LONG | STANDALONE_MASK;
 795 
 796     // Internal notes:
 797     // Calendar contains two kinds of time representations: current "time" in
 798     // milliseconds, and a set of calendar "fields" representing the current time.
 799     // The two representations are usually in sync, but can get out of sync
 800     // as follows.
 801     // 1. Initially, no fields are set, and the time is invalid.
 802     // 2. If the time is set, all fields are computed and in sync.
 803     // 3. If a single field is set, the time is invalid.
 804     // Recomputation of the time and fields happens when the object needs
 805     // to return a result to the user, or use a result for a computation.
 806 
 807     /**
 808      * The calendar field values for the currently set time for this calendar.
 809      * This is an array of <code>FIELD_COUNT</code> integers, with index values
 810      * <code>ERA</code> through <code>DST_OFFSET</code>.
 811      * @serial
 812      */
 813     @SuppressWarnings("ProtectedField")
 814     protected int           fields[];
 815 
 816     /**
 817      * The flags which tell if a specified calendar field for the calendar is set.
 818      * A new object has no fields set.  After the first call to a method
 819      * which generates the fields, they all remain set after that.
 820      * This is an array of <code>FIELD_COUNT</code> booleans, with index values
 821      * <code>ERA</code> through <code>DST_OFFSET</code>.
 822      * @serial
 823      */
 824     @SuppressWarnings("ProtectedField")
 825     protected boolean       isSet[];
 826 
 827     /**
 828      * Pseudo-time-stamps which specify when each field was set. There
 829      * are two special values, UNSET and COMPUTED. Values from
 830      * MINIMUM_USER_SET to Integer.MAX_VALUE are legal user set values.
 831      */
 832     transient private int   stamp[];
 833 
 834     /**
 835      * The currently set time for this calendar, expressed in milliseconds after
 836      * January 1, 1970, 0:00:00 GMT.
 837      * @see #isTimeSet
 838      * @serial
 839      */
 840     @SuppressWarnings("ProtectedField")
 841     protected long          time;
 842 
 843     /**
 844      * True if then the value of <code>time</code> is valid.
 845      * The time is made invalid by a change to an item of <code>field[]</code>.
 846      * @see #time
 847      * @serial
 848      */
 849     @SuppressWarnings("ProtectedField")
 850     protected boolean       isTimeSet;
 851 
 852     /**
 853      * True if <code>fields[]</code> are in sync with the currently set time.
 854      * If false, then the next attempt to get the value of a field will
 855      * force a recomputation of all fields from the current value of
 856      * <code>time</code>.
 857      * @serial
 858      */
 859     @SuppressWarnings("ProtectedField")
 860     protected boolean       areFieldsSet;
 861 
 862     /**
 863      * True if all fields have been set.
 864      * @serial
 865      */
 866     transient boolean       areAllFieldsSet;
 867 
 868     /**
 869      * <code>True</code> if this calendar allows out-of-range field values during computation
 870      * of <code>time</code> from <code>fields[]</code>.
 871      * @see #setLenient
 872      * @see #isLenient
 873      * @serial
 874      */
 875     private boolean         lenient = true;
 876 
 877     /**
 878      * The <code>TimeZone</code> used by this calendar. <code>Calendar</code>
 879      * uses the time zone data to translate between locale and GMT time.


 958      * </dd>
 959      * <dt><b>1</b></dt>
 960      * <dd>
 961      * JDK 1.1.6 or later.  Writes a correct 'time' value
 962      * as well as compatible values for other fields.  This is a
 963      * transitional format.
 964      * </dd>
 965      * </dl>
 966      * When streaming out this class, the most recent format
 967      * and the highest allowable <code>serialVersionOnStream</code>
 968      * is written.
 969      * @serial
 970      * @since JDK1.1.6
 971      */
 972     private int             serialVersionOnStream = currentSerialVersion;
 973 
 974     // Proclaim serialization compatibility with JDK 1.1
 975     static final long       serialVersionUID = -1807547505821590642L;
 976 
 977     // Mask values for calendar fields
 978     @SuppressWarnings("PointlessBitwiseExpression")
 979     final static int ERA_MASK           = (1 << ERA);
 980     final static int YEAR_MASK          = (1 << YEAR);
 981     final static int MONTH_MASK         = (1 << MONTH);
 982     final static int WEEK_OF_YEAR_MASK  = (1 << WEEK_OF_YEAR);
 983     final static int WEEK_OF_MONTH_MASK = (1 << WEEK_OF_MONTH);
 984     final static int DAY_OF_MONTH_MASK  = (1 << DAY_OF_MONTH);
 985     final static int DATE_MASK          = DAY_OF_MONTH_MASK;
 986     final static int DAY_OF_YEAR_MASK   = (1 << DAY_OF_YEAR);
 987     final static int DAY_OF_WEEK_MASK   = (1 << DAY_OF_WEEK);
 988     final static int DAY_OF_WEEK_IN_MONTH_MASK  = (1 << DAY_OF_WEEK_IN_MONTH);
 989     final static int AM_PM_MASK         = (1 << AM_PM);
 990     final static int HOUR_MASK          = (1 << HOUR);
 991     final static int HOUR_OF_DAY_MASK   = (1 << HOUR_OF_DAY);
 992     final static int MINUTE_MASK        = (1 << MINUTE);
 993     final static int SECOND_MASK        = (1 << SECOND);
 994     final static int MILLISECOND_MASK   = (1 << MILLISECOND);
 995     final static int ZONE_OFFSET_MASK   = (1 << ZONE_OFFSET);
 996     final static int DST_OFFSET_MASK    = (1 << DST_OFFSET);
 997 
 998     /**


1067     /**
1068      * Gets a calendar with the specified time zone and locale.
1069      * The <code>Calendar</code> returned is based on the current time
1070      * in the given time zone with the given locale.
1071      *
1072      * @param zone the time zone to use
1073      * @param aLocale the locale for the week data
1074      * @return a Calendar.
1075      */
1076     public static Calendar getInstance(TimeZone zone,
1077                                        Locale aLocale)
1078     {
1079         return createCalendar(zone, aLocale);
1080     }
1081 
1082     private static Calendar createCalendar(TimeZone zone,
1083                                            Locale aLocale)
1084     {
1085         Calendar cal = null;
1086 
1087         if (aLocale.hasExtensions()) {
1088         String caltype = aLocale.getUnicodeLocaleType("ca");
1089             if (caltype != null) {
1090                 switch (caltype) {
1091                 case "buddhist":



1092                 cal = new BuddhistCalendar(zone, aLocale);
1093                     break;
1094                 case "japanese":
1095                     cal = new JapaneseImperialCalendar(zone, aLocale);
1096                     break;
1097                 case "gregory":
1098                     cal = new GregorianCalendar(zone, aLocale);
1099                     break;
1100                 }
1101             }
1102         }
1103         if (cal == null) {
1104             // If no known calendar type is explicitly specified,
1105             // perform the traditional way to create a Calendar:
1106             // create a BuddhistCalendar for th_TH locale,
1107             // a JapaneseImperialCalendar for ja_JP_JP locale, or
1108             // a GregorianCalendar for any other locales.
1109             // NOTE: The language, country and variant strings are interned.
1110             if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
1111                 cal = new BuddhistCalendar(zone, aLocale);
1112             } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
1113                        && aLocale.getCountry() == "JP") {
1114                 cal = new JapaneseImperialCalendar(zone, aLocale);
1115             } else {


1116                 cal = new GregorianCalendar(zone, aLocale);
1117             }
1118         }
1119         return cal;
1120     }
1121 
1122     /**
1123      * Returns an array of all locales for which the <code>getInstance</code>
1124      * methods of this class can return localized instances.
1125      * The array returned must contain at least a <code>Locale</code>
1126      * instance equal to {@link java.util.Locale#US Locale.US}.
1127      *
1128      * @return An array of locales for which localized
1129      *         <code>Calendar</code> instances are available.
1130      */
1131     public static synchronized Locale[] getAvailableLocales()
1132     {
1133         return DateFormat.getAvailableLocales();
1134     }
1135 
1136     /**
1137      * Converts the current calendar field values in {@link #fields fields[]}
1138      * to the millisecond time value


1453      * {@link Calendar#get(int) get(field)} to get the calendar
1454      * <code>field</code> value if the string representation is
1455      * applicable to the given calendar <code>field</code>.
1456      *
1457      * <p>For example, if this <code>Calendar</code> is a
1458      * <code>GregorianCalendar</code> and its date is 2005-01-01, then
1459      * the string representation of the {@link #MONTH} field would be
1460      * "January" in the long style in an English locale or "Jan" in
1461      * the short style. However, no string representation would be
1462      * available for the {@link #DAY_OF_MONTH} field, and this method
1463      * would return <code>null</code>.
1464      *
1465      * <p>The default implementation supports the calendar fields for
1466      * which a {@link DateFormatSymbols} has names in the given
1467      * <code>locale</code>.
1468      *
1469      * @param field
1470      *        the calendar field for which the string representation
1471      *        is returned
1472      * @param style
1473      *        the style applied to the string representation; one of {@link
1474      *        #SHORT_FORMAT} ({@link #SHORT}), {@link #SHORT_STANDALONE},
1475      *        {@link #LONG_FORMAT} ({@link #LONG}) or {@link #LONG_STANDALONE}.
1476      * @param locale
1477      *        the locale for the string representation
1478      *        (any calendar types specified by {@code locale} are ignored)
1479      * @return the string representation of the given
1480      *        <code>field</code> in the given <code>style</code>, or
1481      *        <code>null</code> if no string representation is
1482      *        applicable.
1483      * @exception IllegalArgumentException
1484      *        if <code>field</code> or <code>style</code> is invalid,
1485      *        or if this <code>Calendar</code> is non-lenient and any
1486      *        of the calendar fields have invalid values
1487      * @exception NullPointerException
1488      *        if <code>locale</code> is null
1489      * @since 1.6
1490      */
1491     public String getDisplayName(int field, int style, Locale locale) {
1492         if (!checkDisplayNameParams(field, style, SHORT, LONG, locale,
1493                             ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
1494             return null;
1495         }
1496 
1497         // the standalone styles are supported only through CalendarDataProviders.
1498         if (isStandaloneStyle(style)) {
1499             return CalendarDataUtility.retrieveFieldValueName(getCalendarType(),
1500                                                               field, get(field),
1501                                                               style, locale);
1502         }
1503 
1504         DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale);
1505         String[] strings = getFieldStrings(field, style, symbols);
1506         if (strings != null) {
1507             int fieldValue = get(field);
1508             if (fieldValue < strings.length) {
1509                 return strings[fieldValue];
1510             }
1511         }
1512         return null;
1513     }
1514 
1515     /**
1516      * Returns a <code>Map</code> containing all names of the calendar
1517      * <code>field</code> in the given <code>style</code> and
1518      * <code>locale</code> and their corresponding field values. For
1519      * example, if this <code>Calendar</code> is a {@link
1520      * GregorianCalendar}, the returned map would contain "Jan" to
1521      * {@link #JANUARY}, "Feb" to {@link #FEBRUARY}, and so on, in the
1522      * {@linkplain #SHORT short} style in an English locale.
1523      *
1524      * <p>The values of other calendar fields may be taken into
1525      * account to determine a set of display names. For example, if
1526      * this <code>Calendar</code> is a lunisolar calendar system and
1527      * the year value given by the {@link #YEAR} field has a leap
1528      * month, this method would return month names containing the leap
1529      * month name, and month names are mapped to their values specific
1530      * for the year.
1531      *
1532      * <p>The default implementation supports display names contained in
1533      * a {@link DateFormatSymbols}. For example, if <code>field</code>
1534      * is {@link #MONTH} and <code>style</code> is {@link
1535      * #ALL_STYLES}, this method returns a <code>Map</code> containing
1536      * all strings returned by {@link DateFormatSymbols#getShortMonths()}
1537      * and {@link DateFormatSymbols#getMonths()}.
1538      *
1539      * @param field
1540      *        the calendar field for which the display names are returned
1541      * @param style
1542      *        the style applied to the string representation; one of {@link
1543      *        #SHORT_FORMAT} ({@link #SHORT}), {@link #SHORT_STANDALONE},
1544      *        {@link #LONG_FORMAT} ({@link #LONG}) or {@link #LONG_STANDALONE}.
1545      * @param locale
1546      *        the locale for the display names
1547      * @return a <code>Map</code> containing all display names in
1548      *        <code>style</code> and <code>locale</code> and their
1549      *        field values, or <code>null</code> if no display names
1550      *        are defined for <code>field</code>
1551      * @exception IllegalArgumentException
1552      *        if <code>field</code> or <code>style</code> is invalid,
1553      *        or if this <code>Calendar</code> is non-lenient and any
1554      *        of the calendar fields have invalid values
1555      * @exception NullPointerException
1556      *        if <code>locale</code> is null
1557      * @since 1.6
1558      */
1559     public Map<String, Integer> getDisplayNames(int field, int style, Locale locale) {
1560         if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale,
1561                                     ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
1562             return null;
1563         }
1564         if (style == ALL_STYLES || isStandaloneStyle(style)) {
1565             return CalendarDataUtility.retrieveFieldValueNames(getCalendarType(), field, style, locale);




1566         }










1567         // SHORT or LONG
1568         return getDisplayNamesImpl(field, style, locale);
1569     }
1570 
1571     private Map<String,Integer> getDisplayNamesImpl(int field, int style, Locale locale) {
1572         DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale);
1573         String[] strings = getFieldStrings(field, style, symbols);
1574         if (strings != null) {
1575             Map<String,Integer> names = new HashMap<>();
1576             for (int i = 0; i < strings.length; i++) {
1577                 if (strings[i].length() == 0) {
1578                     continue;
1579                 }
1580                 names.put(strings[i], i);
1581             }
1582             return names;
1583         }
1584         return null;
1585     }
1586 
1587     boolean checkDisplayNameParams(int field, int style, int minStyle, int maxStyle,
1588                                    Locale locale, int fieldMask) {
1589         int baseStyle = getBaseStyle(style); // Ignore the standalone mask
1590         if (field < 0 || field >= fields.length ||
1591             baseStyle < minStyle || baseStyle > maxStyle) {
1592             throw new IllegalArgumentException();
1593         }
1594         if (locale == null) {
1595             throw new NullPointerException();
1596         }
1597         return isFieldSet(fieldMask, field);
1598     }
1599 
1600     private String[] getFieldStrings(int field, int style, DateFormatSymbols symbols) {
1601         int baseStyle = getBaseStyle(style); // ignore the standalone mask
1602         String[] strings = null;
1603         switch (field) {
1604         case ERA:
1605             strings = symbols.getEras();
1606             break;
1607 
1608         case MONTH:
1609             strings = (baseStyle == LONG) ? symbols.getMonths() : symbols.getShortMonths();
1610             break;
1611 
1612         case DAY_OF_WEEK:
1613             strings = (baseStyle == LONG) ? symbols.getWeekdays() : symbols.getShortWeekdays();
1614             break;
1615 
1616         case AM_PM:
1617             strings = symbols.getAmPmStrings();
1618             break;
1619         }
1620         return strings;
1621     }
1622 
1623     /**
1624      * Fills in any unset fields in the calendar fields. First, the {@link
1625      * #computeTime()} method is called if the time value (millisecond offset
1626      * from the <a href="#Epoch">Epoch</a>) has not been calculated from
1627      * calendar field values. Then, the {@link #computeFields()} method is
1628      * called to calculate all calendar field values.
1629      */
1630     protected void complete()
1631     {
1632         if (!isTimeSet) {
1633             updateTime();
1634         }
1635         if (!areFieldsSet || !areAllFieldsSet) {
1636             computeFields(); // fills in unset fields
1637             areAllFieldsSet = areFieldsSet = true;
1638         }
1639     }
1640 
1641     /**
1642      * Returns whether the value of the specified calendar field has been set
1643      * externally by calling one of the setter methods rather than by the
1644      * internal time calculation.
1645      *
1646      * @return <code>true</code> if the field has been set externally,
1647      * <code>false</code> otherwise.
1648      * @exception IndexOutOfBoundsException if the specified
1649      *                <code>field</code> is out of range
1650      *               (<code>field &lt; 0 || field &gt;= FIELD_COUNT</code>).
1651      * @see #selectFields()
1652      * @see #setFieldsComputed(int)
1653      */
1654     final boolean isExternallySet(int field) {


1748 
1749     /**
1750      * Returns whether the calendar fields are fully in sync with the time
1751      * value.
1752      */
1753     final boolean isFullyNormalized() {
1754         return areFieldsSet && areAllFieldsSet;
1755     }
1756 
1757     /**
1758      * Marks this Calendar as not sync'd.
1759      */
1760     final void setUnnormalized() {
1761         areFieldsSet = areAllFieldsSet = false;
1762     }
1763 
1764     /**
1765      * Returns whether the specified <code>field</code> is on in the
1766      * <code>fieldMask</code>.
1767      */
1768     static boolean isFieldSet(int fieldMask, int field) {
1769         return (fieldMask & (1 << field)) != 0;
1770     }
1771 
1772     /**
1773      * Returns a field mask indicating which calendar field values
1774      * to be used to calculate the time value. The calendar fields are
1775      * returned as a bit mask, each bit of which corresponds to a field, i.e.,
1776      * the mask value of <code>field</code> is <code>(1 &lt;&lt;
1777      * field)</code>. For example, 0x26 represents the <code>YEAR</code>,
1778      * <code>MONTH</code>, and <code>DAY_OF_MONTH</code> fields (i.e., 0x26 is
1779      * equal to
1780      * <code>(1&lt;&lt;YEAR)|(1&lt;&lt;MONTH)|(1&lt;&lt;DAY_OF_MONTH))</code>.
1781      *
1782      * <p>This method supports the calendar fields resolution as described in
1783      * the class description. If the bit mask for a given field is on and its
1784      * field has not been set (i.e., <code>isSet(field)</code> is
1785      * <code>false</code>), then the default value of the field has to be
1786      * used, which case means that the field has been selected because the
1787      * selected combination involves the field.
1788      *


1924         }
1925         if (stamp[MINUTE] != UNSET) {
1926             fieldMask |= MINUTE_MASK;
1927         }
1928         if (stamp[SECOND] != UNSET) {
1929             fieldMask |= SECOND_MASK;
1930         }
1931         if (stamp[MILLISECOND] != UNSET) {
1932             fieldMask |= MILLISECOND_MASK;
1933         }
1934         if (stamp[ZONE_OFFSET] >= MINIMUM_USER_STAMP) {
1935                 fieldMask |= ZONE_OFFSET_MASK;
1936         }
1937         if (stamp[DST_OFFSET] >= MINIMUM_USER_STAMP) {
1938             fieldMask |= DST_OFFSET_MASK;
1939         }
1940 
1941         return fieldMask;
1942     }
1943 
1944     int getBaseStyle(int style) {
1945         return style & ~STANDALONE_MASK;
1946     }
1947 
1948     boolean isStandaloneStyle(int style) {
1949         return (style & STANDALONE_MASK) != 0;
1950     }
1951 
1952     /**
1953      * Returns the pseudo-time-stamp for two fields, given their
1954      * individual pseudo-time-stamps.  If either of the fields
1955      * is unset, then the aggregate is unset.  Otherwise, the
1956      * aggregate is the later of the two stamps.
1957      */
1958     private static int aggregateStamp(int stamp_a, int stamp_b) {
1959         if (stamp_a == UNSET || stamp_b == UNSET) {
1960             return UNSET;
1961         }
1962         return (stamp_a > stamp_b) ? stamp_a : stamp_b;
1963     }
1964 
1965     /**
1966      * Returns the calendar type of this {@code Calendar}. Calendar types are
1967      * defined by the <em>Unicode Locale Data Markup Language (LDML)</em>
1968      * specification.
1969      *
1970      * <p>The default implementation of this method returns the class name of
1971      * this {@code Calendar} instance. Any subclasses that implement
1972      * LDML-defined calendar systems should override this method to return
1973      * appropriate calendar types.
1974      *
1975      * @return the LDML-defined calendar type or the class name of this
1976      *         {@code Calendar} instance
1977      * @since 1.8
1978      * @see <a href="Locale.html#def_extensions">Locale extensions</a>
1979      * @see Locale.Builder#setLocale(Locale)
1980      * @see Locale.Builder#setUnicodeLocaleKeyword(String, String)
1981      */
1982     public String getCalendarType() {
1983         return this.getClass().getName();
1984     }
1985 
1986     /**
1987      * Compares this <code>Calendar</code> to the specified
1988      * <code>Object</code>.  The result is <code>true</code> if and only if
1989      * the argument is a <code>Calendar</code> object of the same calendar
1990      * system that represents the same time value (millisecond offset from the
1991      * <a href="#Epoch">Epoch</a>) under the same
1992      * <code>Calendar</code> parameters as this object.
1993      *
1994      * <p>The <code>Calendar</code> parameters are the values represented
1995      * by the <code>isLenient</code>, <code>getFirstDayOfWeek</code>,
1996      * <code>getMinimalDaysInFirstWeek</code> and <code>getTimeZone</code>
1997      * methods. If there is any difference in those parameters
1998      * between the two <code>Calendar</code>s, this method returns
1999      * <code>false</code>.
2000      *
2001      * <p>Use the {@link #compareTo(Calendar) compareTo} method to
2002      * compare only the time values.
2003      *
2004      * @param obj the object to compare with.
2005      * @return <code>true</code> if this object is equal to <code>obj</code>;
2006      * <code>false</code> otherwise.
2007      */
2008     @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
2009     @Override
2010     public boolean equals(Object obj) {
2011         if (this == obj) {
2012             return true;
2013         }
2014         try {
2015             Calendar that = (Calendar)obj;
2016             return compareTo(getMillisOf(that)) == 0 &&
2017                 lenient == that.lenient &&
2018                 firstDayOfWeek == that.firstDayOfWeek &&
2019                 minimalDaysInFirstWeek == that.minimalDaysInFirstWeek &&
2020                 zone.equals(that.zone);
2021         } catch (Exception e) {
2022             // Note: GregorianCalendar.computeTime throws
2023             // IllegalArgumentException if the ERA value is invalid
2024             // even it's in lenient mode.
2025         }
2026         return false;
2027     }
2028 
2029     /**
2030      * Returns a hash code for this calendar.
2031      *
2032      * @return a hash code value for this object.
2033      * @since 1.2
2034      */
2035     @Override
2036     public int hashCode() {
2037         // 'otheritems' represents the hash code for the previous versions.
2038         int otheritems = (lenient ? 1 : 0)
2039             | (firstDayOfWeek << 1)
2040             | (minimalDaysInFirstWeek << 4)
2041             | (zone.hashCode() << 7);
2042         long t = getMillisOf(this);
2043         return (int) t ^ (int)(t >> 32) ^ otheritems;
2044     }
2045 
2046     /**
2047      * Returns whether this <code>Calendar</code> represents a time
2048      * before the time represented by the specified
2049      * <code>Object</code>. This method is equivalent to:
2050      * <pre><blockquote>
2051      *         compareTo(when) < 0
2052      * </blockquote></pre>
2053      * if and only if <code>when</code> is a <code>Calendar</code>
2054      * instance. Otherwise, the method returns <code>false</code>.
2055      *


2087 
2088     /**
2089      * Compares the time values (millisecond offsets from the <a
2090      * href="#Epoch">Epoch</a>) represented by two
2091      * <code>Calendar</code> objects.
2092      *
2093      * @param anotherCalendar the <code>Calendar</code> to be compared.
2094      * @return the value <code>0</code> if the time represented by the argument
2095      * is equal to the time represented by this <code>Calendar</code>; a value
2096      * less than <code>0</code> if the time of this <code>Calendar</code> is
2097      * before the time represented by the argument; and a value greater than
2098      * <code>0</code> if the time of this <code>Calendar</code> is after the
2099      * time represented by the argument.
2100      * @exception NullPointerException if the specified <code>Calendar</code> is
2101      *            <code>null</code>.
2102      * @exception IllegalArgumentException if the time value of the
2103      * specified <code>Calendar</code> object can't be obtained due to
2104      * any invalid calendar values.
2105      * @since   1.5
2106      */
2107     @Override
2108     public int compareTo(Calendar anotherCalendar) {
2109         return compareTo(getMillisOf(anotherCalendar));
2110     }
2111 
2112     /**
2113      * Adds or subtracts the specified amount of time to the given calendar field,
2114      * based on the calendar's rules. For example, to subtract 5 days from
2115      * the current time of the calendar, you can achieve it by calling:
2116      * <p><code>add(Calendar.DAY_OF_MONTH, -5)</code>.
2117      *
2118      * @param field the calendar field.
2119      * @param amount the amount of date or time to be added to the field.
2120      * @see #roll(int,int)
2121      * @see #set(int,int)
2122      */
2123     abstract public void add(int field, int amount);
2124 
2125     /**
2126      * Adds or subtracts (up/down) a single unit of time on the given time
2127      * field without changing larger fields. For example, to roll the current


2561      * @see #getLeastMaximum(int)
2562      * @see #getActualMinimum(int)
2563      * @since 1.2
2564      */
2565     public int getActualMaximum(int field) {
2566         int fieldValue = getLeastMaximum(field);
2567         int endValue = getMaximum(field);
2568 
2569         // if we know that the maximum value is always the same, just return it.
2570         if (fieldValue == endValue) {
2571             return fieldValue;
2572         }
2573 
2574         // clone the calendar so we don't mess with the real one, and set it to
2575         // accept anything for the field values.
2576         Calendar work = (Calendar)this.clone();
2577         work.setLenient(true);
2578 
2579         // if we're counting weeks, set the day of the week to Sunday.  We know the
2580         // last week of a month or year will contain the first day of the week.
2581         if (field == WEEK_OF_YEAR || field == WEEK_OF_MONTH) {
2582             work.set(DAY_OF_WEEK, firstDayOfWeek);
2583         }
2584 
2585         // now try each value from getLeastMaximum() to getMaximum() one by one until
2586         // we get a value that normalizes to another value.  The last value that
2587         // normalizes to itself is the actual maximum for the current date
2588         int result = fieldValue;
2589 
2590         do {
2591             work.set(field, fieldValue);
2592             if (work.get(field) != fieldValue) {
2593                 break;
2594             } else {
2595                 result = fieldValue;
2596                 fieldValue++;
2597             }
2598         } while (fieldValue <= endValue);
2599 
2600         return result;
2601     }
2602 
2603     /**
2604      * Creates and returns a copy of this object.
2605      *
2606      * @return a copy of this object.
2607      */
2608     @Override
2609     public Object clone()
2610     {
2611         try {
2612             Calendar other = (Calendar) super.clone();
2613 
2614             other.fields = new int[FIELD_COUNT];
2615             other.isSet = new boolean[FIELD_COUNT];
2616             other.stamp = new int[FIELD_COUNT];
2617             for (int i = 0; i < FIELD_COUNT; i++) {
2618                 other.fields[i] = fields[i];
2619                 other.stamp[i] = stamp[i];
2620                 other.isSet[i] = isSet[i];
2621             }
2622             other.zone = (TimeZone) zone.clone();
2623             return other;
2624         }
2625         catch (CloneNotSupportedException e) {
2626             // this shouldn't happen, since we are Cloneable
2627             throw new InternalError(e);
2628         }
2629     }
2630 
2631     private static final String[] FIELD_NAME = {
2632         "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH",
2633         "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR",
2634         "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",
2635         "DST_OFFSET"
2636     };
2637 
2638     /**
2639      * Returns the name of the specified calendar field.
2640      *
2641      * @param field the calendar field
2642      * @return the calendar field name
2643      * @exception IndexOutOfBoundsException if <code>field</code> is negative,
2644      * equal to or greater then <code>FIELD_COUNT</code>.
2645      */
2646     static String getFieldName(int field) {
2647         return FIELD_NAME[field];
2648     }
2649 
2650     /**
2651      * Return a string representation of this calendar. This method
2652      * is intended to be used only for debugging purposes, and the
2653      * format of the returned string may vary between implementations.
2654      * The returned string may be empty but may not be <code>null</code>.
2655      *
2656      * @return  a string representation of this calendar.
2657      */
2658     @Override
2659     public String toString() {
2660         // NOTE: BuddhistCalendar.toString() interprets the string
2661         // produced by this method so that the Gregorian year number
2662         // is substituted by its B.E. year value. It relies on
2663         // "...,YEAR=<year>,..." or "...,YEAR=?,...".
2664         StringBuilder buffer = new StringBuilder(800);
2665         buffer.append(getClass().getName()).append('[');
2666         appendValue(buffer, "time", isTimeSet, time);
2667         buffer.append(",areFieldsSet=").append(areFieldsSet);
2668         buffer.append(",areAllFieldsSet=").append(areAllFieldsSet);
2669         buffer.append(",lenient=").append(lenient);
2670         buffer.append(",zone=").append(zone);
2671         appendValue(buffer, ",firstDayOfWeek", true, (long) firstDayOfWeek);
2672         appendValue(buffer, ",minimalDaysInFirstWeek", true, (long) minimalDaysInFirstWeek);
2673         for (int i = 0; i < FIELD_COUNT; ++i) {
2674             buffer.append(',');
2675             appendValue(buffer, FIELD_NAME[i], isSet(i), (long) fields[i]);
2676         }
2677         buffer.append(']');
2678         return buffer.toString();
2679     }
2680 
2681     // =======================privates===============================
2682 
2683     private static void appendValue(StringBuilder sb, String item, boolean valid, long value) {
2684         sb.append(item).append('=');
2685         if (valid) {
2686             sb.append(value);
2687         } else {
2688             sb.append('?');
2689         }
2690     }
2691 
2692     /**
2693      * Both firstDayOfWeek and minimalDaysInFirstWeek are locale-dependent.
2694      * They are used to figure out the week count for a specific date for
2695      * a given locale. These must be set when a Calendar is constructed.
2696      * @param desiredLocale the given locale.
2697      */
2698     private void setWeekCountData(Locale desiredLocale)
2699     {
2700         /* try to get the Locale data from the cache */
2701         int[] data = cachedLocaleData.get(desiredLocale);
2702         if (data == null) {  /* cache miss */
2703             LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(CalendarDataProvider.class, desiredLocale);
2704             CalendarDataProvider provider = adapter.getCalendarDataProvider();
2705             data = new int[2];
2706             data[0] = provider.getFirstDayOfWeek(desiredLocale);
2707             data[1] = provider.getMinimalDaysInFirstWeek(desiredLocale);
2708             assert data[0] != 0 && data[1] != 0;
2709             cachedLocaleData.putIfAbsent(desiredLocale, data);
2710         }
2711         firstDayOfWeek = data[0];
2712         minimalDaysInFirstWeek = data[1];
2713     }
2714 
2715     /**
2716      * Recomputes the time and updates the status fields isTimeSet
2717      * and areFieldsSet.  Callers should check isTimeSet and only
2718      * call this method if isTimeSet is false.
2719      */
2720     private void updateTime() {
2721         computeTime();
2722         // The areFieldsSet and areAllFieldsSet values are no longer
2723         // controlled here (as of 1.5).
2724         isTimeSet = true;
2725     }
2726 
2727     private int compareTo(long t) {
2728         long thisTime = getMillisOf(this);
2729         return (thisTime > t) ? 1 : (thisTime == t) ? 0 : -1;
2730     }
2731 
2732     private static long getMillisOf(Calendar calendar) {
2733         if (calendar.isTimeSet) {
2734             return calendar.time;
2735         }
2736         Calendar cal = (Calendar) calendar.clone();
2737         cal.setLenient(true);
2738         return cal.getTimeInMillis();
2739     }
2740 
2741     /**
2742      * Adjusts the stamp[] values before nextStamp overflow. nextStamp
2743      * is set to the next stamp value upon the return.
2744      */
2745     private void adjustStamp() {
2746         int max = MINIMUM_USER_STAMP;
2747         int newStamp = MINIMUM_USER_STAMP;
2748 
2749         for (;;) {
2750             int min = Integer.MAX_VALUE;
2751             for (int i = 0; i < stamp.length; i++) {
2752                 int v = stamp[i];
2753                 if (v >= newStamp && min > v) {
2754                     min = v;
2755                 }
2756                 if (max < v) {
2757                     max = v;
2758                 }
2759             }
2760             if (max != min && min == Integer.MAX_VALUE) {
2761                 break;
2762             }
2763             for (int i = 0; i < stamp.length; i++) {
2764                 if (stamp[i] == min) {
2765                     stamp[i] = newStamp;


2850 
2851         // Write out the ZoneInfo object
2852         // 4802409: we write out even if it is null, a temporary workaround
2853         // the real fix for bug 4844924 in corba-iiop
2854         stream.writeObject(savedZone);
2855         if (savedZone != null) {
2856             zone = savedZone;
2857         }
2858     }
2859 
2860     private static class CalendarAccessControlContext {
2861         private static final AccessControlContext INSTANCE;
2862         static {
2863             RuntimePermission perm = new RuntimePermission("accessClassInPackage.sun.util.calendar");
2864             PermissionCollection perms = perm.newPermissionCollection();
2865             perms.add(perm);
2866             INSTANCE = new AccessControlContext(new ProtectionDomain[] {
2867                                                     new ProtectionDomain(null, perms)
2868                                                 });
2869         }
2870         private CalendarAccessControlContext() {
2871         }
2872     }
2873 
2874     /**
2875      * Reconstitutes this object from a stream (i.e., deserialize it).
2876      */
2877     private void readObject(ObjectInputStream stream)
2878          throws IOException, ClassNotFoundException
2879     {
2880         final ObjectInputStream input = stream;
2881         input.defaultReadObject();
2882 
2883         stamp = new int[FIELD_COUNT];
2884 
2885         // Starting with version 2 (not implemented yet), we expect that
2886         // fields[], isSet[], isTimeSet, and areFieldsSet may not be
2887         // streamed out anymore.  We expect 'time' to be correct.
2888         if (serialVersionOnStream >= 2)
2889         {
2890             isTimeSet = true;
2891             if (fields == null) {
2892                 fields = new int[FIELD_COUNT];
2893             }
2894             if (isSet == null) {
2895                 isSet = new boolean[FIELD_COUNT];
2896             }
2897         }
2898         else if (serialVersionOnStream >= 0)
2899         {
2900             for (int i=0; i<FIELD_COUNT; ++i) {
2901                 stamp[i] = isSet[i] ? COMPUTED : UNSET;
2902             }
2903         }
2904 
2905         serialVersionOnStream = currentSerialVersion;
2906 
2907         // If there's a ZoneInfo object, use it for zone.
2908         ZoneInfo zi = null;
2909         try {
2910             zi = AccessController.doPrivileged(
2911                     new PrivilegedExceptionAction<ZoneInfo>() {
2912                         @Override
2913                         public ZoneInfo run() throws Exception {
2914                             return (ZoneInfo) input.readObject();
2915                         }
2916                     },
2917                     CalendarAccessControlContext.INSTANCE);
2918         } catch (PrivilegedActionException pae) {
2919             Exception e = pae.getException();
2920             if (!(e instanceof OptionalDataException)) {
2921                 if (e instanceof RuntimeException) {
2922                     throw (RuntimeException) e;
2923                 } else if (e instanceof IOException) {
2924                     throw (IOException) e;
2925                 } else if (e instanceof ClassNotFoundException) {
2926                     throw (ClassNotFoundException) e;
2927                 }
2928                 throw new RuntimeException(e);
2929             }
2930         }
2931         if (zi != null) {
2932             zone = zi;