Path: blob/master/src/java.base/share/classes/java/util/Calendar.java
41152 views
/*1* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* (C) Copyright Taligent, Inc. 1996-1998 - All Rights Reserved27* (C) Copyright IBM Corp. 1996-1998 - All Rights Reserved28*29* The original version of this source code and documentation is copyrighted30* and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These31* materials are provided under terms of a License Agreement between Taligent32* and Sun. This technology is protected by multiple US and International33* patents. This notice and attribution to Taligent may not be removed.34* Taligent is a registered trademark of Taligent, Inc.35*36*/3738package java.util;3940import java.io.IOException;41import java.io.ObjectInputStream;42import java.io.ObjectOutputStream;43import java.io.OptionalDataException;44import java.io.Serializable;45import java.security.AccessControlContext;46import java.security.AccessController;47import java.security.PermissionCollection;48import java.security.PrivilegedActionException;49import java.security.PrivilegedExceptionAction;50import java.security.ProtectionDomain;51import java.text.DateFormat;52import java.text.DateFormatSymbols;53import java.time.Instant;54import java.util.concurrent.ConcurrentHashMap;55import java.util.concurrent.ConcurrentMap;56import sun.util.BuddhistCalendar;57import sun.util.calendar.ZoneInfo;58import sun.util.locale.provider.CalendarDataUtility;59import sun.util.locale.provider.LocaleProviderAdapter;60import sun.util.locale.provider.TimeZoneNameUtility;61import sun.util.spi.CalendarProvider;6263/**64* The {@code Calendar} class is an abstract class that provides methods65* for converting between a specific instant in time and a set of {@link66* #fields calendar fields} such as {@code YEAR}, {@code MONTH},67* {@code DAY_OF_MONTH}, {@code HOUR}, and so on, and for68* manipulating the calendar fields, such as getting the date of the next69* week. An instant in time can be represented by a millisecond value that is70* an offset from the <a id="Epoch"><em>Epoch</em></a>, January 1, 197071* 00:00:00.000 GMT (Gregorian).72*73* <p>The class also provides additional fields and methods for74* implementing a concrete calendar system outside the package. Those75* fields and methods are defined as {@code protected}.76*77* <p>78* Like other locale-sensitive classes, {@code Calendar} provides a79* class method, {@code getInstance}, for getting a generally useful80* object of this type. {@code Calendar}'s {@code getInstance} method81* returns a {@code Calendar} object whose82* calendar fields have been initialized with the current date and time:83* <blockquote>84* <pre>85* Calendar rightNow = Calendar.getInstance();86* </pre>87* </blockquote>88*89* <p>A {@code Calendar} object can produce all the calendar field values90* needed to implement the date-time formatting for a particular language and91* calendar style (for example, Japanese-Gregorian, Japanese-Traditional).92* {@code Calendar} defines the range of values returned by93* certain calendar fields, as well as their meaning. For example,94* the first month of the calendar system has value <code>MONTH ==95* JANUARY</code> for all calendars. Other values are defined by the96* concrete subclass, such as {@code ERA}. See individual field97* documentation and subclass documentation for details.98*99* <h2>Getting and Setting Calendar Field Values</h2>100*101* <p>The calendar field values can be set by calling the {@code set}102* methods. Any field values set in a {@code Calendar} will not be103* interpreted until it needs to calculate its time value (milliseconds from104* the Epoch) or values of the calendar fields. Calling the105* {@code get}, {@code getTimeInMillis}, {@code getTime},106* {@code add} and {@code roll} involves such calculation.107*108* <h3>Leniency</h3>109*110* <p>{@code Calendar} has two modes for interpreting the calendar111* fields, <em>lenient</em> and <em>non-lenient</em>. When a112* {@code Calendar} is in lenient mode, it accepts a wider range of113* calendar field values than it produces. When a {@code Calendar}114* recomputes calendar field values for return by {@code get()}, all of115* the calendar fields are normalized. For example, a lenient116* {@code GregorianCalendar} interprets {@code MONTH == JANUARY},117* {@code DAY_OF_MONTH == 32} as February 1.118*119* <p>When a {@code Calendar} is in non-lenient mode, it throws an120* exception if there is any inconsistency in its calendar fields. For121* example, a {@code GregorianCalendar} always produces122* {@code DAY_OF_MONTH} values between 1 and the length of the month. A123* non-lenient {@code GregorianCalendar} throws an exception upon124* calculating its time or calendar field values if any out-of-range field125* value has been set.126*127* <h3><a id="first_week">First Week</a></h3>128*129* {@code Calendar} defines a locale-specific seven day week using two130* parameters: the first day of the week and the minimal days in first week131* (from 1 to 7). These numbers are taken from the locale resource data or the132* locale itself when a {@code Calendar} is constructed. If the designated133* locale contains "fw" and/or "rg" <a href="./Locale.html#def_locale_extension">134* Unicode extensions</a>, the first day of the week will be obtained according to135* those extensions. If both "fw" and "rg" are specified, the value from the "fw"136* extension supersedes the implicit one from the "rg" extension.137* They may also be specified explicitly through the methods for setting their138* values.139*140* <p>When setting or getting the {@code WEEK_OF_MONTH} or141* {@code WEEK_OF_YEAR} fields, {@code Calendar} must determine the142* first week of the month or year as a reference point. The first week of a143* month or year is defined as the earliest seven day period beginning on144* {@code getFirstDayOfWeek()} and containing at least145* {@code getMinimalDaysInFirstWeek()} days of that month or year. Weeks146* numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow147* it. Note that the normalized numbering returned by {@code get()} may be148* different. For example, a specific {@code Calendar} subclass may149* designate the week before week 1 of a year as week <code><i>n</i></code> of150* the previous year.151*152* <h3>Calendar Fields Resolution</h3>153*154* When computing a date and time from the calendar fields, there155* may be insufficient information for the computation (such as only156* year and month with no day of month), or there may be inconsistent157* information (such as Tuesday, July 15, 1996 (Gregorian) -- July 15,158* 1996 is actually a Monday). {@code Calendar} will resolve159* calendar field values to determine the date and time in the160* following way.161*162* <p><a id="resolution">If there is any conflict in calendar field values,163* {@code Calendar} gives priorities to calendar fields that have been set164* more recently.</a> The following are the default combinations of the165* calendar fields. The most recent combination, as determined by the166* most recently set single field, will be used.167*168* <p><a id="date_resolution">For the date fields</a>:169* <blockquote>170* <pre>171* YEAR + MONTH + DAY_OF_MONTH172* YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK173* YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK174* YEAR + DAY_OF_YEAR175* YEAR + DAY_OF_WEEK + WEEK_OF_YEAR176* </pre></blockquote>177*178* <a id="time_resolution">For the time of day fields</a>:179* <blockquote>180* <pre>181* HOUR_OF_DAY182* AM_PM + HOUR183* </pre></blockquote>184*185* <p>If there are any calendar fields whose values haven't been set in the selected186* field combination, {@code Calendar} uses their default values. The default187* value of each field may vary by concrete calendar systems. For example, in188* {@code GregorianCalendar}, the default of a field is the same as that189* of the start of the Epoch: i.e., {@code YEAR = 1970}, <code>MONTH =190* JANUARY</code>, {@code DAY_OF_MONTH = 1}, etc.191*192* <p>193* <strong>Note:</strong> There are certain possible ambiguities in194* interpretation of certain singular times, which are resolved in the195* following ways:196* <ol>197* <li> 23:59 is the last minute of the day and 00:00 is the first198* minute of the next day. Thus, 23:59 on Dec 31, 1999 < 00:00 on199* Jan 1, 2000 < 00:01 on Jan 1, 2000.200*201* <li> Although historically not precise, midnight also belongs to "am",202* and noon belongs to "pm", so on the same day,203* 12:00 am (midnight) < 12:01 am, and 12:00 pm (noon) < 12:01 pm204* </ol>205*206* <p>207* The date or time format strings are not part of the definition of a208* calendar, as those must be modifiable or overridable by the user at209* runtime. Use {@link DateFormat}210* to format dates.211*212* <h3>Field Manipulation</h3>213*214* The calendar fields can be changed using three methods:215* {@code set()}, {@code add()}, and {@code roll()}.216*217* <p><strong>{@code set(f, value)}</strong> changes calendar field218* {@code f} to {@code value}. In addition, it sets an219* internal member variable to indicate that calendar field {@code f} has220* been changed. Although calendar field {@code f} is changed immediately,221* the calendar's time value in milliseconds is not recomputed until the next call to222* {@code get()}, {@code getTime()}, {@code getTimeInMillis()},223* {@code add()}, or {@code roll()} is made. Thus, multiple calls to224* {@code set()} do not trigger multiple, unnecessary225* computations. As a result of changing a calendar field using226* {@code set()}, other calendar fields may also change, depending on the227* calendar field, the calendar field value, and the calendar system. In addition,228* {@code get(f)} will not necessarily return {@code value} set by229* the call to the {@code set} method230* after the calendar fields have been recomputed. The specifics are determined by231* the concrete calendar class.</p>232*233* <p><em>Example</em>: Consider a {@code GregorianCalendar}234* originally set to August 31, 1999. Calling <code>set(Calendar.MONTH,235* Calendar.SEPTEMBER)</code> sets the date to September 31,236* 1999. This is a temporary internal representation that resolves to237* October 1, 1999 if {@code getTime()} is then called. However, a238* call to {@code set(Calendar.DAY_OF_MONTH, 30)} before the call to239* {@code getTime()} sets the date to September 30, 1999, since240* no recomputation occurs after {@code set()} itself.</p>241*242* <p><strong>{@code add(f, delta)}</strong> adds {@code delta}243* to field {@code f}. This is equivalent to calling <code>set(f,244* get(f) + delta)</code> with two adjustments:</p>245*246* <blockquote>247* <p><strong>Add rule 1</strong>. The value of field {@code f}248* after the call minus the value of field {@code f} before the249* call is {@code delta}, modulo any overflow that has occurred in250* field {@code f}. Overflow occurs when a field value exceeds its251* range and, as a result, the next larger field is incremented or252* decremented and the field value is adjusted back into its range.</p>253*254* <p><strong>Add rule 2</strong>. If a smaller field is expected to be255* invariant, but it is impossible for it to be equal to its256* prior value because of changes in its minimum or maximum after field257* {@code f} is changed or other constraints, such as time zone258* offset changes, then its value is adjusted to be as close259* as possible to its expected value. A smaller field represents a260* smaller unit of time. {@code HOUR} is a smaller field than261* {@code DAY_OF_MONTH}. No adjustment is made to smaller fields262* that are not expected to be invariant. The calendar system263* determines what fields are expected to be invariant.</p>264* </blockquote>265*266* <p>In addition, unlike {@code set()}, {@code add()} forces267* an immediate recomputation of the calendar's milliseconds and all268* fields.</p>269*270* <p><em>Example</em>: Consider a {@code GregorianCalendar}271* originally set to August 31, 1999. Calling <code>add(Calendar.MONTH,272* 13)</code> sets the calendar to September 30, 2000. <strong>Add rule273* 1</strong> sets the {@code MONTH} field to September, since274* adding 13 months to August gives September of the next year. Since275* {@code DAY_OF_MONTH} cannot be 31 in September in a276* {@code GregorianCalendar}, <strong>add rule 2</strong> sets the277* {@code DAY_OF_MONTH} to 30, the closest possible value. Although278* it is a smaller field, {@code DAY_OF_WEEK} is not adjusted by279* rule 2, since it is expected to change when the month changes in a280* {@code GregorianCalendar}.</p>281*282* <p><strong>{@code roll(f, delta)}</strong> adds283* {@code delta} to field {@code f} without changing larger284* fields. This is equivalent to calling {@code add(f, delta)} with285* the following adjustment:</p>286*287* <blockquote>288* <p><strong>Roll rule</strong>. Larger fields are unchanged after the289* call. A larger field represents a larger unit of290* time. {@code DAY_OF_MONTH} is a larger field than291* {@code HOUR}.</p>292* </blockquote>293*294* <p><em>Example</em>: See {@link java.util.GregorianCalendar#roll(int, int)}.295*296* <p><strong>Usage model</strong>. To motivate the behavior of297* {@code add()} and {@code roll()}, consider a user interface298* component with increment and decrement buttons for the month, day, and299* year, and an underlying {@code GregorianCalendar}. If the300* interface reads January 31, 1999 and the user presses the month301* increment button, what should it read? If the underlying302* implementation uses {@code set()}, it might read March 3, 1999. A303* better result would be February 28, 1999. Furthermore, if the user304* presses the month increment button again, it should read March 31,305* 1999, not March 28, 1999. By saving the original date and using either306* {@code add()} or {@code roll()}, depending on whether larger307* fields should be affected, the user interface can behave as most users308* will intuitively expect.</p>309*310* @see java.lang.System#currentTimeMillis()311* @see Date312* @see GregorianCalendar313* @see TimeZone314* @see java.text.DateFormat315* @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu316* @since 1.1317*/318public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {319320// Data flow in Calendar321// ---------------------322323// The current time is represented in two ways by Calendar: as UTC324// milliseconds from the epoch (1 January 1970 0:00 UTC), and as local325// fields such as MONTH, HOUR, AM_PM, etc. It is possible to compute the326// millis from the fields, and vice versa. The data needed to do this327// conversion is encapsulated by a TimeZone object owned by the Calendar.328// The data provided by the TimeZone object may also be overridden if the329// user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class330// keeps track of what information was most recently set by the caller, and331// uses that to compute any other information as needed.332333// If the user sets the fields using set(), the data flow is as follows.334// This is implemented by the Calendar subclass's computeTime() method.335// During this process, certain fields may be ignored. The disambiguation336// algorithm for resolving which fields to pay attention to is described337// in the class documentation.338339// local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)340// |341// | Using Calendar-specific algorithm342// V343// local standard millis344// |345// | Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET346// V347// UTC millis (in time data member)348349// If the user sets the UTC millis using setTime() or setTimeInMillis(),350// the data flow is as follows. This is implemented by the Calendar351// subclass's computeFields() method.352353// UTC millis (in time data member)354// |355// | Using TimeZone getOffset()356// V357// local standard millis358// |359// | Using Calendar-specific algorithm360// V361// local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)362363// In general, a round trip from fields, through local and UTC millis, and364// back out to fields is made when necessary. This is implemented by the365// complete() method. Resolving a partial set of fields into a UTC millis366// value allows all remaining fields to be generated from that value. If367// the Calendar is lenient, the fields are also renormalized to standard368// ranges when they are regenerated.369370/**371* Field number for {@code get} and {@code set} indicating the372* era, e.g., AD or BC in the Julian calendar. This is a calendar-specific373* value; see subclass documentation.374*375* @see GregorianCalendar#AD376* @see GregorianCalendar#BC377*/378public static final int ERA = 0;379380/**381* Field number for {@code get} and {@code set} indicating the382* year. This is a calendar-specific value; see subclass documentation.383*/384public static final int YEAR = 1;385386/**387* Field number for {@code get} and {@code set} indicating the388* month. This is a calendar-specific value. The first month of389* the year in the Gregorian and Julian calendars is390* {@code JANUARY} which is 0; the last depends on the number391* of months in a year.392*393* @see #JANUARY394* @see #FEBRUARY395* @see #MARCH396* @see #APRIL397* @see #MAY398* @see #JUNE399* @see #JULY400* @see #AUGUST401* @see #SEPTEMBER402* @see #OCTOBER403* @see #NOVEMBER404* @see #DECEMBER405* @see #UNDECIMBER406*/407public static final int MONTH = 2;408409/**410* Field number for {@code get} and {@code set} indicating the411* week number within the current year. The first week of the year, as412* defined by {@code getFirstDayOfWeek()} and413* {@code getMinimalDaysInFirstWeek()}, has value 1. Subclasses define414* the value of {@code WEEK_OF_YEAR} for days before the first week of415* the year.416*417* @see #getFirstDayOfWeek418* @see #getMinimalDaysInFirstWeek419*/420public static final int WEEK_OF_YEAR = 3;421422/**423* Field number for {@code get} and {@code set} indicating the424* week number within the current month. The first week of the month, as425* defined by {@code getFirstDayOfWeek()} and426* {@code getMinimalDaysInFirstWeek()}, has value 1. Subclasses define427* the value of {@code WEEK_OF_MONTH} for days before the first week of428* the month.429*430* @see #getFirstDayOfWeek431* @see #getMinimalDaysInFirstWeek432*/433public static final int WEEK_OF_MONTH = 4;434435/**436* Field number for {@code get} and {@code set} indicating the437* day of the month. This is a synonym for {@code DAY_OF_MONTH}.438* The first day of the month has value 1.439*440* @see #DAY_OF_MONTH441*/442public static final int DATE = 5;443444/**445* Field number for {@code get} and {@code set} indicating the446* day of the month. This is a synonym for {@code DATE}.447* The first day of the month has value 1.448*449* @see #DATE450*/451public static final int DAY_OF_MONTH = 5;452453/**454* Field number for {@code get} and {@code set} indicating the day455* number within the current year. The first day of the year has value 1.456*/457public static final int DAY_OF_YEAR = 6;458459/**460* Field number for {@code get} and {@code set} indicating the day461* of the week. This field takes values {@code SUNDAY},462* {@code MONDAY}, {@code TUESDAY}, {@code WEDNESDAY},463* {@code THURSDAY}, {@code FRIDAY}, and {@code SATURDAY}.464*465* @see #SUNDAY466* @see #MONDAY467* @see #TUESDAY468* @see #WEDNESDAY469* @see #THURSDAY470* @see #FRIDAY471* @see #SATURDAY472*/473public static final int DAY_OF_WEEK = 7;474475/**476* Field number for {@code get} and {@code set} indicating the477* ordinal number of the day of the week within the current month. Together478* with the {@code DAY_OF_WEEK} field, this uniquely specifies a day479* within a month. Unlike {@code WEEK_OF_MONTH} and480* {@code WEEK_OF_YEAR}, this field's value does <em>not</em> depend on481* {@code getFirstDayOfWeek()} or482* {@code getMinimalDaysInFirstWeek()}. {@code DAY_OF_MONTH 1}483* through {@code 7} always correspond to <code>DAY_OF_WEEK_IN_MONTH484* 1</code>; {@code 8} through {@code 14} correspond to485* {@code DAY_OF_WEEK_IN_MONTH 2}, and so on.486* {@code DAY_OF_WEEK_IN_MONTH 0} indicates the week before487* {@code DAY_OF_WEEK_IN_MONTH 1}. Negative values count back from the488* end of the month, so the last Sunday of a month is specified as489* {@code DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1}. Because490* negative values count backward they will usually be aligned differently491* within the month than positive values. For example, if a month has 31492* days, {@code DAY_OF_WEEK_IN_MONTH -1} will overlap493* {@code DAY_OF_WEEK_IN_MONTH 5} and the end of {@code 4}.494*495* @see #DAY_OF_WEEK496* @see #WEEK_OF_MONTH497*/498public static final int DAY_OF_WEEK_IN_MONTH = 8;499500/**501* Field number for {@code get} and {@code set} indicating502* whether the {@code HOUR} is before or after noon.503* E.g., at 10:04:15.250 PM the {@code AM_PM} is {@code PM}.504*505* @see #AM506* @see #PM507* @see #HOUR508*/509public static final int AM_PM = 9;510511/**512* Field number for {@code get} and {@code set} indicating the513* hour of the morning or afternoon. {@code HOUR} is used for the514* 12-hour clock (0 - 11). Noon and midnight are represented by 0, not by 12.515* E.g., at 10:04:15.250 PM the {@code HOUR} is 10.516*517* @see #AM_PM518* @see #HOUR_OF_DAY519*/520public static final int HOUR = 10;521522/**523* Field number for {@code get} and {@code set} indicating the524* hour of the day. {@code HOUR_OF_DAY} is used for the 24-hour clock.525* E.g., at 10:04:15.250 PM the {@code HOUR_OF_DAY} is 22.526*527* @see #HOUR528*/529public static final int HOUR_OF_DAY = 11;530531/**532* Field number for {@code get} and {@code set} indicating the533* minute within the hour.534* E.g., at 10:04:15.250 PM the {@code MINUTE} is 4.535*/536public static final int MINUTE = 12;537538/**539* Field number for {@code get} and {@code set} indicating the540* second within the minute.541* E.g., at 10:04:15.250 PM the {@code SECOND} is 15.542*/543public static final int SECOND = 13;544545/**546* Field number for {@code get} and {@code set} indicating the547* millisecond within the second.548* E.g., at 10:04:15.250 PM the {@code MILLISECOND} is 250.549*/550public static final int MILLISECOND = 14;551552/**553* Field number for {@code get} and {@code set}554* indicating the raw offset from GMT in milliseconds.555* <p>556* This field reflects the correct GMT offset value of the time557* zone of this {@code Calendar} if the558* {@code TimeZone} implementation subclass supports559* historical GMT offset changes.560*/561public static final int ZONE_OFFSET = 15;562563/**564* Field number for {@code get} and {@code set} indicating the565* daylight saving offset in milliseconds.566* <p>567* This field reflects the correct daylight saving offset value of568* the time zone of this {@code Calendar} if the569* {@code TimeZone} implementation subclass supports570* historical Daylight Saving Time schedule changes.571*/572public static final int DST_OFFSET = 16;573574/**575* The number of distinct fields recognized by {@code get} and {@code set}.576* Field numbers range from {@code 0..FIELD_COUNT-1}.577*/578public static final int FIELD_COUNT = 17;579580/**581* Value of the {@link #DAY_OF_WEEK} field indicating582* Sunday.583*/584public static final int SUNDAY = 1;585586/**587* Value of the {@link #DAY_OF_WEEK} field indicating588* Monday.589*/590public static final int MONDAY = 2;591592/**593* Value of the {@link #DAY_OF_WEEK} field indicating594* Tuesday.595*/596public static final int TUESDAY = 3;597598/**599* Value of the {@link #DAY_OF_WEEK} field indicating600* Wednesday.601*/602public static final int WEDNESDAY = 4;603604/**605* Value of the {@link #DAY_OF_WEEK} field indicating606* Thursday.607*/608public static final int THURSDAY = 5;609610/**611* Value of the {@link #DAY_OF_WEEK} field indicating612* Friday.613*/614public static final int FRIDAY = 6;615616/**617* Value of the {@link #DAY_OF_WEEK} field indicating618* Saturday.619*/620public static final int SATURDAY = 7;621622/**623* Value of the {@link #MONTH} field indicating the624* first month of the year in the Gregorian and Julian calendars.625*/626public static final int JANUARY = 0;627628/**629* Value of the {@link #MONTH} field indicating the630* second month of the year in the Gregorian and Julian calendars.631*/632public static final int FEBRUARY = 1;633634/**635* Value of the {@link #MONTH} field indicating the636* third month of the year in the Gregorian and Julian calendars.637*/638public static final int MARCH = 2;639640/**641* Value of the {@link #MONTH} field indicating the642* fourth month of the year in the Gregorian and Julian calendars.643*/644public static final int APRIL = 3;645646/**647* Value of the {@link #MONTH} field indicating the648* fifth month of the year in the Gregorian and Julian calendars.649*/650public static final int MAY = 4;651652/**653* Value of the {@link #MONTH} field indicating the654* sixth month of the year in the Gregorian and Julian calendars.655*/656public static final int JUNE = 5;657658/**659* Value of the {@link #MONTH} field indicating the660* seventh month of the year in the Gregorian and Julian calendars.661*/662public static final int JULY = 6;663664/**665* Value of the {@link #MONTH} field indicating the666* eighth month of the year in the Gregorian and Julian calendars.667*/668public static final int AUGUST = 7;669670/**671* Value of the {@link #MONTH} field indicating the672* ninth month of the year in the Gregorian and Julian calendars.673*/674public static final int SEPTEMBER = 8;675676/**677* Value of the {@link #MONTH} field indicating the678* tenth month of the year in the Gregorian and Julian calendars.679*/680public static final int OCTOBER = 9;681682/**683* Value of the {@link #MONTH} field indicating the684* eleventh month of the year in the Gregorian and Julian calendars.685*/686public static final int NOVEMBER = 10;687688/**689* Value of the {@link #MONTH} field indicating the690* twelfth month of the year in the Gregorian and Julian calendars.691*/692public static final int DECEMBER = 11;693694/**695* Value of the {@link #MONTH} field indicating the696* thirteenth month of the year. Although {@code GregorianCalendar}697* does not use this value, lunar calendars do.698*/699public static final int UNDECIMBER = 12;700701/**702* Value of the {@link #AM_PM} field indicating the703* period of the day from midnight to just before noon.704*/705public static final int AM = 0;706707/**708* Value of the {@link #AM_PM} field indicating the709* period of the day from noon to just before midnight.710*/711public static final int PM = 1;712713/**714* A style specifier for {@link #getDisplayNames(int, int, Locale)715* getDisplayNames} indicating names in all styles, such as716* "January" and "Jan".717*718* @see #SHORT_FORMAT719* @see #LONG_FORMAT720* @see #SHORT_STANDALONE721* @see #LONG_STANDALONE722* @see #SHORT723* @see #LONG724* @since 1.6725*/726public static final int ALL_STYLES = 0;727728static final int STANDALONE_MASK = 0x8000;729730/**731* A style specifier for {@link #getDisplayName(int, int, Locale)732* getDisplayName} and {@link #getDisplayNames(int, int, Locale)733* getDisplayNames} equivalent to {@link #SHORT_FORMAT}.734*735* @see #SHORT_STANDALONE736* @see #LONG737* @since 1.6738*/739public static final int SHORT = 1;740741/**742* A style specifier for {@link #getDisplayName(int, int, Locale)743* getDisplayName} and {@link #getDisplayNames(int, int, Locale)744* getDisplayNames} equivalent to {@link #LONG_FORMAT}.745*746* @see #LONG_STANDALONE747* @see #SHORT748* @since 1.6749*/750public static final int LONG = 2;751752/**753* A style specifier for {@link #getDisplayName(int, int, Locale)754* getDisplayName} and {@link #getDisplayNames(int, int, Locale)755* getDisplayNames} indicating a narrow name used for format. Narrow names756* are typically single character strings, such as "M" for Monday.757*758* @see #NARROW_STANDALONE759* @see #SHORT_FORMAT760* @see #LONG_FORMAT761* @since 1.8762*/763public static final int NARROW_FORMAT = 4;764765/**766* A style specifier for {@link #getDisplayName(int, int, Locale)767* getDisplayName} and {@link #getDisplayNames(int, int, Locale)768* getDisplayNames} indicating a narrow name independently. Narrow names769* are typically single character strings, such as "M" for Monday.770*771* @see #NARROW_FORMAT772* @see #SHORT_STANDALONE773* @see #LONG_STANDALONE774* @since 1.8775*/776public static final int NARROW_STANDALONE = NARROW_FORMAT | STANDALONE_MASK;777778/**779* A style specifier for {@link #getDisplayName(int, int, Locale)780* getDisplayName} and {@link #getDisplayNames(int, int, Locale)781* getDisplayNames} indicating a short name used for format.782*783* @see #SHORT_STANDALONE784* @see #LONG_FORMAT785* @see #LONG_STANDALONE786* @since 1.8787*/788public static final int SHORT_FORMAT = 1;789790/**791* A style specifier for {@link #getDisplayName(int, int, Locale)792* getDisplayName} and {@link #getDisplayNames(int, int, Locale)793* getDisplayNames} indicating a long name used for format.794*795* @see #LONG_STANDALONE796* @see #SHORT_FORMAT797* @see #SHORT_STANDALONE798* @since 1.8799*/800public static final int LONG_FORMAT = 2;801802/**803* A style specifier for {@link #getDisplayName(int, int, Locale)804* getDisplayName} and {@link #getDisplayNames(int, int, Locale)805* getDisplayNames} indicating a short name used independently,806* such as a month abbreviation as calendar headers.807*808* @see #SHORT_FORMAT809* @see #LONG_FORMAT810* @see #LONG_STANDALONE811* @since 1.8812*/813public static final int SHORT_STANDALONE = SHORT | STANDALONE_MASK;814815/**816* A style specifier for {@link #getDisplayName(int, int, Locale)817* getDisplayName} and {@link #getDisplayNames(int, int, Locale)818* getDisplayNames} indicating a long name used independently,819* such as a month name as calendar headers.820*821* @see #LONG_FORMAT822* @see #SHORT_FORMAT823* @see #SHORT_STANDALONE824* @since 1.8825*/826public static final int LONG_STANDALONE = LONG | STANDALONE_MASK;827828// Internal notes:829// Calendar contains two kinds of time representations: current "time" in830// milliseconds, and a set of calendar "fields" representing the current time.831// The two representations are usually in sync, but can get out of sync832// as follows.833// 1. Initially, no fields are set, and the time is invalid.834// 2. If the time is set, all fields are computed and in sync.835// 3. If a single field is set, the time is invalid.836// Recomputation of the time and fields happens when the object needs837// to return a result to the user, or use a result for a computation.838839/**840* The calendar field values for the currently set time for this calendar.841* This is an array of {@code FIELD_COUNT} integers, with index values842* {@code ERA} through {@code DST_OFFSET}.843* @serial844*/845@SuppressWarnings("ProtectedField")846protected int fields[];847848/**849* The flags which tell if a specified calendar field for the calendar is set.850* A new object has no fields set. After the first call to a method851* which generates the fields, they all remain set after that.852* This is an array of {@code FIELD_COUNT} booleans, with index values853* {@code ERA} through {@code DST_OFFSET}.854* @serial855*/856@SuppressWarnings("ProtectedField")857protected boolean isSet[];858859/**860* Pseudo-time-stamps which specify when each field was set. There861* are two special values, UNSET and COMPUTED. Values from862* MINIMUM_USER_SET to Integer.MAX_VALUE are legal user set values.863*/864private transient int stamp[];865866/**867* The currently set time for this calendar, expressed in milliseconds after868* January 1, 1970, 0:00:00 GMT.869* @see #isTimeSet870* @serial871*/872@SuppressWarnings("ProtectedField")873protected long time;874875/**876* True if then the value of {@code time} is valid.877* The time is made invalid by a change to an item of {@code field[]}.878* @see #time879* @serial880*/881@SuppressWarnings("ProtectedField")882protected boolean isTimeSet;883884/**885* True if {@code fields[]} are in sync with the currently set time.886* If false, then the next attempt to get the value of a field will887* force a recomputation of all fields from the current value of888* {@code time}.889* @serial890*/891@SuppressWarnings("ProtectedField")892protected boolean areFieldsSet;893894/**895* True if all fields have been set.896* @serial897*/898transient boolean areAllFieldsSet;899900/**901* {@code True} if this calendar allows out-of-range field values during computation902* of {@code time} from {@code fields[]}.903* @see #setLenient904* @see #isLenient905* @serial906*/907private boolean lenient = true;908909/**910* The {@code TimeZone} used by this calendar. {@code Calendar}911* uses the time zone data to translate between locale and GMT time.912* @serial913*/914private TimeZone zone;915916/**917* {@code True} if zone references to a shared TimeZone object.918*/919private transient boolean sharedZone = false;920921/**922* The first day of the week, with possible values {@code SUNDAY},923* {@code MONDAY}, etc. This is a locale-dependent value.924* @serial925*/926private int firstDayOfWeek;927928/**929* The number of days required for the first week in a month or year,930* with possible values from 1 to 7. This is a locale-dependent value.931* @serial932*/933private int minimalDaysInFirstWeek;934935/**936* Cache to hold the firstDayOfWeek and minimalDaysInFirstWeek937* of a Locale.938*/939private static final ConcurrentMap<Locale, int[]> cachedLocaleData940= new ConcurrentHashMap<>(3);941942// Special values of stamp[]943/**944* The corresponding fields[] has no value.945*/946private static final int UNSET = 0;947948/**949* The value of the corresponding fields[] has been calculated internally.950*/951private static final int COMPUTED = 1;952953/**954* The value of the corresponding fields[] has been set externally. Stamp955* values which are greater than 1 represents the (pseudo) time when the956* corresponding fields[] value was set.957*/958private static final int MINIMUM_USER_STAMP = 2;959960/**961* The mask value that represents all of the fields.962*/963static final int ALL_FIELDS = (1 << FIELD_COUNT) - 1;964965/**966* The next available value for {@code stamp[]}, an internal array.967* This actually should not be written out to the stream, and will probably968* be removed from the stream in the near future. In the meantime,969* a value of {@code MINIMUM_USER_STAMP} should be used.970* @serial971*/972private int nextStamp = MINIMUM_USER_STAMP;973974// the internal serial version which says which version was written975// - 0 (default) for version up to JDK 1.1.5976// - 1 for version from JDK 1.1.6, which writes a correct 'time' value977// as well as compatible values for other fields. This is a978// transitional format.979// - 2 (not implemented yet) a future version, in which fields[],980// areFieldsSet, and isTimeSet become transient, and isSet[] is981// removed. In JDK 1.1.6 we write a format compatible with version 2.982static final int currentSerialVersion = 1;983984/**985* The version of the serialized data on the stream. Possible values:986* <dl>987* <dt><b>0</b> or not present on stream</dt>988* <dd>989* JDK 1.1.5 or earlier.990* </dd>991* <dt><b>1</b></dt>992* <dd>993* JDK 1.1.6 or later. Writes a correct 'time' value994* as well as compatible values for other fields. This is a995* transitional format.996* </dd>997* </dl>998* When streaming out this class, the most recent format999* and the highest allowable {@code serialVersionOnStream}1000* is written.1001* @serial1002* @since 1.1.61003*/1004private int serialVersionOnStream = currentSerialVersion;10051006// Proclaim serialization compatibility with JDK 1.11007@java.io.Serial1008static final long serialVersionUID = -1807547505821590642L;10091010// Mask values for calendar fields1011@SuppressWarnings("PointlessBitwiseExpression")1012static final int ERA_MASK = (1 << ERA);1013static final int YEAR_MASK = (1 << YEAR);1014static final int MONTH_MASK = (1 << MONTH);1015static final int WEEK_OF_YEAR_MASK = (1 << WEEK_OF_YEAR);1016static final int WEEK_OF_MONTH_MASK = (1 << WEEK_OF_MONTH);1017static final int DAY_OF_MONTH_MASK = (1 << DAY_OF_MONTH);1018static final int DATE_MASK = DAY_OF_MONTH_MASK;1019static final int DAY_OF_YEAR_MASK = (1 << DAY_OF_YEAR);1020static final int DAY_OF_WEEK_MASK = (1 << DAY_OF_WEEK);1021static final int DAY_OF_WEEK_IN_MONTH_MASK = (1 << DAY_OF_WEEK_IN_MONTH);1022static final int AM_PM_MASK = (1 << AM_PM);1023static final int HOUR_MASK = (1 << HOUR);1024static final int HOUR_OF_DAY_MASK = (1 << HOUR_OF_DAY);1025static final int MINUTE_MASK = (1 << MINUTE);1026static final int SECOND_MASK = (1 << SECOND);1027static final int MILLISECOND_MASK = (1 << MILLISECOND);1028static final int ZONE_OFFSET_MASK = (1 << ZONE_OFFSET);1029static final int DST_OFFSET_MASK = (1 << DST_OFFSET);10301031/**1032* {@code Calendar.Builder} is used for creating a {@code Calendar} from1033* various date-time parameters.1034*1035* <p>There are two ways to set a {@code Calendar} to a date-time value. One1036* is to set the instant parameter to a millisecond offset from the <a1037* href="Calendar.html#Epoch">Epoch</a>. The other is to set individual1038* field parameters, such as {@link Calendar#YEAR YEAR}, to their desired1039* values. These two ways can't be mixed. Trying to set both the instant and1040* individual fields will cause an {@link IllegalStateException} to be1041* thrown. However, it is permitted to override previous values of the1042* instant or field parameters.1043*1044* <p>If no enough field parameters are given for determining date and/or1045* time, calendar specific default values are used when building a1046* {@code Calendar}. For example, if the {@link Calendar#YEAR YEAR} value1047* isn't given for the Gregorian calendar, 1970 will be used. If there are1048* any conflicts among field parameters, the <a1049* href="Calendar.html#resolution"> resolution rules</a> are applied.1050* Therefore, the order of field setting matters.1051*1052* <p>In addition to the date-time parameters,1053* the {@linkplain #setLocale(Locale) locale},1054* {@linkplain #setTimeZone(TimeZone) time zone},1055* {@linkplain #setWeekDefinition(int, int) week definition}, and1056* {@linkplain #setLenient(boolean) leniency mode} parameters can be set.1057*1058* <p><b>Examples</b>1059* <p>The following are sample usages. Sample code assumes that the1060* {@code Calendar} constants are statically imported.1061*1062* <p>The following code produces a {@code Calendar} with date 2012-12-311063* (Gregorian) because Monday is the first day of a week with the <a1064* href="GregorianCalendar.html#iso8601_compatible_setting"> ISO 86011065* compatible week parameters</a>.1066* <pre>1067* Calendar cal = new Calendar.Builder().setCalendarType("iso8601")1068* .setWeekDate(2013, 1, MONDAY).build();</pre>1069* <p>The following code produces a Japanese {@code Calendar} with date1070* 1989-01-08 (Gregorian), assuming that the default {@link Calendar#ERA ERA}1071* is <em>Heisei</em> that started on that day.1072* <pre>1073* Calendar cal = new Calendar.Builder().setCalendarType("japanese")1074* .setFields(YEAR, 1, DAY_OF_YEAR, 1).build();</pre>1075*1076* @since 1.81077* @see Calendar#getInstance(TimeZone, Locale)1078* @see Calendar#fields1079*/1080public static class Builder {1081private static final int NFIELDS = FIELD_COUNT + 1; // +1 for WEEK_YEAR1082private static final int WEEK_YEAR = FIELD_COUNT;10831084private long instant;1085// Calendar.stamp[] (lower half) and Calendar.fields[] (upper half) combined1086private int[] fields;1087// Pseudo timestamp starting from MINIMUM_USER_STAMP.1088// (COMPUTED is used to indicate that the instant has been set.)1089private int nextStamp;1090// maxFieldIndex keeps the max index of fields which have been set.1091// (WEEK_YEAR is never included.)1092private int maxFieldIndex;1093private String type;1094private TimeZone zone;1095private boolean lenient = true;1096private Locale locale;1097private int firstDayOfWeek, minimalDaysInFirstWeek;10981099/**1100* Constructs a {@code Calendar.Builder}.1101*/1102public Builder() {1103}11041105/**1106* Sets the instant parameter to the given {@code instant} value that is1107* a millisecond offset from <a href="Calendar.html#Epoch">the1108* Epoch</a>.1109*1110* @param instant a millisecond offset from the Epoch1111* @return this {@code Calendar.Builder}1112* @throws IllegalStateException if any of the field parameters have1113* already been set1114* @see Calendar#setTime(Date)1115* @see Calendar#setTimeInMillis(long)1116* @see Calendar#time1117*/1118public Builder setInstant(long instant) {1119if (fields != null) {1120throw new IllegalStateException();1121}1122this.instant = instant;1123nextStamp = COMPUTED;1124return this;1125}11261127/**1128* Sets the instant parameter to the {@code instant} value given by a1129* {@link Date}. This method is equivalent to a call to1130* {@link #setInstant(long) setInstant(instant.getTime())}.1131*1132* @param instant a {@code Date} representing a millisecond offset from1133* the Epoch1134* @return this {@code Calendar.Builder}1135* @throws NullPointerException if {@code instant} is {@code null}1136* @throws IllegalStateException if any of the field parameters have1137* already been set1138* @see Calendar#setTime(Date)1139* @see Calendar#setTimeInMillis(long)1140* @see Calendar#time1141*/1142public Builder setInstant(Date instant) {1143return setInstant(instant.getTime()); // NPE if instant == null1144}11451146/**1147* Sets the {@code field} parameter to the given {@code value}.1148* {@code field} is an index to the {@link Calendar#fields}, such as1149* {@link Calendar#DAY_OF_MONTH DAY_OF_MONTH}. Field value validation is1150* not performed in this method. Any out of range values are either1151* normalized in lenient mode or detected as an invalid value in1152* non-lenient mode when building a {@code Calendar}.1153*1154* @param field an index to the {@code Calendar} fields1155* @param value the field value1156* @return this {@code Calendar.Builder}1157* @throws IllegalArgumentException if {@code field} is invalid1158* @throws IllegalStateException if the instant value has already been set,1159* or if fields have been set too many1160* (approximately {@link Integer#MAX_VALUE}) times.1161* @see Calendar#set(int, int)1162*/1163public Builder set(int field, int value) {1164// Note: WEEK_YEAR can't be set with this method.1165if (field < 0 || field >= FIELD_COUNT) {1166throw new IllegalArgumentException("field is invalid");1167}1168if (isInstantSet()) {1169throw new IllegalStateException("instant has been set");1170}1171allocateFields();1172internalSet(field, value);1173return this;1174}11751176/**1177* Sets field parameters to their values given by1178* {@code fieldValuePairs} that are pairs of a field and its value.1179* For example,1180* <pre>1181* setFields(Calendar.YEAR, 2013,1182* Calendar.MONTH, Calendar.DECEMBER,1183* Calendar.DAY_OF_MONTH, 23);</pre>1184* is equivalent to the sequence of the following1185* {@link #set(int, int) set} calls:1186* <pre>1187* set(Calendar.YEAR, 2013)1188* .set(Calendar.MONTH, Calendar.DECEMBER)1189* .set(Calendar.DAY_OF_MONTH, 23);</pre>1190*1191* @param fieldValuePairs field-value pairs1192* @return this {@code Calendar.Builder}1193* @throws NullPointerException if {@code fieldValuePairs} is {@code null}1194* @throws IllegalArgumentException if any of fields are invalid,1195* or if {@code fieldValuePairs.length} is an odd number.1196* @throws IllegalStateException if the instant value has been set,1197* or if fields have been set too many (approximately1198* {@link Integer#MAX_VALUE}) times.1199*/1200public Builder setFields(int... fieldValuePairs) {1201int len = fieldValuePairs.length;1202if ((len % 2) != 0) {1203throw new IllegalArgumentException();1204}1205if (isInstantSet()) {1206throw new IllegalStateException("instant has been set");1207}1208if ((nextStamp + len / 2) < 0) {1209throw new IllegalStateException("stamp counter overflow");1210}1211allocateFields();1212for (int i = 0; i < len; ) {1213int field = fieldValuePairs[i++];1214// Note: WEEK_YEAR can't be set with this method.1215if (field < 0 || field >= FIELD_COUNT) {1216throw new IllegalArgumentException("field is invalid");1217}1218internalSet(field, fieldValuePairs[i++]);1219}1220return this;1221}12221223/**1224* Sets the date field parameters to the values given by {@code year},1225* {@code month}, and {@code dayOfMonth}. This method is equivalent to1226* a call to:1227* <pre>1228* setFields(Calendar.YEAR, year,1229* Calendar.MONTH, month,1230* Calendar.DAY_OF_MONTH, dayOfMonth);</pre>1231*1232* @param year the {@link Calendar#YEAR YEAR} value1233* @param month the {@link Calendar#MONTH MONTH} value1234* (the month numbering is <em>0-based</em>).1235* @param dayOfMonth the {@link Calendar#DAY_OF_MONTH DAY_OF_MONTH} value1236* @return this {@code Calendar.Builder}1237*/1238public Builder setDate(int year, int month, int dayOfMonth) {1239return setFields(YEAR, year, MONTH, month, DAY_OF_MONTH, dayOfMonth);1240}12411242/**1243* Sets the time of day field parameters to the values given by1244* {@code hourOfDay}, {@code minute}, and {@code second}. This method is1245* equivalent to a call to:1246* <pre>1247* setTimeOfDay(hourOfDay, minute, second, 0);</pre>1248*1249* @param hourOfDay the {@link Calendar#HOUR_OF_DAY HOUR_OF_DAY} value1250* (24-hour clock)1251* @param minute the {@link Calendar#MINUTE MINUTE} value1252* @param second the {@link Calendar#SECOND SECOND} value1253* @return this {@code Calendar.Builder}1254*/1255public Builder setTimeOfDay(int hourOfDay, int minute, int second) {1256return setTimeOfDay(hourOfDay, minute, second, 0);1257}12581259/**1260* Sets the time of day field parameters to the values given by1261* {@code hourOfDay}, {@code minute}, {@code second}, and1262* {@code millis}. This method is equivalent to a call to:1263* <pre>1264* setFields(Calendar.HOUR_OF_DAY, hourOfDay,1265* Calendar.MINUTE, minute,1266* Calendar.SECOND, second,1267* Calendar.MILLISECOND, millis);</pre>1268*1269* @param hourOfDay the {@link Calendar#HOUR_OF_DAY HOUR_OF_DAY} value1270* (24-hour clock)1271* @param minute the {@link Calendar#MINUTE MINUTE} value1272* @param second the {@link Calendar#SECOND SECOND} value1273* @param millis the {@link Calendar#MILLISECOND MILLISECOND} value1274* @return this {@code Calendar.Builder}1275*/1276public Builder setTimeOfDay(int hourOfDay, int minute, int second, int millis) {1277return setFields(HOUR_OF_DAY, hourOfDay, MINUTE, minute,1278SECOND, second, MILLISECOND, millis);1279}12801281/**1282* Sets the week-based date parameters to the values with the given1283* date specifiers - week year, week of year, and day of week.1284*1285* <p>If the specified calendar doesn't support week dates, the1286* {@link #build() build} method will throw an {@link IllegalArgumentException}.1287*1288* @param weekYear the week year1289* @param weekOfYear the week number based on {@code weekYear}1290* @param dayOfWeek the day of week value: one of the constants1291* for the {@link Calendar#DAY_OF_WEEK DAY_OF_WEEK} field:1292* {@link Calendar#SUNDAY SUNDAY}, ..., {@link Calendar#SATURDAY SATURDAY}.1293* @return this {@code Calendar.Builder}1294* @see Calendar#setWeekDate(int, int, int)1295* @see Calendar#isWeekDateSupported()1296*/1297public Builder setWeekDate(int weekYear, int weekOfYear, int dayOfWeek) {1298allocateFields();1299internalSet(WEEK_YEAR, weekYear);1300internalSet(WEEK_OF_YEAR, weekOfYear);1301internalSet(DAY_OF_WEEK, dayOfWeek);1302return this;1303}13041305/**1306* Sets the time zone parameter to the given {@code zone}. If no time1307* zone parameter is given to this {@code Calendar.Builder}, the1308* {@linkplain TimeZone#getDefault() default1309* {@code TimeZone}} will be used in the {@link #build() build}1310* method.1311*1312* @param zone the {@link TimeZone}1313* @return this {@code Calendar.Builder}1314* @throws NullPointerException if {@code zone} is {@code null}1315* @see Calendar#setTimeZone(TimeZone)1316*/1317public Builder setTimeZone(TimeZone zone) {1318if (zone == null) {1319throw new NullPointerException();1320}1321this.zone = zone;1322return this;1323}13241325/**1326* Sets the lenient mode parameter to the value given by {@code lenient}.1327* If no lenient parameter is given to this {@code Calendar.Builder},1328* lenient mode will be used in the {@link #build() build} method.1329*1330* @param lenient {@code true} for lenient mode;1331* {@code false} for non-lenient mode1332* @return this {@code Calendar.Builder}1333* @see Calendar#setLenient(boolean)1334*/1335public Builder setLenient(boolean lenient) {1336this.lenient = lenient;1337return this;1338}13391340/**1341* Sets the calendar type parameter to the given {@code type}. The1342* calendar type given by this method has precedence over any explicit1343* or implicit calendar type given by the1344* {@linkplain #setLocale(Locale) locale}.1345*1346* <p>In addition to the available calendar types returned by the1347* {@link Calendar#getAvailableCalendarTypes() Calendar.getAvailableCalendarTypes}1348* method, {@code "gregorian"} and {@code "iso8601"} as aliases of1349* {@code "gregory"} can be used with this method.1350*1351* @param type the calendar type1352* @return this {@code Calendar.Builder}1353* @throws NullPointerException if {@code type} is {@code null}1354* @throws IllegalArgumentException if {@code type} is unknown1355* @throws IllegalStateException if another calendar type has already been set1356* @see Calendar#getCalendarType()1357* @see Calendar#getAvailableCalendarTypes()1358*/1359public Builder setCalendarType(String type) {1360if (type.equals("gregorian")) { // NPE if type == null1361type = "gregory";1362}1363if (!Calendar.getAvailableCalendarTypes().contains(type)1364&& !type.equals("iso8601")) {1365throw new IllegalArgumentException("unknown calendar type: " + type);1366}1367if (this.type == null) {1368this.type = type;1369} else {1370if (!this.type.equals(type)) {1371throw new IllegalStateException("calendar type override");1372}1373}1374return this;1375}13761377/**1378* Sets the locale parameter to the given {@code locale}. If no locale1379* is given to this {@code Calendar.Builder}, the {@linkplain1380* Locale#getDefault(Locale.Category) default {@code Locale}}1381* for {@link Locale.Category#FORMAT} will be used.1382*1383* <p>If no calendar type is explicitly given by a call to the1384* {@link #setCalendarType(String) setCalendarType} method,1385* the {@code Locale} value is used to determine what type of1386* {@code Calendar} to be built.1387*1388* <p>If no week definition parameters are explicitly given by a call to1389* the {@link #setWeekDefinition(int,int) setWeekDefinition} method, the1390* {@code Locale}'s default values are used.1391*1392* @param locale the {@link Locale}1393* @throws NullPointerException if {@code locale} is {@code null}1394* @return this {@code Calendar.Builder}1395* @see Calendar#getInstance(Locale)1396*/1397public Builder setLocale(Locale locale) {1398if (locale == null) {1399throw new NullPointerException();1400}1401this.locale = locale;1402return this;1403}14041405/**1406* Sets the week definition parameters to the values given by1407* {@code firstDayOfWeek} and {@code minimalDaysInFirstWeek} that are1408* used to determine the <a href="Calendar.html#first_week">first1409* week</a> of a year. The parameters given by this method have1410* precedence over the default values given by the1411* {@linkplain #setLocale(Locale) locale}.1412*1413* @param firstDayOfWeek the first day of a week; one of1414* {@link Calendar#SUNDAY} to {@link Calendar#SATURDAY}1415* @param minimalDaysInFirstWeek the minimal number of days in the first1416* week (1..7)1417* @return this {@code Calendar.Builder}1418* @throws IllegalArgumentException if {@code firstDayOfWeek} or1419* {@code minimalDaysInFirstWeek} is invalid1420* @see Calendar#getFirstDayOfWeek()1421* @see Calendar#getMinimalDaysInFirstWeek()1422*/1423public Builder setWeekDefinition(int firstDayOfWeek, int minimalDaysInFirstWeek) {1424if (!isValidWeekParameter(firstDayOfWeek)1425|| !isValidWeekParameter(minimalDaysInFirstWeek)) {1426throw new IllegalArgumentException();1427}1428this.firstDayOfWeek = firstDayOfWeek;1429this.minimalDaysInFirstWeek = minimalDaysInFirstWeek;1430return this;1431}14321433/**1434* Returns a {@code Calendar} built from the parameters set by the1435* setter methods. The calendar type given by the {@link #setCalendarType(String)1436* setCalendarType} method or the {@linkplain #setLocale(Locale) locale} is1437* used to determine what {@code Calendar} to be created. If no explicit1438* calendar type is given, the locale's default calendar is created.1439*1440* <p>If the calendar type is {@code "iso8601"}, the1441* {@linkplain GregorianCalendar#setGregorianChange(Date) Gregorian change date}1442* of a {@link GregorianCalendar} is set to {@code Date(Long.MIN_VALUE)}1443* to be the <em>proleptic</em> Gregorian calendar. Its week definition1444* parameters are also set to be <a1445* href="GregorianCalendar.html#iso8601_compatible_setting">compatible1446* with the ISO 8601 standard</a>. Note that the1447* {@link GregorianCalendar#getCalendarType() getCalendarType} method of1448* a {@code GregorianCalendar} created with {@code "iso8601"} returns1449* {@code "gregory"}.1450*1451* <p>The default values are used for locale and time zone if these1452* parameters haven't been given explicitly.1453* <p>1454* If the locale contains the time zone with "tz"1455* <a href="Locale.html#def_locale_extension">Unicode extension</a>,1456* and time zone hasn't been given explicitly, time zone in the locale1457* is used.1458*1459* <p>Any out of range field values are either normalized in lenient1460* mode or detected as an invalid value in non-lenient mode.1461*1462* @return a {@code Calendar} built with parameters of this {@code1463* Calendar.Builder}1464* @throws IllegalArgumentException if the calendar type is unknown, or1465* if any invalid field values are given in non-lenient mode, or1466* if a week date is given for the calendar type that doesn't1467* support week dates.1468* @see Calendar#getInstance(TimeZone, Locale)1469* @see Locale#getDefault(Locale.Category)1470* @see TimeZone#getDefault()1471*/1472public Calendar build() {1473if (locale == null) {1474locale = Locale.getDefault();1475}1476if (zone == null) {1477zone = defaultTimeZone(locale);1478}1479if (type == null) {1480type = locale.getUnicodeLocaleType("ca");1481}1482if (type == null) {1483if (locale.getCountry() == "TH"1484&& locale.getLanguage() == "th") {1485type = "buddhist";1486} else {1487type = "gregory";1488}1489}1490final Calendar cal = switch (type) {1491case "gregory" -> new GregorianCalendar(zone, locale, true);1492case "iso8601" -> {1493GregorianCalendar gcal = new GregorianCalendar(zone, locale, true);1494// make gcal a proleptic Gregorian1495gcal.setGregorianChange(new Date(Long.MIN_VALUE));1496// and week definition to be compatible with ISO 86011497setWeekDefinition(MONDAY, 4);1498yield gcal;1499}1500case "buddhist" -> {1501var buddhistCalendar = new BuddhistCalendar(zone, locale);1502buddhistCalendar.clear();1503yield buddhistCalendar;1504}1505case "japanese" -> new JapaneseImperialCalendar(zone, locale, true);1506default -> throw new IllegalArgumentException("unknown calendar type: " + type);1507};1508cal.setLenient(lenient);1509if (firstDayOfWeek != 0) {1510cal.setFirstDayOfWeek(firstDayOfWeek);1511cal.setMinimalDaysInFirstWeek(minimalDaysInFirstWeek);1512}1513if (isInstantSet()) {1514cal.setTimeInMillis(instant);1515cal.complete();1516return cal;1517}15181519if (fields != null) {1520boolean weekDate = isSet(WEEK_YEAR)1521&& fields[WEEK_YEAR] > fields[YEAR];1522if (weekDate && !cal.isWeekDateSupported()) {1523throw new IllegalArgumentException("week date is unsupported by " + type);1524}15251526// Set the fields from the min stamp to the max stamp so that1527// the fields resolution works in the Calendar.1528for (int stamp = MINIMUM_USER_STAMP; stamp < nextStamp; stamp++) {1529for (int index = 0; index <= maxFieldIndex; index++) {1530if (fields[index] == stamp) {1531cal.set(index, fields[NFIELDS + index]);1532break;1533}1534}1535}15361537if (weekDate) {1538int weekOfYear = isSet(WEEK_OF_YEAR) ? fields[NFIELDS + WEEK_OF_YEAR] : 1;1539int dayOfWeek = isSet(DAY_OF_WEEK)1540? fields[NFIELDS + DAY_OF_WEEK] : cal.getFirstDayOfWeek();1541cal.setWeekDate(fields[NFIELDS + WEEK_YEAR], weekOfYear, dayOfWeek);1542}1543cal.complete();1544}15451546return cal;1547}15481549private void allocateFields() {1550if (fields == null) {1551fields = new int[NFIELDS * 2];1552nextStamp = MINIMUM_USER_STAMP;1553maxFieldIndex = -1;1554}1555}15561557private void internalSet(int field, int value) {1558fields[field] = nextStamp++;1559if (nextStamp < 0) {1560throw new IllegalStateException("stamp counter overflow");1561}1562fields[NFIELDS + field] = value;1563if (field > maxFieldIndex && field < WEEK_YEAR) {1564maxFieldIndex = field;1565}1566}15671568private boolean isInstantSet() {1569return nextStamp == COMPUTED;1570}15711572private boolean isSet(int index) {1573return fields != null && fields[index] > UNSET;1574}15751576private boolean isValidWeekParameter(int value) {1577return value > 0 && value <= 7;1578}1579}15801581/**1582* Constructs a Calendar with the default time zone1583* and the default {@link java.util.Locale.Category#FORMAT FORMAT}1584* locale.1585* @see TimeZone#getDefault1586*/1587protected Calendar()1588{1589this(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));1590sharedZone = true;1591}15921593/**1594* Constructs a calendar with the specified time zone and locale.1595*1596* @param zone the time zone to use1597* @param aLocale the locale for the week data1598*/1599protected Calendar(TimeZone zone, Locale aLocale)1600{1601fields = new int[FIELD_COUNT];1602isSet = new boolean[FIELD_COUNT];1603stamp = new int[FIELD_COUNT];16041605this.zone = zone;1606setWeekCountData(aLocale);1607}16081609/**1610* Gets a calendar using the default time zone and locale. The1611* {@code Calendar} returned is based on the current time1612* in the default time zone with the default1613* {@link Locale.Category#FORMAT FORMAT} locale.1614* <p>1615* If the locale contains the time zone with "tz"1616* <a href="Locale.html#def_locale_extension">Unicode extension</a>,1617* that time zone is used instead.1618*1619* @return a Calendar.1620*/1621public static Calendar getInstance()1622{1623Locale aLocale = Locale.getDefault(Locale.Category.FORMAT);1624return createCalendar(defaultTimeZone(aLocale), aLocale);1625}16261627/**1628* Gets a calendar using the specified time zone and default locale.1629* The {@code Calendar} returned is based on the current time1630* in the given time zone with the default1631* {@link Locale.Category#FORMAT FORMAT} locale.1632*1633* @param zone the time zone to use1634* @return a Calendar.1635*/1636public static Calendar getInstance(TimeZone zone)1637{1638return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT));1639}16401641/**1642* Gets a calendar using the default time zone and specified locale.1643* The {@code Calendar} returned is based on the current time1644* in the default time zone with the given locale.1645* <p>1646* If the locale contains the time zone with "tz"1647* <a href="Locale.html#def_locale_extension">Unicode extension</a>,1648* that time zone is used instead.1649*1650* @param aLocale the locale for the week data1651* @return a Calendar.1652*/1653public static Calendar getInstance(Locale aLocale)1654{1655return createCalendar(defaultTimeZone(aLocale), aLocale);1656}16571658/**1659* Gets a calendar with the specified time zone and locale.1660* The {@code Calendar} returned is based on the current time1661* in the given time zone with the given locale.1662*1663* @param zone the time zone to use1664* @param aLocale the locale for the week data1665* @return a Calendar.1666*/1667public static Calendar getInstance(TimeZone zone,1668Locale aLocale)1669{1670return createCalendar(zone, aLocale);1671}16721673private static TimeZone defaultTimeZone(Locale l) {1674TimeZone defaultTZ = TimeZone.getDefault();1675String shortTZID = l.getUnicodeLocaleType("tz");1676return shortTZID != null ?1677TimeZoneNameUtility.convertLDMLShortID(shortTZID)1678.map(TimeZone::getTimeZone)1679.orElse(defaultTZ) :1680defaultTZ;1681}16821683private static Calendar createCalendar(TimeZone zone,1684Locale aLocale)1685{1686CalendarProvider provider =1687LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)1688.getCalendarProvider();1689if (provider != null) {1690try {1691return provider.getInstance(zone, aLocale);1692} catch (IllegalArgumentException iae) {1693// fall back to the default instantiation1694}1695}16961697Calendar cal = null;16981699if (aLocale.hasExtensions()) {1700String caltype = aLocale.getUnicodeLocaleType("ca");1701if (caltype != null) {1702cal = switch (caltype) {1703case "buddhist" -> new BuddhistCalendar(zone, aLocale);1704case "japanese" -> new JapaneseImperialCalendar(zone, aLocale);1705case "gregory" -> new GregorianCalendar(zone, aLocale);1706default -> null;1707};1708}1709}1710if (cal == null) {1711// If no known calendar type is explicitly specified,1712// perform the traditional way to create a Calendar:1713// create a BuddhistCalendar for th_TH locale,1714// a JapaneseImperialCalendar for ja_JP_JP locale, or1715// a GregorianCalendar for any other locales.1716// NOTE: The language, country and variant strings are interned.1717if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {1718cal = new BuddhistCalendar(zone, aLocale);1719} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"1720&& aLocale.getCountry() == "JP") {1721cal = new JapaneseImperialCalendar(zone, aLocale);1722} else {1723cal = new GregorianCalendar(zone, aLocale);1724}1725}1726return cal;1727}17281729/**1730* Returns an array of all locales for which the {@code getInstance}1731* methods of this class can return localized instances.1732* The array returned must contain at least a {@code Locale}1733* instance equal to {@link java.util.Locale#US Locale.US}.1734*1735* @return An array of locales for which localized1736* {@code Calendar} instances are available.1737*/1738public static synchronized Locale[] getAvailableLocales()1739{1740return DateFormat.getAvailableLocales();1741}17421743/**1744* Converts the current calendar field values in {@link #fields fields[]}1745* to the millisecond time value1746* {@link #time}.1747*1748* @see #complete()1749* @see #computeFields()1750*/1751protected abstract void computeTime();17521753/**1754* Converts the current millisecond time value {@link #time}1755* to calendar field values in {@link #fields fields[]}.1756* This allows you to sync up the calendar field values with1757* a new time that is set for the calendar. The time is <em>not</em>1758* recomputed first; to recompute the time, then the fields, call the1759* {@link #complete()} method.1760*1761* @see #computeTime()1762*/1763protected abstract void computeFields();17641765/**1766* Returns a {@code Date} object representing this1767* {@code Calendar}'s time value (millisecond offset from the <a1768* href="#Epoch">Epoch</a>").1769*1770* @return a {@code Date} representing the time value.1771* @see #setTime(Date)1772* @see #getTimeInMillis()1773*/1774public final Date getTime() {1775return new Date(getTimeInMillis());1776}17771778/**1779* Sets this Calendar's time with the given {@code Date}.1780* <p>1781* Note: Calling {@code setTime()} with1782* {@code Date(Long.MAX_VALUE)} or {@code Date(Long.MIN_VALUE)}1783* may yield incorrect field values from {@code get()}.1784*1785* @param date the given Date.1786* @see #getTime()1787* @see #setTimeInMillis(long)1788* @throws NullPointerException if {@code date} is {@code null}1789*/1790public final void setTime(Date date) {1791Objects.requireNonNull(date, "date must not be null");1792setTimeInMillis(date.getTime());1793}17941795/**1796* Returns this Calendar's time value in milliseconds.1797*1798* @return the current time as UTC milliseconds from the epoch.1799* @see #getTime()1800* @see #setTimeInMillis(long)1801*/1802public long getTimeInMillis() {1803if (!isTimeSet) {1804updateTime();1805}1806return time;1807}18081809/**1810* Sets this Calendar's current time from the given long value.1811*1812* @param millis the new time in UTC milliseconds from the epoch.1813* @see #setTime(Date)1814* @see #getTimeInMillis()1815*/1816public void setTimeInMillis(long millis) {1817// If we don't need to recalculate the calendar field values,1818// do nothing.1819if (time == millis && isTimeSet && areFieldsSet && areAllFieldsSet1820&& (zone instanceof ZoneInfo) && !((ZoneInfo)zone).isDirty()) {1821return;1822}1823time = millis;1824isTimeSet = true;1825areFieldsSet = false;1826computeFields();1827areAllFieldsSet = areFieldsSet = true;1828}18291830/**1831* Returns the value of the given calendar field. In lenient mode,1832* all calendar fields are normalized. In non-lenient mode, all1833* calendar fields are validated and this method throws an1834* exception if any calendar fields have out-of-range values. The1835* normalization and validation are handled by the1836* {@link #complete()} method, which process is calendar1837* system dependent.1838*1839* @param field the given calendar field.1840* @return the value for the given calendar field.1841* @throws ArrayIndexOutOfBoundsException if the specified field is out of range1842* (<code>field < 0 || field >= FIELD_COUNT</code>).1843* @see #set(int,int)1844* @see #complete()1845*/1846public int get(int field)1847{1848complete();1849return internalGet(field);1850}18511852/**1853* Returns the value of the given calendar field. This method does1854* not involve normalization or validation of the field value.1855*1856* @param field the given calendar field.1857* @return the value for the given calendar field.1858* @see #get(int)1859*/1860protected final int internalGet(int field)1861{1862return fields[field];1863}18641865/**1866* Sets the value of the given calendar field. This method does1867* not affect any setting state of the field in this1868* {@code Calendar} instance.1869*1870* @throws IndexOutOfBoundsException if the specified field is out of range1871* (<code>field < 0 || field >= FIELD_COUNT</code>).1872* @see #areFieldsSet1873* @see #isTimeSet1874* @see #areAllFieldsSet1875* @see #set(int,int)1876*/1877final void internalSet(int field, int value)1878{1879fields[field] = value;1880}18811882/**1883* Sets the given calendar field to the given value. The value is not1884* interpreted by this method regardless of the leniency mode.1885*1886* @param field the given calendar field.1887* @param value the value to be set for the given calendar field.1888* @throws ArrayIndexOutOfBoundsException if the specified field is out of range1889* (<code>field < 0 || field >= FIELD_COUNT</code>).1890* in non-lenient mode.1891* @see #set(int,int,int)1892* @see #set(int,int,int,int,int)1893* @see #set(int,int,int,int,int,int)1894* @see #get(int)1895*/1896public void set(int field, int value)1897{1898// If the fields are partially normalized, calculate all the1899// fields before changing any fields.1900if (areFieldsSet && !areAllFieldsSet) {1901computeFields();1902}1903internalSet(field, value);1904isTimeSet = false;1905areFieldsSet = false;1906isSet[field] = true;1907stamp[field] = nextStamp++;1908if (nextStamp == Integer.MAX_VALUE) {1909adjustStamp();1910}1911}19121913/**1914* Sets the values for the calendar fields {@code YEAR},1915* {@code MONTH}, and {@code DAY_OF_MONTH}.1916* Previous values of other calendar fields are retained. If this is not desired,1917* call {@link #clear()} first.1918*1919* @param year the value used to set the {@code YEAR} calendar field.1920* @param month the value used to set the {@code MONTH} calendar field.1921* Month value is 0-based. e.g., 0 for January.1922* @param date the value used to set the {@code DAY_OF_MONTH} calendar field.1923* @see #set(int,int)1924* @see #set(int,int,int,int,int)1925* @see #set(int,int,int,int,int,int)1926*/1927public final void set(int year, int month, int date)1928{1929set(YEAR, year);1930set(MONTH, month);1931set(DATE, date);1932}19331934/**1935* Sets the values for the calendar fields {@code YEAR},1936* {@code MONTH}, {@code DAY_OF_MONTH},1937* {@code HOUR_OF_DAY}, and {@code MINUTE}.1938* Previous values of other fields are retained. If this is not desired,1939* call {@link #clear()} first.1940*1941* @param year the value used to set the {@code YEAR} calendar field.1942* @param month the value used to set the {@code MONTH} calendar field.1943* Month value is 0-based. e.g., 0 for January.1944* @param date the value used to set the {@code DAY_OF_MONTH} calendar field.1945* @param hourOfDay the value used to set the {@code HOUR_OF_DAY} calendar field.1946* @param minute the value used to set the {@code MINUTE} calendar field.1947* @see #set(int,int)1948* @see #set(int,int,int)1949* @see #set(int,int,int,int,int,int)1950*/1951public final void set(int year, int month, int date, int hourOfDay, int minute)1952{1953set(YEAR, year);1954set(MONTH, month);1955set(DATE, date);1956set(HOUR_OF_DAY, hourOfDay);1957set(MINUTE, minute);1958}19591960/**1961* Sets the values for the fields {@code YEAR}, {@code MONTH},1962* {@code DAY_OF_MONTH}, {@code HOUR_OF_DAY}, {@code MINUTE}, and1963* {@code SECOND}.1964* Previous values of other fields are retained. If this is not desired,1965* call {@link #clear()} first.1966*1967* @param year the value used to set the {@code YEAR} calendar field.1968* @param month the value used to set the {@code MONTH} calendar field.1969* Month value is 0-based. e.g., 0 for January.1970* @param date the value used to set the {@code DAY_OF_MONTH} calendar field.1971* @param hourOfDay the value used to set the {@code HOUR_OF_DAY} calendar field.1972* @param minute the value used to set the {@code MINUTE} calendar field.1973* @param second the value used to set the {@code SECOND} calendar field.1974* @see #set(int,int)1975* @see #set(int,int,int)1976* @see #set(int,int,int,int,int)1977*/1978public final void set(int year, int month, int date, int hourOfDay, int minute,1979int second)1980{1981set(YEAR, year);1982set(MONTH, month);1983set(DATE, date);1984set(HOUR_OF_DAY, hourOfDay);1985set(MINUTE, minute);1986set(SECOND, second);1987}19881989/**1990* Sets all the calendar field values and the time value1991* (millisecond offset from the <a href="#Epoch">Epoch</a>) of1992* this {@code Calendar} undefined. This means that {@link1993* #isSet(int) isSet()} will return {@code false} for all the1994* calendar fields, and the date and time calculations will treat1995* the fields as if they had never been set. A1996* {@code Calendar} implementation class may use its specific1997* default field values for date/time calculations. For example,1998* {@code GregorianCalendar} uses 1970 if the1999* {@code YEAR} field value is undefined.2000*2001* @see #clear(int)2002*/2003public final void clear()2004{2005for (int i = 0; i < fields.length; ) {2006stamp[i] = fields[i] = 0; // UNSET == 02007isSet[i++] = false;2008}2009areAllFieldsSet = areFieldsSet = false;2010isTimeSet = false;2011}20122013/**2014* Sets the given calendar field value and the time value2015* (millisecond offset from the <a href="#Epoch">Epoch</a>) of2016* this {@code Calendar} undefined. This means that {@link2017* #isSet(int) isSet(field)} will return {@code false}, and2018* the date and time calculations will treat the field as if it2019* had never been set. A {@code Calendar} implementation2020* class may use the field's specific default value for date and2021* time calculations.2022*2023* <p>The {@link #HOUR_OF_DAY}, {@link #HOUR} and {@link #AM_PM}2024* fields are handled independently and the <a2025* href="#time_resolution">the resolution rule for the time of2026* day</a> is applied. Clearing one of the fields doesn't reset2027* the hour of day value of this {@code Calendar}. Use {@link2028* #set(int,int) set(Calendar.HOUR_OF_DAY, 0)} to reset the hour2029* value.2030*2031* @param field the calendar field to be cleared.2032* @see #clear()2033*/2034public final void clear(int field)2035{2036fields[field] = 0;2037stamp[field] = UNSET;2038isSet[field] = false;20392040areAllFieldsSet = areFieldsSet = false;2041isTimeSet = false;2042}20432044/**2045* Determines if the given calendar field has a value set,2046* including cases that the value has been set by internal fields2047* calculations triggered by a {@code get} method call.2048*2049* @param field the calendar field to test2050* @return {@code true} if the given calendar field has a value set;2051* {@code false} otherwise.2052*/2053public final boolean isSet(int field)2054{2055return stamp[field] != UNSET;2056}20572058/**2059* Returns the string representation of the calendar2060* {@code field} value in the given {@code style} and2061* {@code locale}. If no string representation is2062* applicable, {@code null} is returned. This method calls2063* {@link Calendar#get(int) get(field)} to get the calendar2064* {@code field} value if the string representation is2065* applicable to the given calendar {@code field}.2066*2067* <p>For example, if this {@code Calendar} is a2068* {@code GregorianCalendar} and its date is 2005-01-01, then2069* the string representation of the {@link #MONTH} field would be2070* "January" in the long style in an English locale or "Jan" in2071* the short style. However, no string representation would be2072* available for the {@link #DAY_OF_MONTH} field, and this method2073* would return {@code null}.2074*2075* <p>The default implementation supports the calendar fields for2076* which a {@link DateFormatSymbols} has names in the given2077* {@code locale}.2078*2079* @param field2080* the calendar field for which the string representation2081* is returned2082* @param style2083* the style applied to the string representation; one of {@link2084* #SHORT_FORMAT} ({@link #SHORT}), {@link #SHORT_STANDALONE},2085* {@link #LONG_FORMAT} ({@link #LONG}), {@link #LONG_STANDALONE},2086* {@link #NARROW_FORMAT}, or {@link #NARROW_STANDALONE}.2087* @param locale2088* the locale for the string representation2089* (any calendar types specified by {@code locale} are ignored)2090* @return the string representation of the given2091* {@code field} in the given {@code style}, or2092* {@code null} if no string representation is2093* applicable.2094* @throws IllegalArgumentException2095* if {@code field} or {@code style} is invalid,2096* or if this {@code Calendar} is non-lenient and any2097* of the calendar fields have invalid values2098* @throws NullPointerException2099* if {@code locale} is null2100* @since 1.62101*/2102public String getDisplayName(int field, int style, Locale locale) {2103if (!checkDisplayNameParams(field, style, SHORT, NARROW_FORMAT, locale,2104ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {2105return null;2106}21072108String calendarType = getCalendarType();2109int fieldValue = get(field);2110// the standalone/narrow styles and short era are supported only through2111// CalendarNameProviders.2112if (isStandaloneStyle(style) || isNarrowFormatStyle(style) ||2113field == ERA && (style & SHORT) == SHORT) {2114String val = CalendarDataUtility.retrieveFieldValueName(calendarType,2115field, fieldValue,2116style, locale);2117// Perform fallback here to follow the CLDR rules2118if (val == null) {2119if (isNarrowFormatStyle(style)) {2120val = CalendarDataUtility.retrieveFieldValueName(calendarType,2121field, fieldValue,2122toStandaloneStyle(style),2123locale);2124} else if (isStandaloneStyle(style)) {2125val = CalendarDataUtility.retrieveFieldValueName(calendarType,2126field, fieldValue,2127getBaseStyle(style),2128locale);2129}2130}2131return val;2132}21332134DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale);2135String[] strings = getFieldStrings(field, style, symbols);2136if (strings != null) {2137if (fieldValue < strings.length) {2138return strings[fieldValue];2139}2140}2141return null;2142}21432144/**2145* Returns a {@code Map} containing all names of the calendar2146* {@code field} in the given {@code style} and2147* {@code locale} and their corresponding field values. For2148* example, if this {@code Calendar} is a {@link2149* GregorianCalendar}, the returned map would contain "Jan" to2150* {@link #JANUARY}, "Feb" to {@link #FEBRUARY}, and so on, in the2151* {@linkplain #SHORT short} style in an English locale.2152*2153* <p>Narrow names may not be unique due to use of single characters,2154* such as "S" for Sunday and Saturday. In that case narrow names are not2155* included in the returned {@code Map}.2156*2157* <p>The values of other calendar fields may be taken into2158* account to determine a set of display names. For example, if2159* this {@code Calendar} is a lunisolar calendar system and2160* the year value given by the {@link #YEAR} field has a leap2161* month, this method would return month names containing the leap2162* month name, and month names are mapped to their values specific2163* for the year.2164*2165* <p>The default implementation supports display names contained in2166* a {@link DateFormatSymbols}. For example, if {@code field}2167* is {@link #MONTH} and {@code style} is {@link2168* #ALL_STYLES}, this method returns a {@code Map} containing2169* all strings returned by {@link DateFormatSymbols#getShortMonths()}2170* and {@link DateFormatSymbols#getMonths()}.2171*2172* @param field2173* the calendar field for which the display names are returned2174* @param style2175* the style applied to the string representation; one of {@link2176* #SHORT_FORMAT} ({@link #SHORT}), {@link #SHORT_STANDALONE},2177* {@link #LONG_FORMAT} ({@link #LONG}), {@link #LONG_STANDALONE},2178* {@link #NARROW_FORMAT}, or {@link #NARROW_STANDALONE}2179* @param locale2180* the locale for the display names2181* @return a {@code Map} containing all display names in2182* {@code style} and {@code locale} and their2183* field values, or {@code null} if no display names2184* are defined for {@code field}2185* @throws IllegalArgumentException2186* if {@code field} or {@code style} is invalid,2187* or if this {@code Calendar} is non-lenient and any2188* of the calendar fields have invalid values2189* @throws NullPointerException2190* if {@code locale} is null2191* @since 1.62192*/2193public Map<String, Integer> getDisplayNames(int field, int style, Locale locale) {2194if (!checkDisplayNameParams(field, style, ALL_STYLES, NARROW_FORMAT, locale,2195ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {2196return null;2197}21982199String calendarType = getCalendarType();2200if (style == ALL_STYLES || isStandaloneStyle(style) || isNarrowFormatStyle(style) ||2201field == ERA && (style & SHORT) == SHORT) {2202Map<String, Integer> map;2203map = CalendarDataUtility.retrieveFieldValueNames(calendarType, field, style, locale);22042205// Perform fallback here to follow the CLDR rules2206if (map == null) {2207if (isNarrowFormatStyle(style)) {2208map = CalendarDataUtility.retrieveFieldValueNames(calendarType, field,2209toStandaloneStyle(style), locale);2210} else if (style != ALL_STYLES) {2211map = CalendarDataUtility.retrieveFieldValueNames(calendarType, field,2212getBaseStyle(style), locale);2213}2214}2215return map;2216}22172218// SHORT or LONG2219return getDisplayNamesImpl(field, style, locale);2220}22212222private Map<String,Integer> getDisplayNamesImpl(int field, int style, Locale locale) {2223DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale);2224String[] strings = getFieldStrings(field, style, symbols);2225if (strings != null) {2226Map<String,Integer> names = new HashMap<>();2227for (int i = 0; i < strings.length; i++) {2228if (strings[i].isEmpty()) {2229continue;2230}2231names.put(strings[i], i);2232}2233return names;2234}2235return null;2236}22372238boolean checkDisplayNameParams(int field, int style, int minStyle, int maxStyle,2239Locale locale, int fieldMask) {2240int baseStyle = getBaseStyle(style); // Ignore the standalone mask2241if (field < 0 || field >= fields.length ||2242baseStyle < minStyle || baseStyle > maxStyle || baseStyle == 3) {2243throw new IllegalArgumentException();2244}2245if (locale == null) {2246throw new NullPointerException();2247}2248return isFieldSet(fieldMask, field);2249}22502251private String[] getFieldStrings(int field, int style, DateFormatSymbols symbols) {2252int baseStyle = getBaseStyle(style); // ignore the standalone mask22532254// DateFormatSymbols doesn't support any narrow names.2255if (baseStyle == NARROW_FORMAT) {2256return null;2257}22582259return switch (field) {2260case ERA -> symbols.getEras();2261case MONTH -> (baseStyle == LONG) ? symbols.getMonths() : symbols.getShortMonths();2262case DAY_OF_WEEK -> (baseStyle == LONG) ? symbols.getWeekdays() : symbols.getShortWeekdays();2263case AM_PM -> symbols.getAmPmStrings();2264default -> null;2265};2266}22672268/**2269* Fills in any unset fields in the calendar fields. First, the {@link2270* #computeTime()} method is called if the time value (millisecond offset2271* from the <a href="#Epoch">Epoch</a>) has not been calculated from2272* calendar field values. Then, the {@link #computeFields()} method is2273* called to calculate all calendar field values.2274*/2275protected void complete()2276{2277if (!isTimeSet) {2278updateTime();2279}2280if (!areFieldsSet || !areAllFieldsSet) {2281computeFields(); // fills in unset fields2282areAllFieldsSet = areFieldsSet = true;2283}2284}22852286/**2287* Returns whether the value of the specified calendar field has been set2288* externally by calling one of the setter methods rather than by the2289* internal time calculation.2290*2291* @return {@code true} if the field has been set externally,2292* {@code false} otherwise.2293* @throws IndexOutOfBoundsException if the specified2294* {@code field} is out of range2295* (<code>field < 0 || field >= FIELD_COUNT</code>).2296* @see #selectFields()2297* @see #setFieldsComputed(int)2298*/2299final boolean isExternallySet(int field) {2300return stamp[field] >= MINIMUM_USER_STAMP;2301}23022303/**2304* Returns a field mask (bit mask) indicating all calendar fields that2305* have the state of externally or internally set.2306*2307* @return a bit mask indicating set state fields2308*/2309final int getSetStateFields() {2310int mask = 0;2311for (int i = 0; i < fields.length; i++) {2312if (stamp[i] != UNSET) {2313mask |= 1 << i;2314}2315}2316return mask;2317}23182319/**2320* Sets the state of the specified calendar fields to2321* <em>computed</em>. This state means that the specified calendar fields2322* have valid values that have been set by internal time calculation2323* rather than by calling one of the setter methods.2324*2325* @param fieldMask the field to be marked as computed.2326* @throws IndexOutOfBoundsException if the specified2327* {@code field} is out of range2328* (<code>field < 0 || field >= FIELD_COUNT</code>).2329* @see #isExternallySet(int)2330* @see #selectFields()2331*/2332final void setFieldsComputed(int fieldMask) {2333if (fieldMask == ALL_FIELDS) {2334for (int i = 0; i < fields.length; i++) {2335stamp[i] = COMPUTED;2336isSet[i] = true;2337}2338areFieldsSet = areAllFieldsSet = true;2339} else {2340for (int i = 0; i < fields.length; i++) {2341if ((fieldMask & 1) == 1) {2342stamp[i] = COMPUTED;2343isSet[i] = true;2344} else {2345if (areAllFieldsSet && !isSet[i]) {2346areAllFieldsSet = false;2347}2348}2349fieldMask >>>= 1;2350}2351}2352}23532354/**2355* Sets the state of the calendar fields that are <em>not</em> specified2356* by {@code fieldMask} to <em>unset</em>. If {@code fieldMask}2357* specifies all the calendar fields, then the state of this2358* {@code Calendar} becomes that all the calendar fields are in sync2359* with the time value (millisecond offset from the Epoch).2360*2361* @param fieldMask the field mask indicating which calendar fields are in2362* sync with the time value.2363* @throws IndexOutOfBoundsException if the specified2364* {@code field} is out of range2365* (<code>field < 0 || field >= FIELD_COUNT</code>).2366* @see #isExternallySet(int)2367* @see #selectFields()2368*/2369final void setFieldsNormalized(int fieldMask) {2370if (fieldMask != ALL_FIELDS) {2371for (int i = 0; i < fields.length; i++) {2372if ((fieldMask & 1) == 0) {2373stamp[i] = fields[i] = 0; // UNSET == 02374isSet[i] = false;2375}2376fieldMask >>= 1;2377}2378}23792380// Some or all of the fields are in sync with the2381// milliseconds, but the stamp values are not normalized yet.2382areFieldsSet = true;2383areAllFieldsSet = false;2384}23852386/**2387* Returns whether the calendar fields are partially in sync with the time2388* value or fully in sync but not stamp values are not normalized yet.2389*/2390final boolean isPartiallyNormalized() {2391return areFieldsSet && !areAllFieldsSet;2392}23932394/**2395* Returns whether the calendar fields are fully in sync with the time2396* value.2397*/2398final boolean isFullyNormalized() {2399return areFieldsSet && areAllFieldsSet;2400}24012402/**2403* Marks this Calendar as not sync'd.2404*/2405final void setUnnormalized() {2406areFieldsSet = areAllFieldsSet = false;2407}24082409/**2410* Returns whether the specified {@code field} is on in the2411* {@code fieldMask}.2412*/2413static boolean isFieldSet(int fieldMask, int field) {2414return (fieldMask & (1 << field)) != 0;2415}24162417/**2418* Returns a field mask indicating which calendar field values2419* to be used to calculate the time value. The calendar fields are2420* returned as a bit mask, each bit of which corresponds to a field, i.e.,2421* the mask value of {@code field} is <code>(1 <<2422* field)</code>. For example, 0x26 represents the {@code YEAR},2423* {@code MONTH}, and {@code DAY_OF_MONTH} fields (i.e., 0x26 is2424* equal to2425* <code>(1<<YEAR)|(1<<MONTH)|(1<<DAY_OF_MONTH))</code>.2426*2427* <p>This method supports the calendar fields resolution as described in2428* the class description. If the bit mask for a given field is on and its2429* field has not been set (i.e., {@code isSet(field)} is2430* {@code false}), then the default value of the field has to be2431* used, which case means that the field has been selected because the2432* selected combination involves the field.2433*2434* @return a bit mask of selected fields2435* @see #isExternallySet(int)2436*/2437final int selectFields() {2438// This implementation has been taken from the GregorianCalendar class.24392440// The YEAR field must always be used regardless of its SET2441// state because YEAR is a mandatory field to determine the date2442// and the default value (EPOCH_YEAR) may change through the2443// normalization process.2444int fieldMask = YEAR_MASK;24452446if (stamp[ERA] != UNSET) {2447fieldMask |= ERA_MASK;2448}2449// Find the most recent group of fields specifying the day within2450// the year. These may be any of the following combinations:2451// MONTH + DAY_OF_MONTH2452// MONTH + WEEK_OF_MONTH + DAY_OF_WEEK2453// MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK2454// DAY_OF_YEAR2455// WEEK_OF_YEAR + DAY_OF_WEEK2456// We look for the most recent of the fields in each group to determine2457// the age of the group. For groups involving a week-related field such2458// as WEEK_OF_MONTH, DAY_OF_WEEK_IN_MONTH, or WEEK_OF_YEAR, both the2459// week-related field and the DAY_OF_WEEK must be set for the group as a2460// whole to be considered. (See bug 4153860 - liu 7/24/98.)2461int dowStamp = stamp[DAY_OF_WEEK];2462int monthStamp = stamp[MONTH];2463int domStamp = stamp[DAY_OF_MONTH];2464int womStamp = aggregateStamp(stamp[WEEK_OF_MONTH], dowStamp);2465int dowimStamp = aggregateStamp(stamp[DAY_OF_WEEK_IN_MONTH], dowStamp);2466int doyStamp = stamp[DAY_OF_YEAR];2467int woyStamp = aggregateStamp(stamp[WEEK_OF_YEAR], dowStamp);24682469int bestStamp = domStamp;2470if (womStamp > bestStamp) {2471bestStamp = womStamp;2472}2473if (dowimStamp > bestStamp) {2474bestStamp = dowimStamp;2475}2476if (doyStamp > bestStamp) {2477bestStamp = doyStamp;2478}2479if (woyStamp > bestStamp) {2480bestStamp = woyStamp;2481}24822483/* No complete combination exists. Look for WEEK_OF_MONTH,2484* DAY_OF_WEEK_IN_MONTH, or WEEK_OF_YEAR alone. Treat DAY_OF_WEEK alone2485* as DAY_OF_WEEK_IN_MONTH.2486*/2487if (bestStamp == UNSET) {2488womStamp = stamp[WEEK_OF_MONTH];2489dowimStamp = Math.max(stamp[DAY_OF_WEEK_IN_MONTH], dowStamp);2490woyStamp = stamp[WEEK_OF_YEAR];2491bestStamp = Math.max(Math.max(womStamp, dowimStamp), woyStamp);24922493/* Treat MONTH alone or no fields at all as DAY_OF_MONTH. This may2494* result in bestStamp = domStamp = UNSET if no fields are set,2495* which indicates DAY_OF_MONTH.2496*/2497if (bestStamp == UNSET) {2498bestStamp = domStamp = monthStamp;2499}2500}25012502if (bestStamp == domStamp ||2503(bestStamp == womStamp && stamp[WEEK_OF_MONTH] >= stamp[WEEK_OF_YEAR]) ||2504(bestStamp == dowimStamp && stamp[DAY_OF_WEEK_IN_MONTH] >= stamp[WEEK_OF_YEAR])) {2505fieldMask |= MONTH_MASK;2506if (bestStamp == domStamp) {2507fieldMask |= DAY_OF_MONTH_MASK;2508} else {2509assert (bestStamp == womStamp || bestStamp == dowimStamp);2510if (dowStamp != UNSET) {2511fieldMask |= DAY_OF_WEEK_MASK;2512}2513if (womStamp == dowimStamp) {2514// When they are equal, give the priority to2515// WEEK_OF_MONTH for compatibility.2516if (stamp[WEEK_OF_MONTH] >= stamp[DAY_OF_WEEK_IN_MONTH]) {2517fieldMask |= WEEK_OF_MONTH_MASK;2518} else {2519fieldMask |= DAY_OF_WEEK_IN_MONTH_MASK;2520}2521} else {2522if (bestStamp == womStamp) {2523fieldMask |= WEEK_OF_MONTH_MASK;2524} else {2525assert (bestStamp == dowimStamp);2526if (stamp[DAY_OF_WEEK_IN_MONTH] != UNSET) {2527fieldMask |= DAY_OF_WEEK_IN_MONTH_MASK;2528}2529}2530}2531}2532} else {2533assert (bestStamp == doyStamp || bestStamp == woyStamp ||2534bestStamp == UNSET);2535if (bestStamp == doyStamp) {2536fieldMask |= DAY_OF_YEAR_MASK;2537} else {2538assert (bestStamp == woyStamp);2539if (dowStamp != UNSET) {2540fieldMask |= DAY_OF_WEEK_MASK;2541}2542fieldMask |= WEEK_OF_YEAR_MASK;2543}2544}25452546// Find the best set of fields specifying the time of day. There2547// are only two possibilities here; the HOUR_OF_DAY or the2548// AM_PM and the HOUR.2549int hourOfDayStamp = stamp[HOUR_OF_DAY];2550int hourStamp = aggregateStamp(stamp[HOUR], stamp[AM_PM]);2551bestStamp = (hourStamp > hourOfDayStamp) ? hourStamp : hourOfDayStamp;25522553// if bestStamp is still UNSET, then take HOUR or AM_PM. (See 4846659)2554if (bestStamp == UNSET) {2555bestStamp = Math.max(stamp[HOUR], stamp[AM_PM]);2556}25572558// Hours2559if (bestStamp != UNSET) {2560if (bestStamp == hourOfDayStamp) {2561fieldMask |= HOUR_OF_DAY_MASK;2562} else {2563fieldMask |= HOUR_MASK;2564if (stamp[AM_PM] != UNSET) {2565fieldMask |= AM_PM_MASK;2566}2567}2568}2569if (stamp[MINUTE] != UNSET) {2570fieldMask |= MINUTE_MASK;2571}2572if (stamp[SECOND] != UNSET) {2573fieldMask |= SECOND_MASK;2574}2575if (stamp[MILLISECOND] != UNSET) {2576fieldMask |= MILLISECOND_MASK;2577}2578if (stamp[ZONE_OFFSET] >= MINIMUM_USER_STAMP) {2579fieldMask |= ZONE_OFFSET_MASK;2580}2581if (stamp[DST_OFFSET] >= MINIMUM_USER_STAMP) {2582fieldMask |= DST_OFFSET_MASK;2583}25842585return fieldMask;2586}25872588int getBaseStyle(int style) {2589return style & ~STANDALONE_MASK;2590}25912592private int toStandaloneStyle(int style) {2593return style | STANDALONE_MASK;2594}25952596private boolean isStandaloneStyle(int style) {2597return (style & STANDALONE_MASK) != 0;2598}25992600private boolean isNarrowStyle(int style) {2601return style == NARROW_FORMAT || style == NARROW_STANDALONE;2602}26032604private boolean isNarrowFormatStyle(int style) {2605return style == NARROW_FORMAT;2606}26072608/**2609* Returns the pseudo-time-stamp for two fields, given their2610* individual pseudo-time-stamps. If either of the fields2611* is unset, then the aggregate is unset. Otherwise, the2612* aggregate is the later of the two stamps.2613*/2614private static int aggregateStamp(int stamp_a, int stamp_b) {2615if (stamp_a == UNSET || stamp_b == UNSET) {2616return UNSET;2617}2618return (stamp_a > stamp_b) ? stamp_a : stamp_b;2619}26202621/**2622* Returns an unmodifiable {@code Set} containing all calendar types2623* supported by {@code Calendar} in the runtime environment. The available2624* calendar types can be used for the <a2625* href="Locale.html#def_locale_extension">Unicode locale extensions</a>.2626* The {@code Set} returned contains at least {@code "gregory"}. The2627* calendar types don't include aliases, such as {@code "gregorian"} for2628* {@code "gregory"}.2629*2630* @return an unmodifiable {@code Set} containing all available calendar types2631* @since 1.82632* @see #getCalendarType()2633* @see Calendar.Builder#setCalendarType(String)2634* @see Locale#getUnicodeLocaleType(String)2635*/2636public static Set<String> getAvailableCalendarTypes() {2637return AvailableCalendarTypes.SET;2638}26392640private static class AvailableCalendarTypes {2641private static final Set<String> SET;2642static {2643Set<String> set = new HashSet<>(3);2644set.add("gregory");2645set.add("buddhist");2646set.add("japanese");2647SET = Collections.unmodifiableSet(set);2648}2649private AvailableCalendarTypes() {2650}2651}26522653/**2654* Returns the calendar type of this {@code Calendar}. Calendar types are2655* defined by the <em>Unicode Locale Data Markup Language (LDML)</em>2656* specification.2657*2658* <p>The default implementation of this method returns the class name of2659* this {@code Calendar} instance. Any subclasses that implement2660* LDML-defined calendar systems should override this method to return2661* appropriate calendar types.2662*2663* @return the LDML-defined calendar type or the class name of this2664* {@code Calendar} instance2665* @since 1.82666* @see <a href="Locale.html#def_extensions">Locale extensions</a>2667* @see Locale.Builder#setLocale(Locale)2668* @see Locale.Builder#setUnicodeLocaleKeyword(String, String)2669*/2670public String getCalendarType() {2671return this.getClass().getName();2672}26732674/**2675* Compares this {@code Calendar} to the specified2676* {@code Object}. The result is {@code true} if and only if2677* the argument is a {@code Calendar} object of the same calendar2678* system that represents the same time value (millisecond offset from the2679* <a href="#Epoch">Epoch</a>) under the same2680* {@code Calendar} parameters as this object.2681*2682* <p>The {@code Calendar} parameters are the values represented2683* by the {@code isLenient}, {@code getFirstDayOfWeek},2684* {@code getMinimalDaysInFirstWeek} and {@code getTimeZone}2685* methods. If there is any difference in those parameters2686* between the two {@code Calendar}s, this method returns2687* {@code false}.2688*2689* <p>Use the {@link #compareTo(Calendar) compareTo} method to2690* compare only the time values.2691*2692* @param obj the object to compare with.2693* @return {@code true} if this object is equal to {@code obj};2694* {@code false} otherwise.2695*/2696@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")2697@Override2698public boolean equals(Object obj) {2699if (this == obj) {2700return true;2701}2702try {2703Calendar that = (Calendar)obj;2704return compareTo(getMillisOf(that)) == 0 &&2705lenient == that.lenient &&2706firstDayOfWeek == that.firstDayOfWeek &&2707minimalDaysInFirstWeek == that.minimalDaysInFirstWeek &&2708(zone instanceof ZoneInfo ?2709zone.equals(that.zone) :2710zone.equals(that.getTimeZone()));2711} catch (Exception e) {2712// Note: GregorianCalendar.computeTime throws2713// IllegalArgumentException if the ERA value is invalid2714// even it's in lenient mode.2715}2716return false;2717}27182719/**2720* Returns a hash code for this calendar.2721*2722* @return a hash code value for this object.2723* @since 1.22724*/2725@Override2726public int hashCode() {2727// 'otheritems' represents the hash code for the previous versions.2728int otheritems = (lenient ? 1 : 0)2729| (firstDayOfWeek << 1)2730| (minimalDaysInFirstWeek << 4)2731| (zone.hashCode() << 7);2732long t = getMillisOf(this);2733return (int) t ^ (int)(t >> 32) ^ otheritems;2734}27352736/**2737* Returns whether this {@code Calendar} represents a time2738* before the time represented by the specified2739* {@code Object}. This method is equivalent to:2740* <pre>{@code2741* compareTo(when) < 02742* }</pre>2743* if and only if {@code when} is a {@code Calendar}2744* instance. Otherwise, the method returns {@code false}.2745*2746* @param when the {@code Object} to be compared2747* @return {@code true} if the time of this2748* {@code Calendar} is before the time represented by2749* {@code when}; {@code false} otherwise.2750* @see #compareTo(Calendar)2751*/2752public boolean before(Object when) {2753return when instanceof Calendar2754&& compareTo((Calendar)when) < 0;2755}27562757/**2758* Returns whether this {@code Calendar} represents a time2759* after the time represented by the specified2760* {@code Object}. This method is equivalent to:2761* <pre>{@code2762* compareTo(when) > 02763* }</pre>2764* if and only if {@code when} is a {@code Calendar}2765* instance. Otherwise, the method returns {@code false}.2766*2767* @param when the {@code Object} to be compared2768* @return {@code true} if the time of this {@code Calendar} is2769* after the time represented by {@code when}; {@code false}2770* otherwise.2771* @see #compareTo(Calendar)2772*/2773public boolean after(Object when) {2774return when instanceof Calendar2775&& compareTo((Calendar)when) > 0;2776}27772778/**2779* Compares the time values (millisecond offsets from the <a2780* href="#Epoch">Epoch</a>) represented by two2781* {@code Calendar} objects.2782*2783* @param anotherCalendar the {@code Calendar} to be compared.2784* @return the value {@code 0} if the time represented by the argument2785* is equal to the time represented by this {@code Calendar}; a value2786* less than {@code 0} if the time of this {@code Calendar} is2787* before the time represented by the argument; and a value greater than2788* {@code 0} if the time of this {@code Calendar} is after the2789* time represented by the argument.2790* @throws NullPointerException if the specified {@code Calendar} is2791* {@code null}.2792* @throws IllegalArgumentException if the time value of the2793* specified {@code Calendar} object can't be obtained due to2794* any invalid calendar values.2795* @since 1.52796*/2797@Override2798public int compareTo(Calendar anotherCalendar) {2799return compareTo(getMillisOf(anotherCalendar));2800}28012802/**2803* Adds or subtracts the specified amount of time to the given calendar field,2804* based on the calendar's rules. For example, to subtract 5 days from2805* the current time of the calendar, you can achieve it by calling:2806* <p>{@code add(Calendar.DAY_OF_MONTH, -5)}.2807*2808* @param field the calendar field.2809* @param amount the amount of date or time to be added to the field.2810* @see #roll(int,int)2811* @see #set(int,int)2812*/2813public abstract void add(int field, int amount);28142815/**2816* Adds or subtracts (up/down) a single unit of time on the given time2817* field without changing larger fields. For example, to roll the current2818* date up by one day, you can achieve it by calling:2819* <p>roll(Calendar.DATE, true).2820* When rolling on the year or Calendar.YEAR field, it will roll the year2821* value in the range between 1 and the value returned by calling2822* {@code getMaximum(Calendar.YEAR)}.2823* When rolling on the month or Calendar.MONTH field, other fields like2824* date might conflict and, need to be changed. For instance,2825* rolling the month on the date 01/31/96 will result in 02/29/96.2826* When rolling on the hour-in-day or Calendar.HOUR_OF_DAY field, it will2827* roll the hour value in the range between 0 and 23, which is zero-based.2828*2829* @param field the time field.2830* @param up indicates if the value of the specified time field is to be2831* rolled up or rolled down. Use true if rolling up, false otherwise.2832* @see Calendar#add(int,int)2833* @see Calendar#set(int,int)2834*/2835public abstract void roll(int field, boolean up);28362837/**2838* Adds the specified (signed) amount to the specified calendar field2839* without changing larger fields. A negative amount means to roll2840* down.2841*2842* <p>NOTE: This default implementation on {@code Calendar} just repeatedly calls the2843* version of {@link #roll(int,boolean) roll()} that rolls by one unit. This may not2844* always do the right thing. For example, if the {@code DAY_OF_MONTH} field is 31,2845* rolling through February will leave it set to 28. The {@code GregorianCalendar}2846* version of this function takes care of this problem. Other subclasses2847* should also provide overrides of this function that do the right thing.2848*2849* @param field the calendar field.2850* @param amount the signed amount to add to the calendar {@code field}.2851* @since 1.22852* @see #roll(int,boolean)2853* @see #add(int,int)2854* @see #set(int,int)2855*/2856public void roll(int field, int amount)2857{2858while (amount > 0) {2859roll(field, true);2860amount--;2861}2862while (amount < 0) {2863roll(field, false);2864amount++;2865}2866}28672868/**2869* Sets the time zone with the given time zone value.2870*2871* @param value the given time zone.2872*/2873public void setTimeZone(TimeZone value)2874{2875zone = value;2876sharedZone = false;2877/* Recompute the fields from the time using the new zone. This also2878* works if isTimeSet is false (after a call to set()). In that case2879* the time will be computed from the fields using the new zone, then2880* the fields will get recomputed from that. Consider the sequence of2881* calls: cal.setTimeZone(EST); cal.set(HOUR, 1); cal.setTimeZone(PST).2882* Is cal set to 1 o'clock EST or 1 o'clock PST? Answer: PST. More2883* generally, a call to setTimeZone() affects calls to set() BEFORE AND2884* AFTER it up to the next call to complete().2885*/2886areAllFieldsSet = areFieldsSet = false;2887}28882889/**2890* Gets the time zone.2891*2892* @return the time zone object associated with this calendar.2893*/2894public TimeZone getTimeZone()2895{2896// If the TimeZone object is shared by other Calendar instances, then2897// create a clone.2898if (sharedZone) {2899zone = (TimeZone) zone.clone();2900sharedZone = false;2901}2902return zone;2903}29042905/**2906* Returns the time zone (without cloning).2907*/2908TimeZone getZone() {2909return zone;2910}29112912/**2913* Sets the sharedZone flag to {@code shared}.2914*/2915void setZoneShared(boolean shared) {2916sharedZone = shared;2917}29182919/**2920* Specifies whether or not date/time interpretation is to be lenient. With2921* lenient interpretation, a date such as "February 942, 1996" will be2922* treated as being equivalent to the 941st day after February 1, 1996.2923* With strict (non-lenient) interpretation, such dates will cause an exception to be2924* thrown. The default is lenient.2925*2926* @param lenient {@code true} if the lenient mode is to be turned2927* on; {@code false} if it is to be turned off.2928* @see #isLenient()2929* @see java.text.DateFormat#setLenient2930*/2931public void setLenient(boolean lenient)2932{2933this.lenient = lenient;2934}29352936/**2937* Tells whether date/time interpretation is to be lenient.2938*2939* @return {@code true} if the interpretation mode of this calendar is lenient;2940* {@code false} otherwise.2941* @see #setLenient(boolean)2942*/2943public boolean isLenient()2944{2945return lenient;2946}29472948/**2949* Sets what the first day of the week is; e.g., {@code SUNDAY} in the U.S.,2950* {@code MONDAY} in France.2951*2952* @param value the given first day of the week.2953* @see #getFirstDayOfWeek()2954* @see #getMinimalDaysInFirstWeek()2955*/2956public void setFirstDayOfWeek(int value)2957{2958if (firstDayOfWeek == value) {2959return;2960}2961firstDayOfWeek = value;2962invalidateWeekFields();2963}29642965/**2966* Gets what the first day of the week is; e.g., {@code SUNDAY} in the U.S.,2967* {@code MONDAY} in France.2968*2969* @return the first day of the week.2970* @see #setFirstDayOfWeek(int)2971* @see #getMinimalDaysInFirstWeek()2972*/2973public int getFirstDayOfWeek()2974{2975return firstDayOfWeek;2976}29772978/**2979* Sets what the minimal days required in the first week of the year are;2980* For example, if the first week is defined as one that contains the first2981* day of the first month of a year, call this method with value 1. If it2982* must be a full week, use value 7.2983*2984* @param value the given minimal days required in the first week2985* of the year.2986* @see #getMinimalDaysInFirstWeek()2987*/2988public void setMinimalDaysInFirstWeek(int value)2989{2990if (minimalDaysInFirstWeek == value) {2991return;2992}2993minimalDaysInFirstWeek = value;2994invalidateWeekFields();2995}29962997/**2998* Gets what the minimal days required in the first week of the year are;2999* e.g., if the first week is defined as one that contains the first day3000* of the first month of a year, this method returns 1. If3001* the minimal days required must be a full week, this method3002* returns 7.3003*3004* @return the minimal days required in the first week of the year.3005* @see #setMinimalDaysInFirstWeek(int)3006*/3007public int getMinimalDaysInFirstWeek()3008{3009return minimalDaysInFirstWeek;3010}30113012/**3013* Returns whether this {@code Calendar} supports week dates.3014*3015* <p>The default implementation of this method returns {@code false}.3016*3017* @return {@code true} if this {@code Calendar} supports week dates;3018* {@code false} otherwise.3019* @see #getWeekYear()3020* @see #setWeekDate(int,int,int)3021* @see #getWeeksInWeekYear()3022* @since 1.73023*/3024public boolean isWeekDateSupported() {3025return false;3026}30273028/**3029* Returns the week year represented by this {@code Calendar}. The3030* week year is in sync with the week cycle. The {@linkplain3031* #getFirstDayOfWeek() first day of the first week} is the first3032* day of the week year.3033*3034* <p>The default implementation of this method throws an3035* {@link UnsupportedOperationException}.3036*3037* @return the week year of this {@code Calendar}3038* @throws UnsupportedOperationException3039* if any week year numbering isn't supported3040* in this {@code Calendar}.3041* @see #isWeekDateSupported()3042* @see #getFirstDayOfWeek()3043* @see #getMinimalDaysInFirstWeek()3044* @since 1.73045*/3046public int getWeekYear() {3047throw new UnsupportedOperationException();3048}30493050/**3051* Sets the date of this {@code Calendar} with the given date3052* specifiers - week year, week of year, and day of week.3053*3054* <p>Unlike the {@code set} method, all of the calendar fields3055* and {@code time} values are calculated upon return.3056*3057* <p>If {@code weekOfYear} is out of the valid week-of-year range3058* in {@code weekYear}, the {@code weekYear} and {@code3059* weekOfYear} values are adjusted in lenient mode, or an {@code3060* IllegalArgumentException} is thrown in non-lenient mode.3061*3062* <p>The default implementation of this method throws an3063* {@code UnsupportedOperationException}.3064*3065* @param weekYear the week year3066* @param weekOfYear the week number based on {@code weekYear}3067* @param dayOfWeek the day of week value: one of the constants3068* for the {@link #DAY_OF_WEEK} field: {@link3069* #SUNDAY}, ..., {@link #SATURDAY}.3070* @throws IllegalArgumentException3071* if any of the given date specifiers is invalid3072* or any of the calendar fields are inconsistent3073* with the given date specifiers in non-lenient mode3074* @throws UnsupportedOperationException3075* if any week year numbering isn't supported in this3076* {@code Calendar}.3077* @see #isWeekDateSupported()3078* @see #getFirstDayOfWeek()3079* @see #getMinimalDaysInFirstWeek()3080* @since 1.73081*/3082public void setWeekDate(int weekYear, int weekOfYear, int dayOfWeek) {3083throw new UnsupportedOperationException();3084}30853086/**3087* Returns the number of weeks in the week year represented by this3088* {@code Calendar}.3089*3090* <p>The default implementation of this method throws an3091* {@code UnsupportedOperationException}.3092*3093* @return the number of weeks in the week year.3094* @throws UnsupportedOperationException3095* if any week year numbering isn't supported in this3096* {@code Calendar}.3097* @see #WEEK_OF_YEAR3098* @see #isWeekDateSupported()3099* @see #getWeekYear()3100* @see #getActualMaximum(int)3101* @since 1.73102*/3103public int getWeeksInWeekYear() {3104throw new UnsupportedOperationException();3105}31063107/**3108* Returns the minimum value for the given calendar field of this3109* {@code Calendar} instance. The minimum value is defined as3110* the smallest value returned by the {@link #get(int) get} method3111* for any possible time value. The minimum value depends on3112* calendar system specific parameters of the instance.3113*3114* @param field the calendar field.3115* @return the minimum value for the given calendar field.3116* @see #getMaximum(int)3117* @see #getGreatestMinimum(int)3118* @see #getLeastMaximum(int)3119* @see #getActualMinimum(int)3120* @see #getActualMaximum(int)3121*/3122public abstract int getMinimum(int field);31233124/**3125* Returns the maximum value for the given calendar field of this3126* {@code Calendar} instance. The maximum value is defined as3127* the largest value returned by the {@link #get(int) get} method3128* for any possible time value. The maximum value depends on3129* calendar system specific parameters of the instance.3130*3131* @param field the calendar field.3132* @return the maximum value for the given calendar field.3133* @see #getMinimum(int)3134* @see #getGreatestMinimum(int)3135* @see #getLeastMaximum(int)3136* @see #getActualMinimum(int)3137* @see #getActualMaximum(int)3138*/3139public abstract int getMaximum(int field);31403141/**3142* Returns the highest minimum value for the given calendar field3143* of this {@code Calendar} instance. The highest minimum3144* value is defined as the largest value returned by {@link3145* #getActualMinimum(int)} for any possible time value. The3146* greatest minimum value depends on calendar system specific3147* parameters of the instance.3148*3149* @param field the calendar field.3150* @return the highest minimum value for the given calendar field.3151* @see #getMinimum(int)3152* @see #getMaximum(int)3153* @see #getLeastMaximum(int)3154* @see #getActualMinimum(int)3155* @see #getActualMaximum(int)3156*/3157public abstract int getGreatestMinimum(int field);31583159/**3160* Returns the lowest maximum value for the given calendar field3161* of this {@code Calendar} instance. The lowest maximum3162* value is defined as the smallest value returned by {@link3163* #getActualMaximum(int)} for any possible time value. The least3164* maximum value depends on calendar system specific parameters of3165* the instance. For example, a {@code Calendar} for the3166* Gregorian calendar system returns 28 for the3167* {@code DAY_OF_MONTH} field, because the 28th is the last3168* day of the shortest month of this calendar, February in a3169* common year.3170*3171* @param field the calendar field.3172* @return the lowest maximum value for the given calendar field.3173* @see #getMinimum(int)3174* @see #getMaximum(int)3175* @see #getGreatestMinimum(int)3176* @see #getActualMinimum(int)3177* @see #getActualMaximum(int)3178*/3179public abstract int getLeastMaximum(int field);31803181/**3182* Returns the minimum value that the specified calendar field3183* could have, given the time value of this {@code Calendar}.3184*3185* <p>The default implementation of this method uses an iterative3186* algorithm to determine the actual minimum value for the3187* calendar field. Subclasses should, if possible, override this3188* with a more efficient implementation - in many cases, they can3189* simply return {@code getMinimum()}.3190*3191* @param field the calendar field3192* @return the minimum of the given calendar field for the time3193* value of this {@code Calendar}3194* @see #getMinimum(int)3195* @see #getMaximum(int)3196* @see #getGreatestMinimum(int)3197* @see #getLeastMaximum(int)3198* @see #getActualMaximum(int)3199* @since 1.23200*/3201public int getActualMinimum(int field) {3202int fieldValue = getGreatestMinimum(field);3203int endValue = getMinimum(field);32043205// if we know that the minimum value is always the same, just return it3206if (fieldValue == endValue) {3207return fieldValue;3208}32093210// clone the calendar so we don't mess with the real one, and set it to3211// accept anything for the field values3212Calendar work = (Calendar)this.clone();3213work.setLenient(true);32143215// now try each value from getLeastMaximum() to getMaximum() one by one until3216// we get a value that normalizes to another value. The last value that3217// normalizes to itself is the actual minimum for the current date3218int result = fieldValue;32193220do {3221work.set(field, fieldValue);3222if (work.get(field) != fieldValue) {3223break;3224} else {3225result = fieldValue;3226fieldValue--;3227}3228} while (fieldValue >= endValue);32293230return result;3231}32323233/**3234* Returns the maximum value that the specified calendar field3235* could have, given the time value of this3236* {@code Calendar}. For example, the actual maximum value of3237* the {@code MONTH} field is 12 in some years, and 13 in3238* other years in the Hebrew calendar system.3239*3240* <p>The default implementation of this method uses an iterative3241* algorithm to determine the actual maximum value for the3242* calendar field. Subclasses should, if possible, override this3243* with a more efficient implementation.3244*3245* @param field the calendar field3246* @return the maximum of the given calendar field for the time3247* value of this {@code Calendar}3248* @see #getMinimum(int)3249* @see #getMaximum(int)3250* @see #getGreatestMinimum(int)3251* @see #getLeastMaximum(int)3252* @see #getActualMinimum(int)3253* @since 1.23254*/3255public int getActualMaximum(int field) {3256int fieldValue = getLeastMaximum(field);3257int endValue = getMaximum(field);32583259// if we know that the maximum value is always the same, just return it.3260if (fieldValue == endValue) {3261return fieldValue;3262}32633264// clone the calendar so we don't mess with the real one, and set it to3265// accept anything for the field values.3266Calendar work = (Calendar)this.clone();3267work.setLenient(true);32683269// if we're counting weeks, set the day of the week to Sunday. We know the3270// last week of a month or year will contain the first day of the week.3271if (field == WEEK_OF_YEAR || field == WEEK_OF_MONTH) {3272work.set(DAY_OF_WEEK, firstDayOfWeek);3273}32743275// now try each value from getLeastMaximum() to getMaximum() one by one until3276// we get a value that normalizes to another value. The last value that3277// normalizes to itself is the actual maximum for the current date3278int result = fieldValue;32793280do {3281work.set(field, fieldValue);3282if (work.get(field) != fieldValue) {3283break;3284} else {3285result = fieldValue;3286fieldValue++;3287}3288} while (fieldValue <= endValue);32893290return result;3291}32923293/**3294* Creates and returns a copy of this object.3295*3296* @return a copy of this object.3297*/3298@Override3299public Object clone()3300{3301try {3302Calendar other = (Calendar) super.clone();33033304other.fields = new int[FIELD_COUNT];3305other.isSet = new boolean[FIELD_COUNT];3306other.stamp = new int[FIELD_COUNT];3307for (int i = 0; i < FIELD_COUNT; i++) {3308other.fields[i] = fields[i];3309other.stamp[i] = stamp[i];3310other.isSet[i] = isSet[i];3311}3312if (!sharedZone) {3313other.zone = (TimeZone) zone.clone();3314}3315return other;3316}3317catch (CloneNotSupportedException e) {3318// this shouldn't happen, since we are Cloneable3319throw new InternalError(e);3320}3321}33223323private static final String[] FIELD_NAME = {3324"ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH",3325"DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR",3326"HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",3327"DST_OFFSET"3328};33293330/**3331* Returns the name of the specified calendar field.3332*3333* @param field the calendar field3334* @return the calendar field name3335* @throws IndexOutOfBoundsException if {@code field} is negative,3336* equal to or greater than {@code FIELD_COUNT}.3337*/3338static String getFieldName(int field) {3339return FIELD_NAME[field];3340}33413342/**3343* Return a string representation of this calendar. This method3344* is intended to be used only for debugging purposes, and the3345* format of the returned string may vary between implementations.3346* The returned string may be empty but may not be {@code null}.3347*3348* @return a string representation of this calendar.3349*/3350@Override3351public String toString() {3352// NOTE: BuddhistCalendar.toString() interprets the string3353// produced by this method so that the Gregorian year number3354// is substituted by its B.E. year value. It relies on3355// "...,YEAR=<year>,..." or "...,YEAR=?,...".3356StringBuilder buffer = new StringBuilder(800);3357buffer.append(getClass().getName()).append('[');3358appendValue(buffer, "time", isTimeSet, time);3359buffer.append(",areFieldsSet=").append(areFieldsSet);3360buffer.append(",areAllFieldsSet=").append(areAllFieldsSet);3361buffer.append(",lenient=").append(lenient);3362buffer.append(",zone=").append(zone);3363appendValue(buffer, ",firstDayOfWeek", true, (long) firstDayOfWeek);3364appendValue(buffer, ",minimalDaysInFirstWeek", true, (long) minimalDaysInFirstWeek);3365for (int i = 0; i < FIELD_COUNT; ++i) {3366buffer.append(',');3367appendValue(buffer, FIELD_NAME[i], isSet(i), (long) fields[i]);3368}3369buffer.append(']');3370return buffer.toString();3371}33723373// =======================privates===============================33743375private static void appendValue(StringBuilder sb, String item, boolean valid, long value) {3376sb.append(item).append('=');3377if (valid) {3378sb.append(value);3379} else {3380sb.append('?');3381}3382}33833384/**3385* Both firstDayOfWeek and minimalDaysInFirstWeek are locale-dependent.3386* They are used to figure out the week count for a specific date for3387* a given locale. These must be set when a Calendar is constructed.3388* @param desiredLocale the given locale.3389*/3390private void setWeekCountData(Locale desiredLocale)3391{3392/* try to get the Locale data from the cache */3393int[] data = cachedLocaleData.get(desiredLocale);3394if (data == null) { /* cache miss */3395data = new int[2];3396data[0] = CalendarDataUtility.retrieveFirstDayOfWeek(desiredLocale);3397data[1] = CalendarDataUtility.retrieveMinimalDaysInFirstWeek(desiredLocale);3398cachedLocaleData.putIfAbsent(desiredLocale, data);3399}3400firstDayOfWeek = data[0];3401minimalDaysInFirstWeek = data[1];3402}34033404/**3405* Recomputes the time and updates the status fields isTimeSet3406* and areFieldsSet. Callers should check isTimeSet and only3407* call this method if isTimeSet is false.3408*/3409private void updateTime() {3410computeTime();3411// The areFieldsSet and areAllFieldsSet values are no longer3412// controlled here (as of 1.5).3413isTimeSet = true;3414}34153416private int compareTo(long t) {3417long thisTime = getMillisOf(this);3418return (thisTime > t) ? 1 : (thisTime == t) ? 0 : -1;3419}34203421private static long getMillisOf(Calendar calendar) {3422if (calendar.isTimeSet) {3423return calendar.time;3424}3425Calendar cal = (Calendar) calendar.clone();3426cal.setLenient(true);3427return cal.getTimeInMillis();3428}34293430/**3431* Adjusts the stamp[] values before nextStamp overflow. nextStamp3432* is set to the next stamp value upon the return.3433*/3434private void adjustStamp() {3435int max = MINIMUM_USER_STAMP;3436int newStamp = MINIMUM_USER_STAMP;34373438for (;;) {3439int min = Integer.MAX_VALUE;3440for (int v : stamp) {3441if (v >= newStamp && min > v) {3442min = v;3443}3444if (max < v) {3445max = v;3446}3447}3448if (max != min && min == Integer.MAX_VALUE) {3449break;3450}3451for (int i = 0; i < stamp.length; i++) {3452if (stamp[i] == min) {3453stamp[i] = newStamp;3454}3455}3456newStamp++;3457if (min == max) {3458break;3459}3460}3461nextStamp = newStamp;3462}34633464/**3465* Sets the WEEK_OF_MONTH and WEEK_OF_YEAR fields to new values with the3466* new parameter value if they have been calculated internally.3467*/3468private void invalidateWeekFields()3469{3470if (stamp[WEEK_OF_MONTH] != COMPUTED &&3471stamp[WEEK_OF_YEAR] != COMPUTED) {3472return;3473}34743475// We have to check the new values of these fields after changing3476// firstDayOfWeek and/or minimalDaysInFirstWeek. If the field values3477// have been changed, then set the new values. (4822110)3478Calendar cal = (Calendar) clone();3479cal.setLenient(true);3480cal.clear(WEEK_OF_MONTH);3481cal.clear(WEEK_OF_YEAR);34823483if (stamp[WEEK_OF_MONTH] == COMPUTED) {3484int weekOfMonth = cal.get(WEEK_OF_MONTH);3485if (fields[WEEK_OF_MONTH] != weekOfMonth) {3486fields[WEEK_OF_MONTH] = weekOfMonth;3487}3488}34893490if (stamp[WEEK_OF_YEAR] == COMPUTED) {3491int weekOfYear = cal.get(WEEK_OF_YEAR);3492if (fields[WEEK_OF_YEAR] != weekOfYear) {3493fields[WEEK_OF_YEAR] = weekOfYear;3494}3495}3496}34973498/**3499* Save the state of this object to a stream (i.e., serialize it).3500*3501* Ideally, {@code Calendar} would only write out its state data and3502* the current time, and not write any field data out, such as3503* {@code fields[]}, {@code isTimeSet}, {@code areFieldsSet},3504* and {@code isSet[]}. {@code nextStamp} also should not be part3505* of the persistent state. Unfortunately, this didn't happen before JDK 1.13506* shipped. To be compatible with JDK 1.1, we will always have to write out3507* the field values and state flags. However, {@code nextStamp} can be3508* removed from the serialization stream; this will probably happen in the3509* near future.3510*/3511@java.io.Serial3512private synchronized void writeObject(ObjectOutputStream stream)3513throws IOException3514{3515// Try to compute the time correctly, for the future (stream3516// version 2) in which we don't write out fields[] or isSet[].3517if (!isTimeSet) {3518try {3519updateTime();3520}3521catch (IllegalArgumentException e) {}3522}35233524// If this Calendar has a ZoneInfo, save it and set a3525// SimpleTimeZone equivalent (as a single DST schedule) for3526// backward compatibility.3527TimeZone savedZone = null;3528if (zone instanceof ZoneInfo) {3529SimpleTimeZone stz = ((ZoneInfo)zone).getLastRuleInstance();3530if (stz == null) {3531stz = new SimpleTimeZone(zone.getRawOffset(), zone.getID());3532}3533savedZone = zone;3534zone = stz;3535}35363537// Write out the 1.1 FCS object.3538stream.defaultWriteObject();35393540// Write out the ZoneInfo object3541// 4802409: we write out even if it is null, a temporary workaround3542// the real fix for bug 4844924 in corba-iiop3543stream.writeObject(savedZone);3544if (savedZone != null) {3545zone = savedZone;3546}3547}35483549@SuppressWarnings("removal")3550private static class CalendarAccessControlContext {3551private static final AccessControlContext INSTANCE;3552static {3553RuntimePermission perm = new RuntimePermission("accessClassInPackage.sun.util.calendar");3554PermissionCollection perms = perm.newPermissionCollection();3555perms.add(perm);3556INSTANCE = new AccessControlContext(new ProtectionDomain[] {3557new ProtectionDomain(null, perms)3558});3559}3560private CalendarAccessControlContext() {3561}3562}35633564/**3565* Reconstitutes this object from a stream (i.e., deserialize it).3566*/3567@SuppressWarnings("removal")3568@java.io.Serial3569private void readObject(ObjectInputStream stream)3570throws IOException, ClassNotFoundException3571{3572final ObjectInputStream input = stream;3573input.defaultReadObject();35743575stamp = new int[FIELD_COUNT];35763577// Starting with version 2 (not implemented yet), we expect that3578// fields[], isSet[], isTimeSet, and areFieldsSet may not be3579// streamed out anymore. We expect 'time' to be correct.3580if (serialVersionOnStream >= 2)3581{3582isTimeSet = true;3583if (fields == null) {3584fields = new int[FIELD_COUNT];3585}3586if (isSet == null) {3587isSet = new boolean[FIELD_COUNT];3588}3589}3590else if (serialVersionOnStream >= 0)3591{3592for (int i=0; i<FIELD_COUNT; ++i) {3593stamp[i] = isSet[i] ? COMPUTED : UNSET;3594}3595}35963597serialVersionOnStream = currentSerialVersion;35983599// If there's a ZoneInfo object, use it for zone.3600ZoneInfo zi = null;3601try {3602zi = AccessController.doPrivileged(3603new PrivilegedExceptionAction<>() {3604@Override3605public ZoneInfo run() throws Exception {3606return (ZoneInfo) input.readObject();3607}3608},3609CalendarAccessControlContext.INSTANCE);3610} catch (PrivilegedActionException pae) {3611Exception e = pae.getException();3612if (!(e instanceof OptionalDataException)) {3613if (e instanceof RuntimeException) {3614throw (RuntimeException) e;3615} else if (e instanceof IOException) {3616throw (IOException) e;3617} else if (e instanceof ClassNotFoundException) {3618throw (ClassNotFoundException) e;3619}3620throw new RuntimeException(e);3621}3622}3623if (zi != null) {3624zone = zi;3625}36263627// If the deserialized object has a SimpleTimeZone, try to3628// replace it with a ZoneInfo equivalent (as of 1.4) in order3629// to be compatible with the SimpleTimeZone-based3630// implementation as much as possible.3631if (zone instanceof SimpleTimeZone) {3632String id = zone.getID();3633TimeZone tz = TimeZone.getTimeZone(id);3634if (tz != null && tz.hasSameRules(zone) && tz.getID().equals(id)) {3635zone = tz;3636}3637}3638}36393640/**3641* Converts this object to an {@link Instant}.3642* <p>3643* The conversion creates an {@code Instant} that represents the3644* same point on the time-line as this {@code Calendar}.3645*3646* @return the instant representing the same point on the time-line3647* @since 1.83648*/3649public final Instant toInstant() {3650return Instant.ofEpochMilli(getTimeInMillis());3651}3652}365336543655