jdk/src/share/classes/java/util/Calendar.java
changeset 13583 dc0017b1a452
parent 12448 b95438b17098
child 14014 da3648e13e67
equal deleted inserted replaced
13582:16f0af616ea0 13583:dc0017b1a452
    51 import java.security.ProtectionDomain;
    51 import java.security.ProtectionDomain;
    52 import java.text.DateFormat;
    52 import java.text.DateFormat;
    53 import java.text.DateFormatSymbols;
    53 import java.text.DateFormatSymbols;
    54 import java.util.concurrent.ConcurrentHashMap;
    54 import java.util.concurrent.ConcurrentHashMap;
    55 import java.util.concurrent.ConcurrentMap;
    55 import java.util.concurrent.ConcurrentMap;
       
    56 import java.util.spi.CalendarDataProvider;
    56 import sun.util.BuddhistCalendar;
    57 import sun.util.BuddhistCalendar;
       
    58 import sun.util.locale.provider.LocaleProviderAdapter;
    57 import sun.util.calendar.ZoneInfo;
    59 import sun.util.calendar.ZoneInfo;
    58 import sun.util.resources.LocaleData;
    60 import sun.util.locale.provider.CalendarDataUtility;
    59 
    61 
    60 /**
    62 /**
    61  * The <code>Calendar</code> class is an abstract class that provides methods
    63  * 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
    64  * 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>,
    65  * #fields calendar fields} such as <code>YEAR</code>, <code>MONTH</code>,
   705     /**
   707     /**
   706      * A style specifier for {@link #getDisplayNames(int, int, Locale)
   708      * A style specifier for {@link #getDisplayNames(int, int, Locale)
   707      * getDisplayNames} indicating names in all styles, such as
   709      * getDisplayNames} indicating names in all styles, such as
   708      * "January" and "Jan".
   710      * "January" and "Jan".
   709      *
   711      *
       
   712      * @see #SHORT_FORMAT
       
   713      * @see #LONG_FORMAT
       
   714      * @see #SHORT_STANDALONE
       
   715      * @see #LONG_STANDALONE
   710      * @see #SHORT
   716      * @see #SHORT
   711      * @see #LONG
   717      * @see #LONG
   712      * @since 1.6
   718      * @since 1.6
   713      */
   719      */
   714     public static final int ALL_STYLES = 0;
   720     public static final int ALL_STYLES = 0;
   715 
   721 
       
   722     static final int STANDALONE_MASK = 0x8000;
       
   723 
   716     /**
   724     /**
   717      * A style specifier for {@link #getDisplayName(int, int, Locale)
   725      * A style specifier for {@link #getDisplayName(int, int, Locale)
   718      * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
   726      * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
   719      * getDisplayNames} indicating a short name, such as "Jan".
   727      * getDisplayNames} equivalent to {@link #SHORT_FORMAT}.
   720      *
   728      *
       
   729      * @see #SHORT_STANDALONE
   721      * @see #LONG
   730      * @see #LONG
   722      * @since 1.6
   731      * @since 1.6
   723      */
   732      */
   724     public static final int SHORT = 1;
   733     public static final int SHORT = 1;
   725 
   734 
   726     /**
   735     /**
   727      * A style specifier for {@link #getDisplayName(int, int, Locale)
   736      * A style specifier for {@link #getDisplayName(int, int, Locale)
   728      * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
   737      * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
   729      * getDisplayNames} indicating a long name, such as "January".
   738      * getDisplayNames} equivalent to {@link #LONG_FORMAT}.
   730      *
   739      *
       
   740      * @see #LONG_STANDALONE
   731      * @see #SHORT
   741      * @see #SHORT
   732      * @since 1.6
   742      * @since 1.6
   733      */
   743      */
   734     public static final int LONG = 2;
   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;
   735 
   795 
   736     // Internal notes:
   796     // Internal notes:
   737     // Calendar contains two kinds of time representations: current "time" in
   797     // Calendar contains two kinds of time representations: current "time" in
   738     // milliseconds, and a set of calendar "fields" representing the current time.
   798     // 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
   799     // The two representations are usually in sync, but can get out of sync
   748      * The calendar field values for the currently set time for this calendar.
   808      * 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
   809      * This is an array of <code>FIELD_COUNT</code> integers, with index values
   750      * <code>ERA</code> through <code>DST_OFFSET</code>.
   810      * <code>ERA</code> through <code>DST_OFFSET</code>.
   751      * @serial
   811      * @serial
   752      */
   812      */
       
   813     @SuppressWarnings("ProtectedField")
   753     protected int           fields[];
   814     protected int           fields[];
   754 
   815 
   755     /**
   816     /**
   756      * The flags which tell if a specified calendar field for the calendar is set.
   817      * 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
   818      * 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.
   819      * which generates the fields, they all remain set after that.
   759      * This is an array of <code>FIELD_COUNT</code> booleans, with index values
   820      * This is an array of <code>FIELD_COUNT</code> booleans, with index values
   760      * <code>ERA</code> through <code>DST_OFFSET</code>.
   821      * <code>ERA</code> through <code>DST_OFFSET</code>.
   761      * @serial
   822      * @serial
   762      */
   823      */
       
   824     @SuppressWarnings("ProtectedField")
   763     protected boolean       isSet[];
   825     protected boolean       isSet[];
   764 
   826 
   765     /**
   827     /**
   766      * Pseudo-time-stamps which specify when each field was set. There
   828      * Pseudo-time-stamps which specify when each field was set. There
   767      * are two special values, UNSET and COMPUTED. Values from
   829      * are two special values, UNSET and COMPUTED. Values from
   773      * The currently set time for this calendar, expressed in milliseconds after
   835      * The currently set time for this calendar, expressed in milliseconds after
   774      * January 1, 1970, 0:00:00 GMT.
   836      * January 1, 1970, 0:00:00 GMT.
   775      * @see #isTimeSet
   837      * @see #isTimeSet
   776      * @serial
   838      * @serial
   777      */
   839      */
       
   840     @SuppressWarnings("ProtectedField")
   778     protected long          time;
   841     protected long          time;
   779 
   842 
   780     /**
   843     /**
   781      * True if then the value of <code>time</code> is valid.
   844      * 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>.
   845      * The time is made invalid by a change to an item of <code>field[]</code>.
   783      * @see #time
   846      * @see #time
   784      * @serial
   847      * @serial
   785      */
   848      */
       
   849     @SuppressWarnings("ProtectedField")
   786     protected boolean       isTimeSet;
   850     protected boolean       isTimeSet;
   787 
   851 
   788     /**
   852     /**
   789      * True if <code>fields[]</code> are in sync with the currently set time.
   853      * 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
   854      * 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
   855      * force a recomputation of all fields from the current value of
   792      * <code>time</code>.
   856      * <code>time</code>.
   793      * @serial
   857      * @serial
   794      */
   858      */
       
   859     @SuppressWarnings("ProtectedField")
   795     protected boolean       areFieldsSet;
   860     protected boolean       areFieldsSet;
   796 
   861 
   797     /**
   862     /**
   798      * True if all fields have been set.
   863      * True if all fields have been set.
   799      * @serial
   864      * @serial
   908 
   973 
   909     // Proclaim serialization compatibility with JDK 1.1
   974     // Proclaim serialization compatibility with JDK 1.1
   910     static final long       serialVersionUID = -1807547505821590642L;
   975     static final long       serialVersionUID = -1807547505821590642L;
   911 
   976 
   912     // Mask values for calendar fields
   977     // Mask values for calendar fields
       
   978     @SuppressWarnings("PointlessBitwiseExpression")
   913     final static int ERA_MASK           = (1 << ERA);
   979     final static int ERA_MASK           = (1 << ERA);
   914     final static int YEAR_MASK          = (1 << YEAR);
   980     final static int YEAR_MASK          = (1 << YEAR);
   915     final static int MONTH_MASK         = (1 << MONTH);
   981     final static int MONTH_MASK         = (1 << MONTH);
   916     final static int WEEK_OF_YEAR_MASK  = (1 << WEEK_OF_YEAR);
   982     final static int WEEK_OF_YEAR_MASK  = (1 << WEEK_OF_YEAR);
   917     final static int WEEK_OF_MONTH_MASK = (1 << WEEK_OF_MONTH);
   983     final static int WEEK_OF_MONTH_MASK = (1 << WEEK_OF_MONTH);
  1016     private static Calendar createCalendar(TimeZone zone,
  1082     private static Calendar createCalendar(TimeZone zone,
  1017                                            Locale aLocale)
  1083                                            Locale aLocale)
  1018     {
  1084     {
  1019         Calendar cal = null;
  1085         Calendar cal = null;
  1020 
  1086 
       
  1087         if (aLocale.hasExtensions()) {
  1021         String caltype = aLocale.getUnicodeLocaleType("ca");
  1088         String caltype = aLocale.getUnicodeLocaleType("ca");
  1022         if (caltype == null) {
  1089             if (caltype != null) {
  1023             // Calendar type is not specified.
  1090                 switch (caltype) {
  1024             // If the specified locale is a Thai locale,
  1091                 case "buddhist":
  1025             // returns a BuddhistCalendar instance.
       
  1026             if ("th".equals(aLocale.getLanguage())
       
  1027                     && ("TH".equals(aLocale.getCountry()))) {
       
  1028                 cal = new BuddhistCalendar(zone, aLocale);
  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);
  1029             } else {
  1115             } else {
  1030                 cal = new GregorianCalendar(zone, aLocale);
  1116                 cal = new GregorianCalendar(zone, aLocale);
  1031             }
  1117             }
  1032         } else if (caltype.equals("japanese")) {
  1118         }
  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;
  1119         return cal;
  1043     }
  1120     }
  1044 
  1121 
  1045     /**
  1122     /**
  1046      * Returns an array of all locales for which the <code>getInstance</code>
  1123      * Returns an array of all locales for which the <code>getInstance</code>
  1391      *
  1468      *
  1392      * @param field
  1469      * @param field
  1393      *        the calendar field for which the string representation
  1470      *        the calendar field for which the string representation
  1394      *        is returned
  1471      *        is returned
  1395      * @param style
  1472      * @param style
  1396      *        the style applied to the string representation; one of
  1473      *        the style applied to the string representation; one of {@link
  1397      *        {@link #SHORT} or {@link #LONG}.
  1474      *        #SHORT_FORMAT} ({@link #SHORT}), {@link #SHORT_STANDALONE},
       
  1475      *        {@link #LONG_FORMAT} ({@link #LONG}) or {@link #LONG_STANDALONE}.
  1398      * @param locale
  1476      * @param locale
  1399      *        the locale for the string representation
  1477      *        the locale for the string representation
       
  1478      *        (any calendar types specified by {@code locale} are ignored)
  1400      * @return the string representation of the given
  1479      * @return the string representation of the given
  1401      *        <code>field</code> in the given <code>style</code>, or
  1480      *        <code>field</code> in the given <code>style</code>, or
  1402      *        <code>null</code> if no string representation is
  1481      *        <code>null</code> if no string representation is
  1403      *        applicable.
  1482      *        applicable.
  1404      * @exception IllegalArgumentException
  1483      * @exception IllegalArgumentException
  1408      * @exception NullPointerException
  1487      * @exception NullPointerException
  1409      *        if <code>locale</code> is null
  1488      *        if <code>locale</code> is null
  1410      * @since 1.6
  1489      * @since 1.6
  1411      */
  1490      */
  1412     public String getDisplayName(int field, int style, Locale locale) {
  1491     public String getDisplayName(int field, int style, Locale locale) {
  1413         if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale,
  1492         if (!checkDisplayNameParams(field, style, SHORT, LONG, locale,
  1414                                     ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
  1493                             ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
  1415             return null;
  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);
  1416         }
  1502         }
  1417 
  1503 
  1418         DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale);
  1504         DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale);
  1419         String[] strings = getFieldStrings(field, style, symbols);
  1505         String[] strings = getFieldStrings(field, style, symbols);
  1420         if (strings != null) {
  1506         if (strings != null) {
  1451      * and {@link DateFormatSymbols#getMonths()}.
  1537      * and {@link DateFormatSymbols#getMonths()}.
  1452      *
  1538      *
  1453      * @param field
  1539      * @param field
  1454      *        the calendar field for which the display names are returned
  1540      *        the calendar field for which the display names are returned
  1455      * @param style
  1541      * @param style
  1456      *        the style applied to the display names; one of {@link
  1542      *        the style applied to the string representation; one of {@link
  1457      *        #SHORT}, {@link #LONG}, or {@link #ALL_STYLES}.
  1543      *        #SHORT_FORMAT} ({@link #SHORT}), {@link #SHORT_STANDALONE},
       
  1544      *        {@link #LONG_FORMAT} ({@link #LONG}) or {@link #LONG_STANDALONE}.
  1458      * @param locale
  1545      * @param locale
  1459      *        the locale for the display names
  1546      *        the locale for the display names
  1460      * @return a <code>Map</code> containing all display names in
  1547      * @return a <code>Map</code> containing all display names in
  1461      *        <code>style</code> and <code>locale</code> and their
  1548      *        <code>style</code> and <code>locale</code> and their
  1462      *        field values, or <code>null</code> if no display names
  1549      *        field values, or <code>null</code> if no display names
  1472     public Map<String, Integer> getDisplayNames(int field, int style, Locale locale) {
  1559     public Map<String, Integer> getDisplayNames(int field, int style, Locale locale) {
  1473         if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale,
  1560         if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale,
  1474                                     ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
  1561                                     ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
  1475             return null;
  1562             return null;
  1476         }
  1563         }
  1477 
  1564         if (style == ALL_STYLES || isStandaloneStyle(style)) {
  1478         // ALL_STYLES
  1565             return CalendarDataUtility.retrieveFieldValueNames(getCalendarType(), field, style, locale);
  1479         if (style == ALL_STYLES) {
  1566         }
  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
  1567         // SHORT or LONG
  1495         return getDisplayNamesImpl(field, style, locale);
  1568         return getDisplayNamesImpl(field, style, locale);
  1496     }
  1569     }
  1497 
  1570 
  1498     private Map<String,Integer> getDisplayNamesImpl(int field, int style, Locale locale) {
  1571     private Map<String,Integer> getDisplayNamesImpl(int field, int style, Locale locale) {
  1511         return null;
  1584         return null;
  1512     }
  1585     }
  1513 
  1586 
  1514     boolean checkDisplayNameParams(int field, int style, int minStyle, int maxStyle,
  1587     boolean checkDisplayNameParams(int field, int style, int minStyle, int maxStyle,
  1515                                    Locale locale, int fieldMask) {
  1588                                    Locale locale, int fieldMask) {
       
  1589         int baseStyle = getBaseStyle(style); // Ignore the standalone mask
  1516         if (field < 0 || field >= fields.length ||
  1590         if (field < 0 || field >= fields.length ||
  1517             style < minStyle || style > maxStyle) {
  1591             baseStyle < minStyle || baseStyle > maxStyle) {
  1518             throw new IllegalArgumentException();
  1592             throw new IllegalArgumentException();
  1519         }
  1593         }
  1520         if (locale == null) {
  1594         if (locale == null) {
  1521             throw new NullPointerException();
  1595             throw new NullPointerException();
  1522         }
  1596         }
  1523         return isFieldSet(fieldMask, field);
  1597         return isFieldSet(fieldMask, field);
  1524     }
  1598     }
  1525 
  1599 
  1526     private String[] getFieldStrings(int field, int style, DateFormatSymbols symbols) {
  1600     private String[] getFieldStrings(int field, int style, DateFormatSymbols symbols) {
       
  1601         int baseStyle = getBaseStyle(style); // ignore the standalone mask
  1527         String[] strings = null;
  1602         String[] strings = null;
  1528         switch (field) {
  1603         switch (field) {
  1529         case ERA:
  1604         case ERA:
  1530             strings = symbols.getEras();
  1605             strings = symbols.getEras();
  1531             break;
  1606             break;
  1532 
  1607 
  1533         case MONTH:
  1608         case MONTH:
  1534             strings = (style == LONG) ? symbols.getMonths() : symbols.getShortMonths();
  1609             strings = (baseStyle == LONG) ? symbols.getMonths() : symbols.getShortMonths();
  1535             break;
  1610             break;
  1536 
  1611 
  1537         case DAY_OF_WEEK:
  1612         case DAY_OF_WEEK:
  1538             strings = (style == LONG) ? symbols.getWeekdays() : symbols.getShortWeekdays();
  1613             strings = (baseStyle == LONG) ? symbols.getWeekdays() : symbols.getShortWeekdays();
  1539             break;
  1614             break;
  1540 
  1615 
  1541         case AM_PM:
  1616         case AM_PM:
  1542             strings = symbols.getAmPmStrings();
  1617             strings = symbols.getAmPmStrings();
  1543             break;
  1618             break;
  1552      * calendar field values. Then, the {@link #computeFields()} method is
  1627      * calendar field values. Then, the {@link #computeFields()} method is
  1553      * called to calculate all calendar field values.
  1628      * called to calculate all calendar field values.
  1554      */
  1629      */
  1555     protected void complete()
  1630     protected void complete()
  1556     {
  1631     {
  1557         if (!isTimeSet)
  1632         if (!isTimeSet) {
  1558             updateTime();
  1633             updateTime();
       
  1634         }
  1559         if (!areFieldsSet || !areAllFieldsSet) {
  1635         if (!areFieldsSet || !areAllFieldsSet) {
  1560             computeFields(); // fills in unset fields
  1636             computeFields(); // fills in unset fields
  1561             areAllFieldsSet = areFieldsSet = true;
  1637             areAllFieldsSet = areFieldsSet = true;
  1562         }
  1638         }
  1563     }
  1639     }
  1687 
  1763 
  1688     /**
  1764     /**
  1689      * Returns whether the specified <code>field</code> is on in the
  1765      * Returns whether the specified <code>field</code> is on in the
  1690      * <code>fieldMask</code>.
  1766      * <code>fieldMask</code>.
  1691      */
  1767      */
  1692     static final boolean isFieldSet(int fieldMask, int field) {
  1768     static boolean isFieldSet(int fieldMask, int field) {
  1693         return (fieldMask & (1 << field)) != 0;
  1769         return (fieldMask & (1 << field)) != 0;
  1694     }
  1770     }
  1695 
  1771 
  1696     /**
  1772     /**
  1697      * Returns a field mask indicating which calendar field values
  1773      * Returns a field mask indicating which calendar field values
  1863         }
  1939         }
  1864 
  1940 
  1865         return fieldMask;
  1941         return fieldMask;
  1866     }
  1942     }
  1867 
  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 
  1868     /**
  1952     /**
  1869      * Returns the pseudo-time-stamp for two fields, given their
  1953      * Returns the pseudo-time-stamp for two fields, given their
  1870      * individual pseudo-time-stamps.  If either of the fields
  1954      * individual pseudo-time-stamps.  If either of the fields
  1871      * is unset, then the aggregate is unset.  Otherwise, the
  1955      * is unset, then the aggregate is unset.  Otherwise, the
  1872      * aggregate is the later of the two stamps.
  1956      * aggregate is the later of the two stamps.
  1873      */
  1957      */
  1874     private static final int aggregateStamp(int stamp_a, int stamp_b) {
  1958     private static int aggregateStamp(int stamp_a, int stamp_b) {
  1875         if (stamp_a == UNSET || stamp_b == UNSET) {
  1959         if (stamp_a == UNSET || stamp_b == UNSET) {
  1876             return UNSET;
  1960             return UNSET;
  1877         }
  1961         }
  1878         return (stamp_a > stamp_b) ? stamp_a : stamp_b;
  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();
  1879     }
  1984     }
  1880 
  1985 
  1881     /**
  1986     /**
  1882      * Compares this <code>Calendar</code> to the specified
  1987      * Compares this <code>Calendar</code> to the specified
  1883      * <code>Object</code>.  The result is <code>true</code> if and only if
  1988      * <code>Object</code>.  The result is <code>true</code> if and only if
  1898      *
  2003      *
  1899      * @param obj the object to compare with.
  2004      * @param obj the object to compare with.
  1900      * @return <code>true</code> if this object is equal to <code>obj</code>;
  2005      * @return <code>true</code> if this object is equal to <code>obj</code>;
  1901      * <code>false</code> otherwise.
  2006      * <code>false</code> otherwise.
  1902      */
  2007      */
       
  2008     @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
       
  2009     @Override
  1903     public boolean equals(Object obj) {
  2010     public boolean equals(Object obj) {
  1904         if (this == obj)
  2011         if (this == obj) {
  1905             return true;
  2012             return true;
       
  2013         }
  1906         try {
  2014         try {
  1907             Calendar that = (Calendar)obj;
  2015             Calendar that = (Calendar)obj;
  1908             return compareTo(getMillisOf(that)) == 0 &&
  2016             return compareTo(getMillisOf(that)) == 0 &&
  1909                 lenient == that.lenient &&
  2017                 lenient == that.lenient &&
  1910                 firstDayOfWeek == that.firstDayOfWeek &&
  2018                 firstDayOfWeek == that.firstDayOfWeek &&
  1922      * Returns a hash code for this calendar.
  2030      * Returns a hash code for this calendar.
  1923      *
  2031      *
  1924      * @return a hash code value for this object.
  2032      * @return a hash code value for this object.
  1925      * @since 1.2
  2033      * @since 1.2
  1926      */
  2034      */
       
  2035     @Override
  1927     public int hashCode() {
  2036     public int hashCode() {
  1928         // 'otheritems' represents the hash code for the previous versions.
  2037         // 'otheritems' represents the hash code for the previous versions.
  1929         int otheritems = (lenient ? 1 : 0)
  2038         int otheritems = (lenient ? 1 : 0)
  1930             | (firstDayOfWeek << 1)
  2039             | (firstDayOfWeek << 1)
  1931             | (minimalDaysInFirstWeek << 4)
  2040             | (minimalDaysInFirstWeek << 4)
  1993      * @exception IllegalArgumentException if the time value of the
  2102      * @exception IllegalArgumentException if the time value of the
  1994      * specified <code>Calendar</code> object can't be obtained due to
  2103      * specified <code>Calendar</code> object can't be obtained due to
  1995      * any invalid calendar values.
  2104      * any invalid calendar values.
  1996      * @since   1.5
  2105      * @since   1.5
  1997      */
  2106      */
       
  2107     @Override
  1998     public int compareTo(Calendar anotherCalendar) {
  2108     public int compareTo(Calendar anotherCalendar) {
  1999         return compareTo(getMillisOf(anotherCalendar));
  2109         return compareTo(getMillisOf(anotherCalendar));
  2000     }
  2110     }
  2001 
  2111 
  2002     /**
  2112     /**
  2466         Calendar work = (Calendar)this.clone();
  2576         Calendar work = (Calendar)this.clone();
  2467         work.setLenient(true);
  2577         work.setLenient(true);
  2468 
  2578 
  2469         // if we're counting weeks, set the day of the week to Sunday.  We know the
  2579         // 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.
  2580         // 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)
  2581         if (field == WEEK_OF_YEAR || field == WEEK_OF_MONTH) {
  2472             work.set(DAY_OF_WEEK, firstDayOfWeek);
  2582             work.set(DAY_OF_WEEK, firstDayOfWeek);
       
  2583         }
  2473 
  2584 
  2474         // now try each value from getLeastMaximum() to getMaximum() one by one until
  2585         // 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
  2586         // 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
  2587         // normalizes to itself is the actual maximum for the current date
  2477         int result = fieldValue;
  2588         int result = fieldValue;
  2492     /**
  2603     /**
  2493      * Creates and returns a copy of this object.
  2604      * Creates and returns a copy of this object.
  2494      *
  2605      *
  2495      * @return a copy of this object.
  2606      * @return a copy of this object.
  2496      */
  2607      */
       
  2608     @Override
  2497     public Object clone()
  2609     public Object clone()
  2498     {
  2610     {
  2499         try {
  2611         try {
  2500             Calendar other = (Calendar) super.clone();
  2612             Calendar other = (Calendar) super.clone();
  2501 
  2613 
  2529      * @param field the calendar field
  2641      * @param field the calendar field
  2530      * @return the calendar field name
  2642      * @return the calendar field name
  2531      * @exception IndexOutOfBoundsException if <code>field</code> is negative,
  2643      * @exception IndexOutOfBoundsException if <code>field</code> is negative,
  2532      * equal to or greater then <code>FIELD_COUNT</code>.
  2644      * equal to or greater then <code>FIELD_COUNT</code>.
  2533      */
  2645      */
  2534     static final String getFieldName(int field) {
  2646     static String getFieldName(int field) {
  2535         return FIELD_NAME[field];
  2647         return FIELD_NAME[field];
  2536     }
  2648     }
  2537 
  2649 
  2538     /**
  2650     /**
  2539      * Return a string representation of this calendar. This method
  2651      * Return a string representation of this calendar. This method
  2541      * format of the returned string may vary between implementations.
  2653      * format of the returned string may vary between implementations.
  2542      * The returned string may be empty but may not be <code>null</code>.
  2654      * The returned string may be empty but may not be <code>null</code>.
  2543      *
  2655      *
  2544      * @return  a string representation of this calendar.
  2656      * @return  a string representation of this calendar.
  2545      */
  2657      */
       
  2658     @Override
  2546     public String toString() {
  2659     public String toString() {
  2547         // NOTE: BuddhistCalendar.toString() interprets the string
  2660         // NOTE: BuddhistCalendar.toString() interprets the string
  2548         // produced by this method so that the Gregorian year number
  2661         // produced by this method so that the Gregorian year number
  2549         // is substituted by its B.E. year value. It relies on
  2662         // is substituted by its B.E. year value. It relies on
  2550         // "...,YEAR=<year>,..." or "...,YEAR=?,...".
  2663         // "...,YEAR=<year>,..." or "...,YEAR=?,...".
  2565         return buffer.toString();
  2678         return buffer.toString();
  2566     }
  2679     }
  2567 
  2680 
  2568     // =======================privates===============================
  2681     // =======================privates===============================
  2569 
  2682 
  2570     private static final void appendValue(StringBuilder sb, String item, boolean valid, long value) {
  2683     private static void appendValue(StringBuilder sb, String item, boolean valid, long value) {
  2571         sb.append(item).append('=');
  2684         sb.append(item).append('=');
  2572         if (valid) {
  2685         if (valid) {
  2573             sb.append(value);
  2686             sb.append(value);
  2574         } else {
  2687         } else {
  2575             sb.append('?');
  2688             sb.append('?');
  2585     private void setWeekCountData(Locale desiredLocale)
  2698     private void setWeekCountData(Locale desiredLocale)
  2586     {
  2699     {
  2587         /* try to get the Locale data from the cache */
  2700         /* try to get the Locale data from the cache */
  2588         int[] data = cachedLocaleData.get(desiredLocale);
  2701         int[] data = cachedLocaleData.get(desiredLocale);
  2589         if (data == null) {  /* cache miss */
  2702         if (data == null) {  /* cache miss */
  2590             ResourceBundle bundle = LocaleData.getCalendarData(desiredLocale);
  2703             LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(CalendarDataProvider.class, desiredLocale);
       
  2704             CalendarDataProvider provider = adapter.getCalendarDataProvider();
  2591             data = new int[2];
  2705             data = new int[2];
  2592             data[0] = Integer.parseInt(bundle.getString("firstDayOfWeek"));
  2706             data[0] = provider.getFirstDayOfWeek(desiredLocale);
  2593             data[1] = Integer.parseInt(bundle.getString("minimalDaysInFirstWeek"));
  2707             data[1] = provider.getMinimalDaysInFirstWeek(desiredLocale);
       
  2708             assert data[0] != 0 && data[1] != 0;
  2594             cachedLocaleData.putIfAbsent(desiredLocale, data);
  2709             cachedLocaleData.putIfAbsent(desiredLocale, data);
  2595         }
  2710         }
  2596         firstDayOfWeek = data[0];
  2711         firstDayOfWeek = data[0];
  2597         minimalDaysInFirstWeek = data[1];
  2712         minimalDaysInFirstWeek = data[1];
  2598     }
  2713     }
  2612     private int compareTo(long t) {
  2727     private int compareTo(long t) {
  2613         long thisTime = getMillisOf(this);
  2728         long thisTime = getMillisOf(this);
  2614         return (thisTime > t) ? 1 : (thisTime == t) ? 0 : -1;
  2729         return (thisTime > t) ? 1 : (thisTime == t) ? 0 : -1;
  2615     }
  2730     }
  2616 
  2731 
  2617     private static final long getMillisOf(Calendar calendar) {
  2732     private static long getMillisOf(Calendar calendar) {
  2618         if (calendar.isTimeSet) {
  2733         if (calendar.isTimeSet) {
  2619             return calendar.time;
  2734             return calendar.time;
  2620         }
  2735         }
  2621         Calendar cal = (Calendar) calendar.clone();
  2736         Calendar cal = (Calendar) calendar.clone();
  2622         cal.setLenient(true);
  2737         cal.setLenient(true);
  2625 
  2740 
  2626     /**
  2741     /**
  2627      * Adjusts the stamp[] values before nextStamp overflow. nextStamp
  2742      * Adjusts the stamp[] values before nextStamp overflow. nextStamp
  2628      * is set to the next stamp value upon the return.
  2743      * is set to the next stamp value upon the return.
  2629      */
  2744      */
  2630     private final void adjustStamp() {
  2745     private void adjustStamp() {
  2631         int max = MINIMUM_USER_STAMP;
  2746         int max = MINIMUM_USER_STAMP;
  2632         int newStamp = MINIMUM_USER_STAMP;
  2747         int newStamp = MINIMUM_USER_STAMP;
  2633 
  2748 
  2634         for (;;) {
  2749         for (;;) {
  2635             int min = Integer.MAX_VALUE;
  2750             int min = Integer.MAX_VALUE;
  2750             perms.add(perm);
  2865             perms.add(perm);
  2751             INSTANCE = new AccessControlContext(new ProtectionDomain[] {
  2866             INSTANCE = new AccessControlContext(new ProtectionDomain[] {
  2752                                                     new ProtectionDomain(null, perms)
  2867                                                     new ProtectionDomain(null, perms)
  2753                                                 });
  2868                                                 });
  2754         }
  2869         }
       
  2870         private CalendarAccessControlContext() {
       
  2871         }
  2755     }
  2872     }
  2756 
  2873 
  2757     /**
  2874     /**
  2758      * Reconstitutes this object from a stream (i.e., deserialize it).
  2875      * Reconstitutes this object from a stream (i.e., deserialize it).
  2759      */
  2876      */
  2769         // fields[], isSet[], isTimeSet, and areFieldsSet may not be
  2886         // fields[], isSet[], isTimeSet, and areFieldsSet may not be
  2770         // streamed out anymore.  We expect 'time' to be correct.
  2887         // streamed out anymore.  We expect 'time' to be correct.
  2771         if (serialVersionOnStream >= 2)
  2888         if (serialVersionOnStream >= 2)
  2772         {
  2889         {
  2773             isTimeSet = true;
  2890             isTimeSet = true;
  2774             if (fields == null) fields = new int[FIELD_COUNT];
  2891             if (fields == null) {
  2775             if (isSet == null) isSet = new boolean[FIELD_COUNT];
  2892                 fields = new int[FIELD_COUNT];
       
  2893             }
       
  2894             if (isSet == null) {
       
  2895                 isSet = new boolean[FIELD_COUNT];
       
  2896             }
  2776         }
  2897         }
  2777         else if (serialVersionOnStream >= 0)
  2898         else if (serialVersionOnStream >= 0)
  2778         {
  2899         {
  2779             for (int i=0; i<FIELD_COUNT; ++i)
  2900             for (int i=0; i<FIELD_COUNT; ++i) {
  2780                 stamp[i] = isSet[i] ? COMPUTED : UNSET;
  2901                 stamp[i] = isSet[i] ? COMPUTED : UNSET;
       
  2902             }
  2781         }
  2903         }
  2782 
  2904 
  2783         serialVersionOnStream = currentSerialVersion;
  2905         serialVersionOnStream = currentSerialVersion;
  2784 
  2906 
  2785         // If there's a ZoneInfo object, use it for zone.
  2907         // If there's a ZoneInfo object, use it for zone.
  2786         ZoneInfo zi = null;
  2908         ZoneInfo zi = null;
  2787         try {
  2909         try {
  2788             zi = AccessController.doPrivileged(
  2910             zi = AccessController.doPrivileged(
  2789                     new PrivilegedExceptionAction<ZoneInfo>() {
  2911                     new PrivilegedExceptionAction<ZoneInfo>() {
       
  2912                         @Override
  2790                         public ZoneInfo run() throws Exception {
  2913                         public ZoneInfo run() throws Exception {
  2791                             return (ZoneInfo) input.readObject();
  2914                             return (ZoneInfo) input.readObject();
  2792                         }
  2915                         }
  2793                     },
  2916                     },
  2794                     CalendarAccessControlContext.INSTANCE);
  2917                     CalendarAccessControlContext.INSTANCE);