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 < 0 || field >= 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 <<
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<<YEAR)|(1<<MONTH)|(1<<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 < 0 || field >= 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 <<
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<<YEAR)|(1<<MONTH)|(1<<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;
|