< prev index next >

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

Print this page
rev 47480 : [mq]: 8176841


  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) {


< prev index next >