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.time.Instant;
55 import java.util.concurrent.ConcurrentHashMap;
56 import java.util.concurrent.ConcurrentMap;
57 import sun.util.BuddhistCalendar;
58 import sun.util.calendar.ZoneInfo;
59 import sun.util.locale.provider.CalendarDataUtility;
60 import sun.util.locale.provider.LocaleProviderAdapter;
61 import sun.util.spi.CalendarProvider;
62
63 /**
64 * The <code>Calendar</code> class is an abstract class that provides methods
65 * for converting between a specific instant in time and a set of {@link
66 * #fields calendar fields} such as <code>YEAR</code>, <code>MONTH</code>,
67 * <code>DAY_OF_MONTH</code>, <code>HOUR</code>, and so on, and for
68 * manipulating the calendar fields, such as getting the date of the next
69 * week. An instant in time can be represented by a millisecond value that is
70 * an offset from the <a id="Epoch"><em>Epoch</em></a>, January 1, 1970
71 * 00:00:00.000 GMT (Gregorian).
72 *
73 * <p>The class also provides additional fields and methods for
74 * implementing a concrete calendar system outside the package. Those
75 * fields and methods are defined as <code>protected</code>.
76 *
77 * <p>
78 * Like other locale-sensitive classes, <code>Calendar</code> provides a
79 * class method, <code>getInstance</code>, for getting a generally useful
80 * object of this type. <code>Calendar</code>'s <code>getInstance</code> method
111 * fields, <em>lenient</em> and <em>non-lenient</em>. When a
112 * <code>Calendar</code> is in lenient mode, it accepts a wider range of
113 * calendar field values than it produces. When a <code>Calendar</code>
114 * recomputes calendar field values for return by <code>get()</code>, all of
115 * the calendar fields are normalized. For example, a lenient
116 * <code>GregorianCalendar</code> interprets <code>MONTH == JANUARY</code>,
117 * <code>DAY_OF_MONTH == 32</code> as February 1.
118
119 * <p>When a <code>Calendar</code> is in non-lenient mode, it throws an
120 * exception if there is any inconsistency in its calendar fields. For
121 * example, a <code>GregorianCalendar</code> always produces
122 * <code>DAY_OF_MONTH</code> values between 1 and the length of the month. A
123 * non-lenient <code>GregorianCalendar</code> throws an exception upon
124 * calculating its time or calendar field values if any out-of-range field
125 * value has been set.
126 *
127 * <h4><a id="first_week">First Week</a></h4>
128 *
129 * <code>Calendar</code> defines a locale-specific seven day week using two
130 * parameters: the first day of the week and the minimal days in first week
131 * (from 1 to 7). These numbers are taken from the locale resource data when a
132 * <code>Calendar</code> is constructed. They may also be specified explicitly
133 * through the methods for setting their values.
134 *
135 * <p>When setting or getting the <code>WEEK_OF_MONTH</code> or
136 * <code>WEEK_OF_YEAR</code> fields, <code>Calendar</code> must determine the
137 * first week of the month or year as a reference point. The first week of a
138 * month or year is defined as the earliest seven day period beginning on
139 * <code>getFirstDayOfWeek()</code> and containing at least
140 * <code>getMinimalDaysInFirstWeek()</code> days of that month or year. Weeks
141 * numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow
142 * it. Note that the normalized numbering returned by <code>get()</code> may be
143 * different. For example, a specific <code>Calendar</code> subclass may
144 * designate the week before week 1 of a year as week <code><i>n</i></code> of
145 * the previous year.
146 *
147 * <h4>Calendar Fields Resolution</h4>
148 *
149 * When computing a date and time from the calendar fields, there
150 * may be insufficient information for the computation (such as only
151 * year and month with no day of month), or there may be inconsistent
152 * information (such as Tuesday, July 15, 1996 (Gregorian) -- July 15,
153 * 1996 is actually a Monday). <code>Calendar</code> will resolve
1446 * parameters haven't been given explicitly.
1447 *
1448 * <p>Any out of range field values are either normalized in lenient
1449 * mode or detected as an invalid value in non-lenient mode.
1450 *
1451 * @return a {@code Calendar} built with parameters of this {@code
1452 * Calendar.Builder}
1453 * @throws IllegalArgumentException if the calendar type is unknown, or
1454 * if any invalid field values are given in non-lenient mode, or
1455 * if a week date is given for the calendar type that doesn't
1456 * support week dates.
1457 * @see Calendar#getInstance(TimeZone, Locale)
1458 * @see Locale#getDefault(Locale.Category)
1459 * @see TimeZone#getDefault()
1460 */
1461 public Calendar build() {
1462 if (locale == null) {
1463 locale = Locale.getDefault();
1464 }
1465 if (zone == null) {
1466 zone = TimeZone.getDefault();
1467 }
1468 Calendar cal;
1469 if (type == null) {
1470 type = locale.getUnicodeLocaleType("ca");
1471 }
1472 if (type == null) {
1473 if (locale.getCountry() == "TH"
1474 && locale.getLanguage() == "th") {
1475 type = "buddhist";
1476 } else {
1477 type = "gregory";
1478 }
1479 }
1480 switch (type) {
1481 case "gregory":
1482 cal = new GregorianCalendar(zone, locale, true);
1483 break;
1484 case "iso8601":
1485 GregorianCalendar gcal = new GregorianCalendar(zone, locale, true);
1486 // make gcal a proleptic Gregorian
1593 protected Calendar(TimeZone zone, Locale aLocale)
1594 {
1595 fields = new int[FIELD_COUNT];
1596 isSet = new boolean[FIELD_COUNT];
1597 stamp = new int[FIELD_COUNT];
1598
1599 this.zone = zone;
1600 setWeekCountData(aLocale);
1601 }
1602
1603 /**
1604 * Gets a calendar using the default time zone and locale. The
1605 * <code>Calendar</code> returned is based on the current time
1606 * in the default time zone with the default
1607 * {@link Locale.Category#FORMAT FORMAT} locale.
1608 *
1609 * @return a Calendar.
1610 */
1611 public static Calendar getInstance()
1612 {
1613 return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
1614 }
1615
1616 /**
1617 * Gets a calendar using the specified time zone and default locale.
1618 * The <code>Calendar</code> returned is based on the current time
1619 * in the given time zone with the default
1620 * {@link Locale.Category#FORMAT FORMAT} locale.
1621 *
1622 * @param zone the time zone to use
1623 * @return a Calendar.
1624 */
1625 public static Calendar getInstance(TimeZone zone)
1626 {
1627 return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT));
1628 }
1629
1630 /**
1631 * Gets a calendar using the default time zone and specified locale.
1632 * The <code>Calendar</code> returned is based on the current time
1633 * in the default time zone with the given locale.
1634 *
1635 * @param aLocale the locale for the week data
1636 * @return a Calendar.
1637 */
1638 public static Calendar getInstance(Locale aLocale)
1639 {
1640 return createCalendar(TimeZone.getDefault(), aLocale);
1641 }
1642
1643 /**
1644 * Gets a calendar with the specified time zone and locale.
1645 * The <code>Calendar</code> returned is based on the current time
1646 * in the given time zone with the given locale.
1647 *
1648 * @param zone the time zone to use
1649 * @param aLocale the locale for the week data
1650 * @return a Calendar.
1651 */
1652 public static Calendar getInstance(TimeZone zone,
1653 Locale aLocale)
1654 {
1655 return createCalendar(zone, aLocale);
1656 }
1657
1658 private static Calendar createCalendar(TimeZone zone,
1659 Locale aLocale)
1660 {
1661 CalendarProvider provider =
1662 LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
1663 .getCalendarProvider();
1664 if (provider != null) {
1665 try {
1666 return provider.getInstance(zone, aLocale);
1667 } catch (IllegalArgumentException iae) {
1668 // fall back to the default instantiation
1669 }
1670 }
1671
1672 Calendar cal = null;
1673
1674 if (aLocale.hasExtensions()) {
1675 String caltype = aLocale.getUnicodeLocaleType("ca");
1676 if (caltype != null) {
1677 switch (caltype) {
|
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.time.Instant;
55 import java.util.concurrent.ConcurrentHashMap;
56 import java.util.concurrent.ConcurrentMap;
57 import sun.util.BuddhistCalendar;
58 import sun.util.calendar.ZoneInfo;
59 import sun.util.locale.provider.CalendarDataUtility;
60 import sun.util.locale.provider.LocaleProviderAdapter;
61 import sun.util.locale.provider.TimeZoneNameUtility;
62 import sun.util.spi.CalendarProvider;
63
64 /**
65 * The <code>Calendar</code> class is an abstract class that provides methods
66 * for converting between a specific instant in time and a set of {@link
67 * #fields calendar fields} such as <code>YEAR</code>, <code>MONTH</code>,
68 * <code>DAY_OF_MONTH</code>, <code>HOUR</code>, and so on, and for
69 * manipulating the calendar fields, such as getting the date of the next
70 * week. An instant in time can be represented by a millisecond value that is
71 * an offset from the <a id="Epoch"><em>Epoch</em></a>, January 1, 1970
72 * 00:00:00.000 GMT (Gregorian).
73 *
74 * <p>The class also provides additional fields and methods for
75 * implementing a concrete calendar system outside the package. Those
76 * fields and methods are defined as <code>protected</code>.
77 *
78 * <p>
79 * Like other locale-sensitive classes, <code>Calendar</code> provides a
80 * class method, <code>getInstance</code>, for getting a generally useful
81 * object of this type. <code>Calendar</code>'s <code>getInstance</code> method
112 * fields, <em>lenient</em> and <em>non-lenient</em>. When a
113 * <code>Calendar</code> is in lenient mode, it accepts a wider range of
114 * calendar field values than it produces. When a <code>Calendar</code>
115 * recomputes calendar field values for return by <code>get()</code>, all of
116 * the calendar fields are normalized. For example, a lenient
117 * <code>GregorianCalendar</code> interprets <code>MONTH == JANUARY</code>,
118 * <code>DAY_OF_MONTH == 32</code> as February 1.
119
120 * <p>When a <code>Calendar</code> is in non-lenient mode, it throws an
121 * exception if there is any inconsistency in its calendar fields. For
122 * example, a <code>GregorianCalendar</code> always produces
123 * <code>DAY_OF_MONTH</code> values between 1 and the length of the month. A
124 * non-lenient <code>GregorianCalendar</code> throws an exception upon
125 * calculating its time or calendar field values if any out-of-range field
126 * value has been set.
127 *
128 * <h4><a id="first_week">First Week</a></h4>
129 *
130 * <code>Calendar</code> defines a locale-specific seven day week using two
131 * parameters: the first day of the week and the minimal days in first week
132 * (from 1 to 7). These numbers are taken from the locale resource data or the
133 * locale itself when a <code>Calendar</code> is constructed. If the designated
134 * locale contains "fw" and/or "rg" <a href="./Locale.html#def_locale_extension">
135 * Unicode extensions</a>, the first day of the week will be obtained according to
136 * those extensions. If both "fw" and "rg" are specified, the value from "fw"
137 * extension supersedes the implicit one from "rg" extension.
138 * They may also be specified explicitly through the methods for setting their
139 * values.
140 *
141 * <p>When setting or getting the <code>WEEK_OF_MONTH</code> or
142 * <code>WEEK_OF_YEAR</code> fields, <code>Calendar</code> must determine the
143 * first week of the month or year as a reference point. The first week of a
144 * month or year is defined as the earliest seven day period beginning on
145 * <code>getFirstDayOfWeek()</code> and containing at least
146 * <code>getMinimalDaysInFirstWeek()</code> days of that month or year. Weeks
147 * numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow
148 * it. Note that the normalized numbering returned by <code>get()</code> may be
149 * different. For example, a specific <code>Calendar</code> subclass may
150 * designate the week before week 1 of a year as week <code><i>n</i></code> of
151 * the previous year.
152 *
153 * <h4>Calendar Fields Resolution</h4>
154 *
155 * When computing a date and time from the calendar fields, there
156 * may be insufficient information for the computation (such as only
157 * year and month with no day of month), or there may be inconsistent
158 * information (such as Tuesday, July 15, 1996 (Gregorian) -- July 15,
159 * 1996 is actually a Monday). <code>Calendar</code> will resolve
1452 * parameters haven't been given explicitly.
1453 *
1454 * <p>Any out of range field values are either normalized in lenient
1455 * mode or detected as an invalid value in non-lenient mode.
1456 *
1457 * @return a {@code Calendar} built with parameters of this {@code
1458 * Calendar.Builder}
1459 * @throws IllegalArgumentException if the calendar type is unknown, or
1460 * if any invalid field values are given in non-lenient mode, or
1461 * if a week date is given for the calendar type that doesn't
1462 * support week dates.
1463 * @see Calendar#getInstance(TimeZone, Locale)
1464 * @see Locale#getDefault(Locale.Category)
1465 * @see TimeZone#getDefault()
1466 */
1467 public Calendar build() {
1468 if (locale == null) {
1469 locale = Locale.getDefault();
1470 }
1471 if (zone == null) {
1472 zone = defaultTimeZone(locale);
1473 }
1474 Calendar cal;
1475 if (type == null) {
1476 type = locale.getUnicodeLocaleType("ca");
1477 }
1478 if (type == null) {
1479 if (locale.getCountry() == "TH"
1480 && locale.getLanguage() == "th") {
1481 type = "buddhist";
1482 } else {
1483 type = "gregory";
1484 }
1485 }
1486 switch (type) {
1487 case "gregory":
1488 cal = new GregorianCalendar(zone, locale, true);
1489 break;
1490 case "iso8601":
1491 GregorianCalendar gcal = new GregorianCalendar(zone, locale, true);
1492 // make gcal a proleptic Gregorian
1599 protected Calendar(TimeZone zone, Locale aLocale)
1600 {
1601 fields = new int[FIELD_COUNT];
1602 isSet = new boolean[FIELD_COUNT];
1603 stamp = new int[FIELD_COUNT];
1604
1605 this.zone = zone;
1606 setWeekCountData(aLocale);
1607 }
1608
1609 /**
1610 * Gets a calendar using the default time zone and locale. The
1611 * <code>Calendar</code> returned is based on the current time
1612 * in the default time zone with the default
1613 * {@link Locale.Category#FORMAT FORMAT} locale.
1614 *
1615 * @return a Calendar.
1616 */
1617 public static Calendar getInstance()
1618 {
1619 Locale aLocale = Locale.getDefault(Locale.Category.FORMAT);
1620 return createCalendar(defaultTimeZone(aLocale), aLocale);
1621 }
1622
1623 /**
1624 * Gets a calendar using the specified time zone and default locale.
1625 * The <code>Calendar</code> returned is based on the current time
1626 * in the given time zone with the default
1627 * {@link Locale.Category#FORMAT FORMAT} locale.
1628 *
1629 * @param zone the time zone to use
1630 * @return a Calendar.
1631 */
1632 public static Calendar getInstance(TimeZone zone)
1633 {
1634 return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT));
1635 }
1636
1637 /**
1638 * Gets a calendar using the default time zone and specified locale.
1639 * The <code>Calendar</code> returned is based on the current time
1640 * in the default time zone with the given locale.
1641 *
1642 * @param aLocale the locale for the week data
1643 * @return a Calendar.
1644 */
1645 public static Calendar getInstance(Locale aLocale)
1646 {
1647 return createCalendar(defaultTimeZone(aLocale), aLocale);
1648 }
1649
1650 /**
1651 * Gets a calendar with the specified time zone and locale.
1652 * The <code>Calendar</code> returned is based on the current time
1653 * in the given time zone with the given locale.
1654 *
1655 * @param zone the time zone to use
1656 * @param aLocale the locale for the week data
1657 * @return a Calendar.
1658 */
1659 public static Calendar getInstance(TimeZone zone,
1660 Locale aLocale)
1661 {
1662 return createCalendar(zone, aLocale);
1663 }
1664
1665 private static TimeZone defaultTimeZone(Locale l) {
1666 TimeZone defaultTZ = TimeZone.getDefault();
1667 String shortTZID = l.getUnicodeLocaleType("tz");
1668 return shortTZID != null ?
1669 TimeZoneNameUtility.convertLDMLShortID(shortTZID)
1670 .map(TimeZone::getTimeZone)
1671 .orElse(defaultTZ) :
1672 defaultTZ;
1673 }
1674
1675 private static Calendar createCalendar(TimeZone zone,
1676 Locale aLocale)
1677 {
1678 CalendarProvider provider =
1679 LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
1680 .getCalendarProvider();
1681 if (provider != null) {
1682 try {
1683 return provider.getInstance(zone, aLocale);
1684 } catch (IllegalArgumentException iae) {
1685 // fall back to the default instantiation
1686 }
1687 }
1688
1689 Calendar cal = null;
1690
1691 if (aLocale.hasExtensions()) {
1692 String caltype = aLocale.getUnicodeLocaleType("ca");
1693 if (caltype != null) {
1694 switch (caltype) {
|