1 /*
   2  * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * (C) Copyright Taligent, Inc. 1996-1998 - All Rights Reserved
  28  * (C) Copyright IBM Corp. 1996-1998 - All Rights Reserved
  29  *
  30  *   The original version of this source code and documentation is copyrighted
  31  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  32  * materials are provided under terms of a License Agreement between Taligent
  33  * and Sun. This technology is protected by multiple US and International
  34  * patents. This notice and attribution to Taligent may not be removed.
  35  *   Taligent is a registered trademark of Taligent, Inc.
  36  *
  37  */
  38 
  39 package java.util;
  40 
  41 import java.io.IOException;
  42 import java.io.ObjectInputStream;
  43 import java.time.Instant;
  44 import java.time.ZonedDateTime;
  45 import java.time.temporal.ChronoField;
  46 import sun.util.calendar.BaseCalendar;
  47 import sun.util.calendar.CalendarDate;
  48 import sun.util.calendar.CalendarSystem;
  49 import sun.util.calendar.CalendarUtils;
  50 import sun.util.calendar.Era;
  51 import sun.util.calendar.Gregorian;
  52 import sun.util.calendar.JulianCalendar;
  53 import sun.util.calendar.ZoneInfo;
  54 
  55 /**
  56  * <code>GregorianCalendar</code> is a concrete subclass of
  57  * <code>Calendar</code> and provides the standard calendar system
  58  * used by most of the world.
  59  *
  60  * <p> <code>GregorianCalendar</code> is a hybrid calendar that
  61  * supports both the Julian and Gregorian calendar systems with the
  62  * support of a single discontinuity, which corresponds by default to
  63  * the Gregorian date when the Gregorian calendar was instituted
  64  * (October 15, 1582 in some countries, later in others).  The cutover
  65  * date may be changed by the caller by calling {@link
  66  * #setGregorianChange(Date) setGregorianChange()}.
  67  *
  68  * <p>
  69  * Historically, in those countries which adopted the Gregorian calendar first,
  70  * October 4, 1582 (Julian) was thus followed by October 15, 1582 (Gregorian). This calendar models
  71  * this correctly.  Before the Gregorian cutover, <code>GregorianCalendar</code>
  72  * implements the Julian calendar.  The only difference between the Gregorian
  73  * and the Julian calendar is the leap year rule. The Julian calendar specifies
  74  * leap years every four years, whereas the Gregorian calendar omits century
  75  * years which are not divisible by 400.
  76  *
  77  * <p>
  78  * <code>GregorianCalendar</code> implements <em>proleptic</em> Gregorian and
  79  * Julian calendars. That is, dates are computed by extrapolating the current
  80  * rules indefinitely far backward and forward in time. As a result,
  81  * <code>GregorianCalendar</code> may be used for all years to generate
  82  * meaningful and consistent results. However, dates obtained using
  83  * <code>GregorianCalendar</code> are historically accurate only from March 1, 4
  84  * AD onward, when modern Julian calendar rules were adopted.  Before this date,
  85  * leap year rules were applied irregularly, and before 45 BC the Julian
  86  * calendar did not even exist.
  87  *
  88  * <p>
  89  * Prior to the institution of the Gregorian calendar, New Year's Day was
  90  * March 25. To avoid confusion, this calendar always uses January 1. A manual
  91  * adjustment may be made if desired for dates that are prior to the Gregorian
  92  * changeover and which fall between January 1 and March 24.
  93  *
  94  * <h3><a id="week_and_year">Week Of Year and Week Year</a></h3>
  95  *
  96  * <p>Values calculated for the {@link Calendar#WEEK_OF_YEAR
  97  * WEEK_OF_YEAR} field range from 1 to 53. The first week of a
  98  * calendar year is the earliest seven day period starting on {@link
  99  * Calendar#getFirstDayOfWeek() getFirstDayOfWeek()} that contains at
 100  * least {@link Calendar#getMinimalDaysInFirstWeek()
 101  * getMinimalDaysInFirstWeek()} days from that year. It thus depends
 102  * on the values of {@code getMinimalDaysInFirstWeek()}, {@code
 103  * getFirstDayOfWeek()}, and the day of the week of January 1. Weeks
 104  * between week 1 of one year and week 1 of the following year
 105  * (exclusive) are numbered sequentially from 2 to 52 or 53 (except
 106  * for year(s) involved in the Julian-Gregorian transition).
 107  *
 108  * <p>The {@code getFirstDayOfWeek()} and {@code
 109  * getMinimalDaysInFirstWeek()} values are initialized using
 110  * locale-dependent resources when constructing a {@code
 111  * GregorianCalendar}. <a id="iso8601_compatible_setting">The week
 112  * determination is compatible</a> with the ISO 8601 standard when {@code
 113  * getFirstDayOfWeek()} is {@code MONDAY} and {@code
 114  * getMinimalDaysInFirstWeek()} is 4, which values are used in locales
 115  * where the standard is preferred. These values can explicitly be set by
 116  * calling {@link Calendar#setFirstDayOfWeek(int) setFirstDayOfWeek()} and
 117  * {@link Calendar#setMinimalDaysInFirstWeek(int)
 118  * setMinimalDaysInFirstWeek()}.
 119  *
 120  * <p>A <a id="week_year"><em>week year</em></a> is in sync with a
 121  * {@code WEEK_OF_YEAR} cycle. All weeks between the first and last
 122  * weeks (inclusive) have the same <em>week year</em> value.
 123  * Therefore, the first and last days of a week year may have
 124  * different calendar year values.
 125  *
 126  * <p>For example, January 1, 1998 is a Thursday. If {@code
 127  * getFirstDayOfWeek()} is {@code MONDAY} and {@code
 128  * getMinimalDaysInFirstWeek()} is 4 (ISO 8601 standard compatible
 129  * setting), then week 1 of 1998 starts on December 29, 1997, and ends
 130  * on January 4, 1998. The week year is 1998 for the last three days
 131  * of calendar year 1997. If, however, {@code getFirstDayOfWeek()} is
 132  * {@code SUNDAY}, then week 1 of 1998 starts on January 4, 1998, and
 133  * ends on January 10, 1998; the first three days of 1998 then are
 134  * part of week 53 of 1997 and their week year is 1997.
 135  *
 136  * <h4>Week Of Month</h4>
 137  *
 138  * <p>Values calculated for the <code>WEEK_OF_MONTH</code> field range from 0
 139  * to 6.  Week 1 of a month (the days with <code>WEEK_OF_MONTH =
 140  * 1</code>) is the earliest set of at least
 141  * <code>getMinimalDaysInFirstWeek()</code> contiguous days in that month,
 142  * ending on the day before <code>getFirstDayOfWeek()</code>.  Unlike
 143  * week 1 of a year, week 1 of a month may be shorter than 7 days, need
 144  * not start on <code>getFirstDayOfWeek()</code>, and will not include days of
 145  * the previous month.  Days of a month before week 1 have a
 146  * <code>WEEK_OF_MONTH</code> of 0.
 147  *
 148  * <p>For example, if <code>getFirstDayOfWeek()</code> is <code>SUNDAY</code>
 149  * and <code>getMinimalDaysInFirstWeek()</code> is 4, then the first week of
 150  * January 1998 is Sunday, January 4 through Saturday, January 10.  These days
 151  * have a <code>WEEK_OF_MONTH</code> of 1.  Thursday, January 1 through
 152  * Saturday, January 3 have a <code>WEEK_OF_MONTH</code> of 0.  If
 153  * <code>getMinimalDaysInFirstWeek()</code> is changed to 3, then January 1
 154  * through January 3 have a <code>WEEK_OF_MONTH</code> of 1.
 155  *
 156  * <h4>Default Fields Values</h4>
 157  *
 158  * <p>The <code>clear</code> method sets calendar field(s)
 159  * undefined. <code>GregorianCalendar</code> uses the following
 160  * default value for each calendar field if its value is undefined.
 161  *
 162  * <table class="striped" style="text-align: left; width: 66%;">
 163  * <caption style="display:none">GregorianCalendar default field values</caption>
 164  *   <thead>
 165  *     <tr>
 166  *       <th scope="col">
 167  *          Field
 168  *       </th>
 169  *       <th scope="col">
 170             Default Value
 171  *       </th>
 172  *     </tr>
 173  *   </thead>
 174  *   <tbody>
 175  *     <tr>
 176  *       <th scope="row">
 177  *              <code>ERA</code>
 178  *       </th>
 179  *       <td>
 180  *              <code>AD</code>
 181  *       </td>
 182  *     </tr>
 183  *     <tr>
 184  *       <th scope="row">
 185  *              <code>YEAR</code>
 186  *       </th>
 187  *       <td>
 188  *              <code>1970</code>
 189  *       </td>
 190  *     </tr>
 191  *     <tr>
 192  *       <th scope="row">
 193  *              <code>MONTH</code>
 194  *       </th>
 195  *       <td>
 196  *              <code>JANUARY</code>
 197  *       </td>
 198  *     </tr>
 199  *     <tr>
 200  *       <th scope="row">
 201  *              <code>DAY_OF_MONTH</code>
 202  *       </th>
 203  *       <td>
 204  *              <code>1</code>
 205  *       </td>
 206  *     </tr>
 207  *     <tr>
 208  *       <th scope="row">
 209  *              <code>DAY_OF_WEEK</code>
 210  *       </th>
 211  *       <td>
 212  *              <code>the first day of week</code>
 213  *       </td>
 214  *     </tr>
 215  *     <tr>
 216  *       <th scope="row">
 217  *              <code>WEEK_OF_MONTH</code>
 218  *       </th>
 219  *       <td>
 220  *              <code>0</code>
 221  *       </td>
 222  *     </tr>
 223  *     <tr>
 224  *       <th scope="row">
 225  *              <code>DAY_OF_WEEK_IN_MONTH</code>
 226  *       </th>
 227  *       <td>
 228  *              <code>1</code>
 229  *       </td>
 230  *     </tr>
 231  *     <tr>
 232  *       <th scope="row">
 233  *              <code>AM_PM</code>
 234  *       </th>
 235  *       <td>
 236  *              <code>AM</code>
 237  *       </td>
 238  *     </tr>
 239  *     <tr>
 240  *       <th scope="row">
 241  *              <code>HOUR, HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code>
 242  *       </th>
 243  *       <td>
 244  *              <code>0</code>
 245  *       </td>
 246  *     </tr>
 247  *   </tbody>
 248  * </table>
 249  * <br>Default values are not applicable for the fields not listed above.
 250  *
 251  * <p>
 252  * <strong>Example:</strong>
 253  * <blockquote>
 254  * <pre>
 255  * // get the supported ids for GMT-08:00 (Pacific Standard Time)
 256  * String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
 257  * // if no ids were returned, something is wrong. get out.
 258  * if (ids.length == 0)
 259  *     System.exit(0);
 260  *
 261  *  // begin output
 262  * System.out.println("Current Time");
 263  *
 264  * // create a Pacific Standard Time time zone
 265  * SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);
 266  *
 267  * // set up rules for Daylight Saving Time
 268  * pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
 269  * pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
 270  *
 271  * // create a GregorianCalendar with the Pacific Daylight time zone
 272  * // and the current date and time
 273  * Calendar calendar = new GregorianCalendar(pdt);
 274  * Date trialTime = new Date();
 275  * calendar.setTime(trialTime);
 276  *
 277  * // print out a bunch of interesting things
 278  * System.out.println("ERA: " + calendar.get(Calendar.ERA));
 279  * System.out.println("YEAR: " + calendar.get(Calendar.YEAR));
 280  * System.out.println("MONTH: " + calendar.get(Calendar.MONTH));
 281  * System.out.println("WEEK_OF_YEAR: " + calendar.get(Calendar.WEEK_OF_YEAR));
 282  * System.out.println("WEEK_OF_MONTH: " + calendar.get(Calendar.WEEK_OF_MONTH));
 283  * System.out.println("DATE: " + calendar.get(Calendar.DATE));
 284  * System.out.println("DAY_OF_MONTH: " + calendar.get(Calendar.DAY_OF_MONTH));
 285  * System.out.println("DAY_OF_YEAR: " + calendar.get(Calendar.DAY_OF_YEAR));
 286  * System.out.println("DAY_OF_WEEK: " + calendar.get(Calendar.DAY_OF_WEEK));
 287  * System.out.println("DAY_OF_WEEK_IN_MONTH: "
 288  *                    + calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));
 289  * System.out.println("AM_PM: " + calendar.get(Calendar.AM_PM));
 290  * System.out.println("HOUR: " + calendar.get(Calendar.HOUR));
 291  * System.out.println("HOUR_OF_DAY: " + calendar.get(Calendar.HOUR_OF_DAY));
 292  * System.out.println("MINUTE: " + calendar.get(Calendar.MINUTE));
 293  * System.out.println("SECOND: " + calendar.get(Calendar.SECOND));
 294  * System.out.println("MILLISECOND: " + calendar.get(Calendar.MILLISECOND));
 295  * System.out.println("ZONE_OFFSET: "
 296  *                    + (calendar.get(Calendar.ZONE_OFFSET)/(60*60*1000)));
 297  * System.out.println("DST_OFFSET: "
 298  *                    + (calendar.get(Calendar.DST_OFFSET)/(60*60*1000)));
 299 
 300  * System.out.println("Current Time, with hour reset to 3");
 301  * calendar.clear(Calendar.HOUR_OF_DAY); // so doesn't override
 302  * calendar.set(Calendar.HOUR, 3);
 303  * System.out.println("ERA: " + calendar.get(Calendar.ERA));
 304  * System.out.println("YEAR: " + calendar.get(Calendar.YEAR));
 305  * System.out.println("MONTH: " + calendar.get(Calendar.MONTH));
 306  * System.out.println("WEEK_OF_YEAR: " + calendar.get(Calendar.WEEK_OF_YEAR));
 307  * System.out.println("WEEK_OF_MONTH: " + calendar.get(Calendar.WEEK_OF_MONTH));
 308  * System.out.println("DATE: " + calendar.get(Calendar.DATE));
 309  * System.out.println("DAY_OF_MONTH: " + calendar.get(Calendar.DAY_OF_MONTH));
 310  * System.out.println("DAY_OF_YEAR: " + calendar.get(Calendar.DAY_OF_YEAR));
 311  * System.out.println("DAY_OF_WEEK: " + calendar.get(Calendar.DAY_OF_WEEK));
 312  * System.out.println("DAY_OF_WEEK_IN_MONTH: "
 313  *                    + calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));
 314  * System.out.println("AM_PM: " + calendar.get(Calendar.AM_PM));
 315  * System.out.println("HOUR: " + calendar.get(Calendar.HOUR));
 316  * System.out.println("HOUR_OF_DAY: " + calendar.get(Calendar.HOUR_OF_DAY));
 317  * System.out.println("MINUTE: " + calendar.get(Calendar.MINUTE));
 318  * System.out.println("SECOND: " + calendar.get(Calendar.SECOND));
 319  * System.out.println("MILLISECOND: " + calendar.get(Calendar.MILLISECOND));
 320  * System.out.println("ZONE_OFFSET: "
 321  *        + (calendar.get(Calendar.ZONE_OFFSET)/(60*60*1000))); // in hours
 322  * System.out.println("DST_OFFSET: "
 323  *        + (calendar.get(Calendar.DST_OFFSET)/(60*60*1000))); // in hours
 324  * </pre>
 325  * </blockquote>
 326  *
 327  * @see          TimeZone
 328  * @author David Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu
 329  * @since 1.1
 330  */
 331 public class GregorianCalendar extends Calendar {
 332     /*
 333      * Implementation Notes
 334      *
 335      * The epoch is the number of days or milliseconds from some defined
 336      * starting point. The epoch for java.util.Date is used here; that is,
 337      * milliseconds from January 1, 1970 (Gregorian), midnight UTC.  Other
 338      * epochs which are used are January 1, year 1 (Gregorian), which is day 1
 339      * of the Gregorian calendar, and December 30, year 0 (Gregorian), which is
 340      * day 1 of the Julian calendar.
 341      *
 342      * We implement the proleptic Julian and Gregorian calendars.  This means we
 343      * implement the modern definition of the calendar even though the
 344      * historical usage differs.  For example, if the Gregorian change is set
 345      * to new Date(Long.MIN_VALUE), we have a pure Gregorian calendar which
 346      * labels dates preceding the invention of the Gregorian calendar in 1582 as
 347      * if the calendar existed then.
 348      *
 349      * Likewise, with the Julian calendar, we assume a consistent
 350      * 4-year leap year rule, even though the historical pattern of
 351      * leap years is irregular, being every 3 years from 45 BCE
 352      * through 9 BCE, then every 4 years from 8 CE onwards, with no
 353      * leap years in-between.  Thus date computations and functions
 354      * such as isLeapYear() are not intended to be historically
 355      * accurate.
 356      */
 357 
 358 //////////////////
 359 // Class Variables
 360 //////////////////
 361 
 362     /**
 363      * Value of the <code>ERA</code> field indicating
 364      * the period before the common era (before Christ), also known as BCE.
 365      * The sequence of years at the transition from <code>BC</code> to <code>AD</code> is
 366      * ..., 2 BC, 1 BC, 1 AD, 2 AD,...
 367      *
 368      * @see #ERA
 369      */
 370     public static final int BC = 0;
 371 
 372     /**
 373      * Value of the {@link #ERA} field indicating
 374      * the period before the common era, the same value as {@link #BC}.
 375      *
 376      * @see #CE
 377      */
 378     static final int BCE = 0;
 379 
 380     /**
 381      * Value of the <code>ERA</code> field indicating
 382      * the common era (Anno Domini), also known as CE.
 383      * The sequence of years at the transition from <code>BC</code> to <code>AD</code> is
 384      * ..., 2 BC, 1 BC, 1 AD, 2 AD,...
 385      *
 386      * @see #ERA
 387      */
 388     public static final int AD = 1;
 389 
 390     /**
 391      * Value of the {@link #ERA} field indicating
 392      * the common era, the same value as {@link #AD}.
 393      *
 394      * @see #BCE
 395      */
 396     static final int CE = 1;
 397 
 398     private static final int EPOCH_OFFSET   = 719163; // Fixed date of January 1, 1970 (Gregorian)
 399     private static final int EPOCH_YEAR     = 1970;
 400 
 401     static final int MONTH_LENGTH[]
 402         = {31,28,31,30,31,30,31,31,30,31,30,31}; // 0-based
 403     static final int LEAP_MONTH_LENGTH[]
 404         = {31,29,31,30,31,30,31,31,30,31,30,31}; // 0-based
 405 
 406     // Useful millisecond constants.  Although ONE_DAY and ONE_WEEK can fit
 407     // into ints, they must be longs in order to prevent arithmetic overflow
 408     // when performing (bug 4173516).
 409     private static final int  ONE_SECOND = 1000;
 410     private static final int  ONE_MINUTE = 60*ONE_SECOND;
 411     private static final int  ONE_HOUR   = 60*ONE_MINUTE;
 412     private static final long ONE_DAY    = 24*ONE_HOUR;
 413     private static final long ONE_WEEK   = 7*ONE_DAY;
 414 
 415     /*
 416      * <pre>
 417      *                            Greatest       Least
 418      * Field name        Minimum   Minimum     Maximum     Maximum
 419      * ----------        -------   -------     -------     -------
 420      * ERA                     0         0           1           1
 421      * YEAR                    1         1   292269054   292278994
 422      * MONTH                   0         0          11          11
 423      * WEEK_OF_YEAR            1         1          52*         53
 424      * WEEK_OF_MONTH           0         0           4*          6
 425      * DAY_OF_MONTH            1         1          28*         31
 426      * DAY_OF_YEAR             1         1         365*        366
 427      * DAY_OF_WEEK             1         1           7           7
 428      * DAY_OF_WEEK_IN_MONTH    1         1           4*          6
 429      * AM_PM                   0         0           1           1
 430      * HOUR                    0         0          11          11
 431      * HOUR_OF_DAY             0         0          23          23
 432      * MINUTE                  0         0          59          59
 433      * SECOND                  0         0          59          59
 434      * MILLISECOND             0         0         999         999
 435      * ZONE_OFFSET        -13:00    -13:00       14:00       14:00
 436      * DST_OFFSET           0:00      0:00        0:20        2:00
 437      * </pre>
 438      * *: depends on the Gregorian change date
 439      */
 440     static final int MIN_VALUES[] = {
 441         BCE,            // ERA
 442         1,              // YEAR
 443         JANUARY,        // MONTH
 444         1,              // WEEK_OF_YEAR
 445         0,              // WEEK_OF_MONTH
 446         1,              // DAY_OF_MONTH
 447         1,              // DAY_OF_YEAR
 448         SUNDAY,         // DAY_OF_WEEK
 449         1,              // DAY_OF_WEEK_IN_MONTH
 450         AM,             // AM_PM
 451         0,              // HOUR
 452         0,              // HOUR_OF_DAY
 453         0,              // MINUTE
 454         0,              // SECOND
 455         0,              // MILLISECOND
 456         -13*ONE_HOUR,   // ZONE_OFFSET (UNIX compatibility)
 457         0               // DST_OFFSET
 458     };
 459     static final int LEAST_MAX_VALUES[] = {
 460         CE,             // ERA
 461         292269054,      // YEAR
 462         DECEMBER,       // MONTH
 463         52,             // WEEK_OF_YEAR
 464         4,              // WEEK_OF_MONTH
 465         28,             // DAY_OF_MONTH
 466         365,            // DAY_OF_YEAR
 467         SATURDAY,       // DAY_OF_WEEK
 468         4,              // DAY_OF_WEEK_IN
 469         PM,             // AM_PM
 470         11,             // HOUR
 471         23,             // HOUR_OF_DAY
 472         59,             // MINUTE
 473         59,             // SECOND
 474         999,            // MILLISECOND
 475         14*ONE_HOUR,    // ZONE_OFFSET
 476         20*ONE_MINUTE   // DST_OFFSET (historical least maximum)
 477     };
 478     static final int MAX_VALUES[] = {
 479         CE,             // ERA
 480         292278994,      // YEAR
 481         DECEMBER,       // MONTH
 482         53,             // WEEK_OF_YEAR
 483         6,              // WEEK_OF_MONTH
 484         31,             // DAY_OF_MONTH
 485         366,            // DAY_OF_YEAR
 486         SATURDAY,       // DAY_OF_WEEK
 487         6,              // DAY_OF_WEEK_IN
 488         PM,             // AM_PM
 489         11,             // HOUR
 490         23,             // HOUR_OF_DAY
 491         59,             // MINUTE
 492         59,             // SECOND
 493         999,            // MILLISECOND
 494         14*ONE_HOUR,    // ZONE_OFFSET
 495         2*ONE_HOUR      // DST_OFFSET (double summer time)
 496     };
 497 
 498     // Proclaim serialization compatibility with JDK 1.1
 499     @SuppressWarnings("FieldNameHidesFieldInSuperclass")
 500     static final long serialVersionUID = -8125100834729963327L;
 501 
 502     // Reference to the sun.util.calendar.Gregorian instance (singleton).
 503     private static final Gregorian gcal =
 504                                 CalendarSystem.getGregorianCalendar();
 505 
 506     // Reference to the JulianCalendar instance (singleton), set as needed. See
 507     // getJulianCalendarSystem().
 508     private static JulianCalendar jcal;
 509 
 510     // JulianCalendar eras. See getJulianCalendarSystem().
 511     private static Era[] jeras;
 512 
 513     // The default value of gregorianCutover.
 514     static final long DEFAULT_GREGORIAN_CUTOVER = -12219292800000L;
 515 
 516 /////////////////////
 517 // Instance Variables
 518 /////////////////////
 519 
 520     /**
 521      * The point at which the Gregorian calendar rules are used, measured in
 522      * milliseconds from the standard epoch.  Default is October 15, 1582
 523      * (Gregorian) 00:00:00 UTC or -12219292800000L.  For this value, October 4,
 524      * 1582 (Julian) is followed by October 15, 1582 (Gregorian).  This
 525      * corresponds to Julian day number 2299161.
 526      * @serial
 527      */
 528     private long gregorianCutover = DEFAULT_GREGORIAN_CUTOVER;
 529 
 530     /**
 531      * The fixed date of the gregorianCutover.
 532      */
 533     private transient long gregorianCutoverDate =
 534         (((DEFAULT_GREGORIAN_CUTOVER + 1)/ONE_DAY) - 1) + EPOCH_OFFSET; // == 577736
 535 
 536     /**
 537      * The normalized year of the gregorianCutover in Gregorian, with
 538      * 0 representing 1 BCE, -1 representing 2 BCE, etc.
 539      */
 540     private transient int gregorianCutoverYear = 1582;
 541 
 542     /**
 543      * The normalized year of the gregorianCutover in Julian, with 0
 544      * representing 1 BCE, -1 representing 2 BCE, etc.
 545      */
 546     private transient int gregorianCutoverYearJulian = 1582;
 547 
 548     /**
 549      * gdate always has a sun.util.calendar.Gregorian.Date instance to
 550      * avoid overhead of creating it. The assumption is that most
 551      * applications will need only Gregorian calendar calculations.
 552      */
 553     private transient BaseCalendar.Date gdate;
 554 
 555     /**
 556      * Reference to either gdate or a JulianCalendar.Date
 557      * instance. After calling complete(), this value is guaranteed to
 558      * be set.
 559      */
 560     private transient BaseCalendar.Date cdate;
 561 
 562     /**
 563      * The CalendarSystem used to calculate the date in cdate. After
 564      * calling complete(), this value is guaranteed to be set and
 565      * consistent with the cdate value.
 566      */
 567     private transient BaseCalendar calsys;
 568 
 569     /**
 570      * Temporary int[2] to get time zone offsets. zoneOffsets[0] gets
 571      * the GMT offset value and zoneOffsets[1] gets the DST saving
 572      * value.
 573      */
 574     private transient int[] zoneOffsets;
 575 
 576     /**
 577      * Temporary storage for saving original fields[] values in
 578      * non-lenient mode.
 579      */
 580     private transient int[] originalFields;
 581 
 582 ///////////////
 583 // Constructors
 584 ///////////////
 585 
 586     /**
 587      * Constructs a default <code>GregorianCalendar</code> using the current time
 588      * in the default time zone with the default
 589      * {@link Locale.Category#FORMAT FORMAT} locale.
 590      */
 591     public GregorianCalendar() {
 592         this(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));
 593         setZoneShared(true);
 594     }
 595 
 596     /**
 597      * Constructs a <code>GregorianCalendar</code> based on the current time
 598      * in the given time zone with the default
 599      * {@link Locale.Category#FORMAT FORMAT} locale.
 600      *
 601      * @param zone the given time zone.
 602      */
 603     public GregorianCalendar(TimeZone zone) {
 604         this(zone, Locale.getDefault(Locale.Category.FORMAT));
 605     }
 606 
 607     /**
 608      * Constructs a <code>GregorianCalendar</code> based on the current time
 609      * in the default time zone with the given locale.
 610      *
 611      * @param aLocale the given locale.
 612      */
 613     public GregorianCalendar(Locale aLocale) {
 614         this(TimeZone.getDefaultRef(), aLocale);
 615         setZoneShared(true);
 616     }
 617 
 618     /**
 619      * Constructs a <code>GregorianCalendar</code> based on the current time
 620      * in the given time zone with the given locale.
 621      *
 622      * @param zone the given time zone.
 623      * @param aLocale the given locale.
 624      */
 625     public GregorianCalendar(TimeZone zone, Locale aLocale) {
 626         super(zone, aLocale);
 627         gdate = (BaseCalendar.Date) gcal.newCalendarDate(zone);
 628         setTimeInMillis(System.currentTimeMillis());
 629     }
 630 
 631     /**
 632      * Constructs a <code>GregorianCalendar</code> with the given date set
 633      * in the default time zone with the default locale.
 634      *
 635      * @param year the value used to set the <code>YEAR</code> calendar field in the calendar.
 636      * @param month the value used to set the <code>MONTH</code> calendar field in the calendar.
 637      * Month value is 0-based. e.g., 0 for January.
 638      * @param dayOfMonth the value used to set the <code>DAY_OF_MONTH</code> calendar field in the calendar.
 639      */
 640     public GregorianCalendar(int year, int month, int dayOfMonth) {
 641         this(year, month, dayOfMonth, 0, 0, 0, 0);
 642     }
 643 
 644     /**
 645      * Constructs a <code>GregorianCalendar</code> with the given date
 646      * and time set for the default time zone with the default locale.
 647      *
 648      * @param year the value used to set the <code>YEAR</code> calendar field in the calendar.
 649      * @param month the value used to set the <code>MONTH</code> calendar field in the calendar.
 650      * Month value is 0-based. e.g., 0 for January.
 651      * @param dayOfMonth the value used to set the <code>DAY_OF_MONTH</code> calendar field in the calendar.
 652      * @param hourOfDay the value used to set the <code>HOUR_OF_DAY</code> calendar field
 653      * in the calendar.
 654      * @param minute the value used to set the <code>MINUTE</code> calendar field
 655      * in the calendar.
 656      */
 657     public GregorianCalendar(int year, int month, int dayOfMonth, int hourOfDay,
 658                              int minute) {
 659         this(year, month, dayOfMonth, hourOfDay, minute, 0, 0);
 660     }
 661 
 662     /**
 663      * Constructs a GregorianCalendar with the given date
 664      * and time set for the default time zone with the default locale.
 665      *
 666      * @param year the value used to set the <code>YEAR</code> calendar field in the calendar.
 667      * @param month the value used to set the <code>MONTH</code> calendar field in the calendar.
 668      * Month value is 0-based. e.g., 0 for January.
 669      * @param dayOfMonth the value used to set the <code>DAY_OF_MONTH</code> calendar field in the calendar.
 670      * @param hourOfDay the value used to set the <code>HOUR_OF_DAY</code> calendar field
 671      * in the calendar.
 672      * @param minute the value used to set the <code>MINUTE</code> calendar field
 673      * in the calendar.
 674      * @param second the value used to set the <code>SECOND</code> calendar field
 675      * in the calendar.
 676      */
 677     public GregorianCalendar(int year, int month, int dayOfMonth, int hourOfDay,
 678                              int minute, int second) {
 679         this(year, month, dayOfMonth, hourOfDay, minute, second, 0);
 680     }
 681 
 682     /**
 683      * Constructs a <code>GregorianCalendar</code> with the given date
 684      * and time set for the default time zone with the default locale.
 685      *
 686      * @param year the value used to set the <code>YEAR</code> calendar field in the calendar.
 687      * @param month the value used to set the <code>MONTH</code> calendar field in the calendar.
 688      * Month value is 0-based. e.g., 0 for January.
 689      * @param dayOfMonth the value used to set the <code>DAY_OF_MONTH</code> calendar field in the calendar.
 690      * @param hourOfDay the value used to set the <code>HOUR_OF_DAY</code> calendar field
 691      * in the calendar.
 692      * @param minute the value used to set the <code>MINUTE</code> calendar field
 693      * in the calendar.
 694      * @param second the value used to set the <code>SECOND</code> calendar field
 695      * in the calendar.
 696      * @param millis the value used to set the <code>MILLISECOND</code> calendar field
 697      */
 698     GregorianCalendar(int year, int month, int dayOfMonth,
 699                       int hourOfDay, int minute, int second, int millis) {
 700         super();
 701         gdate = (BaseCalendar.Date) gcal.newCalendarDate(getZone());
 702         this.set(YEAR, year);
 703         this.set(MONTH, month);
 704         this.set(DAY_OF_MONTH, dayOfMonth);
 705 
 706         // Set AM_PM and HOUR here to set their stamp values before
 707         // setting HOUR_OF_DAY (6178071).
 708         if (hourOfDay >= 12 && hourOfDay <= 23) {
 709             // If hourOfDay is a valid PM hour, set the correct PM values
 710             // so that it won't throw an exception in case it's set to
 711             // non-lenient later.
 712             this.internalSet(AM_PM, PM);
 713             this.internalSet(HOUR, hourOfDay - 12);
 714         } else {
 715             // The default value for AM_PM is AM.
 716             // We don't care any out of range value here for leniency.
 717             this.internalSet(HOUR, hourOfDay);
 718         }
 719         // The stamp values of AM_PM and HOUR must be COMPUTED. (6440854)
 720         setFieldsComputed(HOUR_MASK|AM_PM_MASK);
 721 
 722         this.set(HOUR_OF_DAY, hourOfDay);
 723         this.set(MINUTE, minute);
 724         this.set(SECOND, second);
 725         // should be changed to set() when this constructor is made
 726         // public.
 727         this.internalSet(MILLISECOND, millis);
 728     }
 729 
 730     /**
 731      * Constructs an empty GregorianCalendar.
 732      *
 733      * @param zone    the given time zone
 734      * @param aLocale the given locale
 735      * @param flag    the flag requesting an empty instance
 736      */
 737     GregorianCalendar(TimeZone zone, Locale locale, boolean flag) {
 738         super(zone, locale);
 739         gdate = (BaseCalendar.Date) gcal.newCalendarDate(getZone());
 740     }
 741 
 742 /////////////////
 743 // Public methods
 744 /////////////////
 745 
 746     /**
 747      * Sets the <code>GregorianCalendar</code> change date. This is the point when the switch
 748      * from Julian dates to Gregorian dates occurred. Default is October 15,
 749      * 1582 (Gregorian). Previous to this, dates will be in the Julian calendar.
 750      * <p>
 751      * To obtain a pure Julian calendar, set the change date to
 752      * <code>Date(Long.MAX_VALUE)</code>.  To obtain a pure Gregorian calendar,
 753      * set the change date to <code>Date(Long.MIN_VALUE)</code>.
 754      *
 755      * @param date the given Gregorian cutover date.
 756      */
 757     public void setGregorianChange(Date date) {
 758         long cutoverTime = date.getTime();
 759         if (cutoverTime == gregorianCutover) {
 760             return;
 761         }
 762         // Before changing the cutover date, make sure to have the
 763         // time of this calendar.
 764         complete();
 765         setGregorianChange(cutoverTime);
 766     }
 767 
 768     private void setGregorianChange(long cutoverTime) {
 769         gregorianCutover = cutoverTime;
 770         gregorianCutoverDate = CalendarUtils.floorDivide(cutoverTime, ONE_DAY)
 771                                 + EPOCH_OFFSET;
 772 
 773         // To provide the "pure" Julian calendar as advertised.
 774         // Strictly speaking, the last millisecond should be a
 775         // Gregorian date. However, the API doc specifies that setting
 776         // the cutover date to Long.MAX_VALUE will make this calendar
 777         // a pure Julian calendar. (See 4167995)
 778         if (cutoverTime == Long.MAX_VALUE) {
 779             gregorianCutoverDate++;
 780         }
 781 
 782         BaseCalendar.Date d = getGregorianCutoverDate();
 783 
 784         // Set the cutover year (in the Gregorian year numbering)
 785         gregorianCutoverYear = d.getYear();
 786 
 787         BaseCalendar julianCal = getJulianCalendarSystem();
 788         d = (BaseCalendar.Date) julianCal.newCalendarDate(TimeZone.NO_TIMEZONE);
 789         julianCal.getCalendarDateFromFixedDate(d, gregorianCutoverDate - 1);
 790         gregorianCutoverYearJulian = d.getNormalizedYear();
 791 
 792         if (time < gregorianCutover) {
 793             // The field values are no longer valid under the new
 794             // cutover date.
 795             setUnnormalized();
 796         }
 797     }
 798 
 799     /**
 800      * Gets the Gregorian Calendar change date.  This is the point when the
 801      * switch from Julian dates to Gregorian dates occurred. Default is
 802      * October 15, 1582 (Gregorian). Previous to this, dates will be in the Julian
 803      * calendar.
 804      *
 805      * @return the Gregorian cutover date for this <code>GregorianCalendar</code> object.
 806      */
 807     public final Date getGregorianChange() {
 808         return new Date(gregorianCutover);
 809     }
 810 
 811     /**
 812      * Determines if the given year is a leap year. Returns <code>true</code> if
 813      * the given year is a leap year. To specify BC year numbers,
 814      * <code>1 - year number</code> must be given. For example, year BC 4 is
 815      * specified as -3.
 816      *
 817      * @param year the given year.
 818      * @return <code>true</code> if the given year is a leap year; <code>false</code> otherwise.
 819      */
 820     public boolean isLeapYear(int year) {
 821         if ((year & 3) != 0) {
 822             return false;
 823         }
 824 
 825         if (year > gregorianCutoverYear) {
 826             return (year%100 != 0) || (year%400 == 0); // Gregorian
 827         }
 828         if (year < gregorianCutoverYearJulian) {
 829             return true; // Julian
 830         }
 831         boolean gregorian;
 832         // If the given year is the Gregorian cutover year, we need to
 833         // determine which calendar system to be applied to February in the year.
 834         if (gregorianCutoverYear == gregorianCutoverYearJulian) {
 835             BaseCalendar.Date d = getCalendarDate(gregorianCutoverDate); // Gregorian
 836             gregorian = d.getMonth() < BaseCalendar.MARCH;
 837         } else {
 838             gregorian = year == gregorianCutoverYear;
 839         }
 840         return gregorian ? (year%100 != 0) || (year%400 == 0) : true;
 841     }
 842 
 843     /**
 844      * Returns {@code "gregory"} as the calendar type.
 845      *
 846      * @return {@code "gregory"}
 847      * @since 1.8
 848      */
 849     @Override
 850     public String getCalendarType() {
 851         return "gregory";
 852     }
 853 
 854     /**
 855      * Compares this <code>GregorianCalendar</code> to the specified
 856      * <code>Object</code>. The result is <code>true</code> if and
 857      * only if the argument is a <code>GregorianCalendar</code> object
 858      * that represents the same time value (millisecond offset from
 859      * the <a href="Calendar.html#Epoch">Epoch</a>) under the same
 860      * <code>Calendar</code> parameters and Gregorian change date as
 861      * this object.
 862      *
 863      * @param obj the object to compare with.
 864      * @return <code>true</code> if this object is equal to <code>obj</code>;
 865      * <code>false</code> otherwise.
 866      * @see Calendar#compareTo(Calendar)
 867      */
 868     @Override
 869     public boolean equals(Object obj) {
 870         return obj instanceof GregorianCalendar &&
 871             super.equals(obj) &&
 872             gregorianCutover == ((GregorianCalendar)obj).gregorianCutover;
 873     }
 874 
 875     /**
 876      * Generates the hash code for this <code>GregorianCalendar</code> object.
 877      */
 878     @Override
 879     public int hashCode() {
 880         return super.hashCode() ^ (int)gregorianCutoverDate;
 881     }
 882 
 883     /**
 884      * Adds the specified (signed) amount of time to the given calendar field,
 885      * based on the calendar's rules.
 886      *
 887      * <p><em>Add rule 1</em>. The value of <code>field</code>
 888      * after the call minus the value of <code>field</code> before the
 889      * call is <code>amount</code>, modulo any overflow that has occurred in
 890      * <code>field</code>. Overflow occurs when a field value exceeds its
 891      * range and, as a result, the next larger field is incremented or
 892      * decremented and the field value is adjusted back into its range.</p>
 893      *
 894      * <p><em>Add rule 2</em>. If a smaller field is expected to be
 895      * invariant, but it is impossible for it to be equal to its
 896      * prior value because of changes in its minimum or maximum after
 897      * <code>field</code> is changed, then its value is adjusted to be as close
 898      * as possible to its expected value. A smaller field represents a
 899      * smaller unit of time. <code>HOUR</code> is a smaller field than
 900      * <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields
 901      * that are not expected to be invariant. The calendar system
 902      * determines what fields are expected to be invariant.</p>
 903      *
 904      * @param field the calendar field.
 905      * @param amount the amount of date or time to be added to the field.
 906      * @exception IllegalArgumentException if <code>field</code> is
 907      * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
 908      * or if any calendar fields have out-of-range values in
 909      * non-lenient mode.
 910      */
 911     @Override
 912     public void add(int field, int amount) {
 913         // If amount == 0, do nothing even the given field is out of
 914         // range. This is tested by JCK.
 915         if (amount == 0) {
 916             return;   // Do nothing!
 917         }
 918 
 919         if (field < 0 || field >= ZONE_OFFSET) {
 920             throw new IllegalArgumentException();
 921         }
 922 
 923         // Sync the time and calendar fields.
 924         complete();
 925 
 926         if (field == YEAR) {
 927             int year = internalGet(YEAR);
 928             if (internalGetEra() == CE) {
 929                 year += amount;
 930                 if (year > 0) {
 931                     set(YEAR, year);
 932                 } else { // year <= 0
 933                     set(YEAR, 1 - year);
 934                     // if year == 0, you get 1 BCE.
 935                     set(ERA, BCE);
 936                 }
 937             }
 938             else { // era == BCE
 939                 year -= amount;
 940                 if (year > 0) {
 941                     set(YEAR, year);
 942                 } else { // year <= 0
 943                     set(YEAR, 1 - year);
 944                     // if year == 0, you get 1 CE
 945                     set(ERA, CE);
 946                 }
 947             }
 948             pinDayOfMonth();
 949         } else if (field == MONTH) {
 950             int month = internalGet(MONTH) + amount;
 951             int year = internalGet(YEAR);
 952             int y_amount;
 953 
 954             if (month >= 0) {
 955                 y_amount = month/12;
 956             } else {
 957                 y_amount = (month+1)/12 - 1;
 958             }
 959             if (y_amount != 0) {
 960                 if (internalGetEra() == CE) {
 961                     year += y_amount;
 962                     if (year > 0) {
 963                         set(YEAR, year);
 964                     } else { // year <= 0
 965                         set(YEAR, 1 - year);
 966                         // if year == 0, you get 1 BCE
 967                         set(ERA, BCE);
 968                     }
 969                 }
 970                 else { // era == BCE
 971                     year -= y_amount;
 972                     if (year > 0) {
 973                         set(YEAR, year);
 974                     } else { // year <= 0
 975                         set(YEAR, 1 - year);
 976                         // if year == 0, you get 1 CE
 977                         set(ERA, CE);
 978                     }
 979                 }
 980             }
 981 
 982             if (month >= 0) {
 983                 set(MONTH,  month % 12);
 984             } else {
 985                 // month < 0
 986                 month %= 12;
 987                 if (month < 0) {
 988                     month += 12;
 989                 }
 990                 set(MONTH, JANUARY + month);
 991             }
 992             pinDayOfMonth();
 993         } else if (field == ERA) {
 994             int era = internalGet(ERA) + amount;
 995             if (era < 0) {
 996                 era = 0;
 997             }
 998             if (era > 1) {
 999                 era = 1;
1000             }
1001             set(ERA, era);
1002         } else {
1003             long delta = amount;
1004             long timeOfDay = 0;
1005             switch (field) {
1006             // Handle the time fields here. Convert the given
1007             // amount to milliseconds and call setTimeInMillis.
1008             case HOUR:
1009             case HOUR_OF_DAY:
1010                 delta *= 60 * 60 * 1000;        // hours to minutes
1011                 break;
1012 
1013             case MINUTE:
1014                 delta *= 60 * 1000;             // minutes to seconds
1015                 break;
1016 
1017             case SECOND:
1018                 delta *= 1000;                  // seconds to milliseconds
1019                 break;
1020 
1021             case MILLISECOND:
1022                 break;
1023 
1024             // Handle week, day and AM_PM fields which involves
1025             // time zone offset change adjustment. Convert the
1026             // given amount to the number of days.
1027             case WEEK_OF_YEAR:
1028             case WEEK_OF_MONTH:
1029             case DAY_OF_WEEK_IN_MONTH:
1030                 delta *= 7;
1031                 break;
1032 
1033             case DAY_OF_MONTH: // synonym of DATE
1034             case DAY_OF_YEAR:
1035             case DAY_OF_WEEK:
1036                 break;
1037 
1038             case AM_PM:
1039                 // Convert the amount to the number of days (delta)
1040                 // and +12 or -12 hours (timeOfDay).
1041                 delta = amount / 2;
1042                 timeOfDay = 12 * (amount % 2);
1043                 break;
1044             }
1045 
1046             // The time fields don't require time zone offset change
1047             // adjustment.
1048             if (field >= HOUR) {
1049                 setTimeInMillis(time + delta);
1050                 return;
1051             }
1052 
1053             // The rest of the fields (week, day or AM_PM fields)
1054             // require time zone offset (both GMT and DST) change
1055             // adjustment.
1056 
1057             // Translate the current time to the fixed date and time
1058             // of the day.
1059             long fd = getCurrentFixedDate();
1060             timeOfDay += internalGet(HOUR_OF_DAY);
1061             timeOfDay *= 60;
1062             timeOfDay += internalGet(MINUTE);
1063             timeOfDay *= 60;
1064             timeOfDay += internalGet(SECOND);
1065             timeOfDay *= 1000;
1066             timeOfDay += internalGet(MILLISECOND);
1067             if (timeOfDay >= ONE_DAY) {
1068                 fd++;
1069                 timeOfDay -= ONE_DAY;
1070             } else if (timeOfDay < 0) {
1071                 fd--;
1072                 timeOfDay += ONE_DAY;
1073             }
1074 
1075             fd += delta; // fd is the expected fixed date after the calculation
1076             int zoneOffset = internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET);
1077             setTimeInMillis((fd - EPOCH_OFFSET) * ONE_DAY + timeOfDay - zoneOffset);
1078             zoneOffset -= internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET);
1079             // If the time zone offset has changed, then adjust the difference.
1080             if (zoneOffset != 0) {
1081                 setTimeInMillis(time + zoneOffset);
1082                 long fd2 = getCurrentFixedDate();
1083                 // If the adjustment has changed the date, then take
1084                 // the previous one.
1085                 if (fd2 != fd) {
1086                     setTimeInMillis(time - zoneOffset);
1087                 }
1088             }
1089         }
1090     }
1091 
1092     /**
1093      * Adds or subtracts (up/down) a single unit of time on the given time
1094      * field without changing larger fields.
1095      * <p>
1096      * <em>Example</em>: Consider a <code>GregorianCalendar</code>
1097      * originally set to December 31, 1999. Calling {@link #roll(int,boolean) roll(Calendar.MONTH, true)}
1098      * sets the calendar to January 31, 1999.  The <code>YEAR</code> field is unchanged
1099      * because it is a larger field than <code>MONTH</code>.</p>
1100      *
1101      * @param up indicates if the value of the specified calendar field is to be
1102      * rolled up or rolled down. Use <code>true</code> if rolling up, <code>false</code> otherwise.
1103      * @exception IllegalArgumentException if <code>field</code> is
1104      * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
1105      * or if any calendar fields have out-of-range values in
1106      * non-lenient mode.
1107      * @see #add(int,int)
1108      * @see #set(int,int)
1109      */
1110     @Override
1111     public void roll(int field, boolean up) {
1112         roll(field, up ? +1 : -1);
1113     }
1114 
1115     /**
1116      * Adds a signed amount to the specified calendar field without changing larger fields.
1117      * A negative roll amount means to subtract from field without changing
1118      * larger fields. If the specified amount is 0, this method performs nothing.
1119      *
1120      * <p>This method calls {@link #complete()} before adding the
1121      * amount so that all the calendar fields are normalized. If there
1122      * is any calendar field having an out-of-range value in non-lenient mode, then an
1123      * <code>IllegalArgumentException</code> is thrown.
1124      *
1125      * <p>
1126      * <em>Example</em>: Consider a <code>GregorianCalendar</code>
1127      * originally set to August 31, 1999. Calling <code>roll(Calendar.MONTH,
1128      * 8)</code> sets the calendar to April 30, <strong>1999</strong>. Using a
1129      * <code>GregorianCalendar</code>, the <code>DAY_OF_MONTH</code> field cannot
1130      * be 31 in the month April. <code>DAY_OF_MONTH</code> is set to the closest possible
1131      * value, 30. The <code>YEAR</code> field maintains the value of 1999 because it
1132      * is a larger field than <code>MONTH</code>.
1133      * <p>
1134      * <em>Example</em>: Consider a <code>GregorianCalendar</code>
1135      * originally set to Sunday June 6, 1999. Calling
1136      * <code>roll(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
1137      * Tuesday June 1, 1999, whereas calling
1138      * <code>add(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
1139      * Sunday May 30, 1999. This is because the roll rule imposes an
1140      * additional constraint: The <code>MONTH</code> must not change when the
1141      * <code>WEEK_OF_MONTH</code> is rolled. Taken together with add rule 1,
1142      * the resultant date must be between Tuesday June 1 and Saturday June
1143      * 5. According to add rule 2, the <code>DAY_OF_WEEK</code>, an invariant
1144      * when changing the <code>WEEK_OF_MONTH</code>, is set to Tuesday, the
1145      * closest possible value to Sunday (where Sunday is the first day of the
1146      * week).</p>
1147      *
1148      * @param field the calendar field.
1149      * @param amount the signed amount to add to <code>field</code>.
1150      * @exception IllegalArgumentException if <code>field</code> is
1151      * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
1152      * or if any calendar fields have out-of-range values in
1153      * non-lenient mode.
1154      * @see #roll(int,boolean)
1155      * @see #add(int,int)
1156      * @see #set(int,int)
1157      * @since 1.2
1158      */
1159     @Override
1160     public void roll(int field, int amount) {
1161         // If amount == 0, do nothing even the given field is out of
1162         // range. This is tested by JCK.
1163         if (amount == 0) {
1164             return;
1165         }
1166 
1167         if (field < 0 || field >= ZONE_OFFSET) {
1168             throw new IllegalArgumentException();
1169         }
1170 
1171         // Sync the time and calendar fields.
1172         complete();
1173 
1174         int min = getMinimum(field);
1175         int max = getMaximum(field);
1176 
1177         switch (field) {
1178         case AM_PM:
1179         case ERA:
1180         case YEAR:
1181         case MINUTE:
1182         case SECOND:
1183         case MILLISECOND:
1184             // These fields are handled simply, since they have fixed minima
1185             // and maxima.  The field DAY_OF_MONTH is almost as simple.  Other
1186             // fields are complicated, since the range within they must roll
1187             // varies depending on the date.
1188             break;
1189 
1190         case HOUR:
1191         case HOUR_OF_DAY:
1192             {
1193                 int rolledValue = getRolledValue(internalGet(field), amount, min, max);
1194                 int hourOfDay = rolledValue;
1195                 if (field == HOUR && internalGet(AM_PM) == PM) {
1196                     hourOfDay += 12;
1197                 }
1198 
1199                 // Create the current date/time value to perform wall-clock-based
1200                 // roll.
1201                 CalendarDate d = calsys.getCalendarDate(time, getZone());
1202                 d.setHours(hourOfDay);
1203                 time = calsys.getTime(d);
1204 
1205                 // If we stay on the same wall-clock time, try the next or previous hour.
1206                 if (internalGet(HOUR_OF_DAY) == d.getHours()) {
1207                     hourOfDay = getRolledValue(rolledValue, amount > 0 ? +1 : -1, min, max);
1208                     if (field == HOUR && internalGet(AM_PM) == PM) {
1209                         hourOfDay += 12;
1210                     }
1211                     d.setHours(hourOfDay);
1212                     time = calsys.getTime(d);
1213                 }
1214                 // Get the new hourOfDay value which might have changed due to a DST transition.
1215                 hourOfDay = d.getHours();
1216                 // Update the hour related fields
1217                 internalSet(HOUR_OF_DAY, hourOfDay);
1218                 internalSet(AM_PM, hourOfDay / 12);
1219                 internalSet(HOUR, hourOfDay % 12);
1220 
1221                 // Time zone offset and/or daylight saving might have changed.
1222                 int zoneOffset = d.getZoneOffset();
1223                 int saving = d.getDaylightSaving();
1224                 internalSet(ZONE_OFFSET, zoneOffset - saving);
1225                 internalSet(DST_OFFSET, saving);
1226                 return;
1227             }
1228 
1229         case MONTH:
1230             // Rolling the month involves both pinning the final value to [0, 11]
1231             // and adjusting the DAY_OF_MONTH if necessary.  We only adjust the
1232             // DAY_OF_MONTH if, after updating the MONTH field, it is illegal.
1233             // E.g., <jan31>.roll(MONTH, 1) -> <feb28> or <feb29>.
1234             {
1235                 if (!isCutoverYear(cdate.getNormalizedYear())) {
1236                     int mon = (internalGet(MONTH) + amount) % 12;
1237                     if (mon < 0) {
1238                         mon += 12;
1239                     }
1240                     set(MONTH, mon);
1241 
1242                     // Keep the day of month in the range.  We don't want to spill over
1243                     // into the next month; e.g., we don't want jan31 + 1 mo -> feb31 ->
1244                     // mar3.
1245                     int monthLen = monthLength(mon);
1246                     if (internalGet(DAY_OF_MONTH) > monthLen) {
1247                         set(DAY_OF_MONTH, monthLen);
1248                     }
1249                 } else {
1250                     // We need to take care of different lengths in
1251                     // year and month due to the cutover.
1252                     int yearLength = getActualMaximum(MONTH) + 1;
1253                     int mon = (internalGet(MONTH) + amount) % yearLength;
1254                     if (mon < 0) {
1255                         mon += yearLength;
1256                     }
1257                     set(MONTH, mon);
1258                     int monthLen = getActualMaximum(DAY_OF_MONTH);
1259                     if (internalGet(DAY_OF_MONTH) > monthLen) {
1260                         set(DAY_OF_MONTH, monthLen);
1261                     }
1262                 }
1263                 return;
1264             }
1265 
1266         case WEEK_OF_YEAR:
1267             {
1268                 int y = cdate.getNormalizedYear();
1269                 max = getActualMaximum(WEEK_OF_YEAR);
1270                 set(DAY_OF_WEEK, internalGet(DAY_OF_WEEK));
1271                 int woy = internalGet(WEEK_OF_YEAR);
1272                 int value = woy + amount;
1273                 if (!isCutoverYear(y)) {
1274                     int weekYear = getWeekYear();
1275                     if (weekYear == y) {
1276                         // If the new value is in between min and max
1277                         // (exclusive), then we can use the value.
1278                         if (value > min && value < max) {
1279                             set(WEEK_OF_YEAR, value);
1280                             return;
1281                         }
1282                         long fd = getCurrentFixedDate();
1283                         // Make sure that the min week has the current DAY_OF_WEEK
1284                         // in the calendar year
1285                         long day1 = fd - (7 * (woy - min));
1286                         if (calsys.getYearFromFixedDate(day1) != y) {
1287                             min++;
1288                         }
1289 
1290                         // Make sure the same thing for the max week
1291                         fd += 7 * (max - internalGet(WEEK_OF_YEAR));
1292                         if (calsys.getYearFromFixedDate(fd) != y) {
1293                             max--;
1294                         }
1295                     } else {
1296                         // When WEEK_OF_YEAR and YEAR are out of sync,
1297                         // adjust woy and amount to stay in the calendar year.
1298                         if (weekYear > y) {
1299                             if (amount < 0) {
1300                                 amount++;
1301                             }
1302                             woy = max;
1303                         } else {
1304                             if (amount > 0) {
1305                                 amount -= woy - max;
1306                             }
1307                             woy = min;
1308                         }
1309                     }
1310                     set(field, getRolledValue(woy, amount, min, max));
1311                     return;
1312                 }
1313 
1314                 // Handle cutover here.
1315                 long fd = getCurrentFixedDate();
1316                 BaseCalendar cal;
1317                 if (gregorianCutoverYear == gregorianCutoverYearJulian) {
1318                     cal = getCutoverCalendarSystem();
1319                 } else if (y == gregorianCutoverYear) {
1320                     cal = gcal;
1321                 } else {
1322                     cal = getJulianCalendarSystem();
1323                 }
1324                 long day1 = fd - (7 * (woy - min));
1325                 // Make sure that the min week has the current DAY_OF_WEEK
1326                 if (cal.getYearFromFixedDate(day1) != y) {
1327                     min++;
1328                 }
1329 
1330                 // Make sure the same thing for the max week
1331                 fd += 7 * (max - woy);
1332                 cal = (fd >= gregorianCutoverDate) ? gcal : getJulianCalendarSystem();
1333                 if (cal.getYearFromFixedDate(fd) != y) {
1334                     max--;
1335                 }
1336                 // value: the new WEEK_OF_YEAR which must be converted
1337                 // to month and day of month.
1338                 value = getRolledValue(woy, amount, min, max) - 1;
1339                 BaseCalendar.Date d = getCalendarDate(day1 + value * 7);
1340                 set(MONTH, d.getMonth() - 1);
1341                 set(DAY_OF_MONTH, d.getDayOfMonth());
1342                 return;
1343             }
1344 
1345         case WEEK_OF_MONTH:
1346             {
1347                 boolean isCutoverYear = isCutoverYear(cdate.getNormalizedYear());
1348                 // dow: relative day of week from first day of week
1349                 int dow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek();
1350                 if (dow < 0) {
1351                     dow += 7;
1352                 }
1353 
1354                 long fd = getCurrentFixedDate();
1355                 long month1;     // fixed date of the first day (usually 1) of the month
1356                 int monthLength; // actual month length
1357                 if (isCutoverYear) {
1358                     month1 = getFixedDateMonth1(cdate, fd);
1359                     monthLength = actualMonthLength();
1360                 } else {
1361                     month1 = fd - internalGet(DAY_OF_MONTH) + 1;
1362                     monthLength = calsys.getMonthLength(cdate);
1363                 }
1364 
1365                 // the first day of week of the month.
1366                 long monthDay1st = BaseCalendar.getDayOfWeekDateOnOrBefore(month1 + 6,
1367                                                                            getFirstDayOfWeek());
1368                 // if the week has enough days to form a week, the
1369                 // week starts from the previous month.
1370                 if ((int)(monthDay1st - month1) >= getMinimalDaysInFirstWeek()) {
1371                     monthDay1st -= 7;
1372                 }
1373                 max = getActualMaximum(field);
1374 
1375                 // value: the new WEEK_OF_MONTH value
1376                 int value = getRolledValue(internalGet(field), amount, 1, max) - 1;
1377 
1378                 // nfd: fixed date of the rolled date
1379                 long nfd = monthDay1st + value * 7 + dow;
1380 
1381                 // Unlike WEEK_OF_YEAR, we need to change day of week if the
1382                 // nfd is out of the month.
1383                 if (nfd < month1) {
1384                     nfd = month1;
1385                 } else if (nfd >= (month1 + monthLength)) {
1386                     nfd = month1 + monthLength - 1;
1387                 }
1388                 int dayOfMonth;
1389                 if (isCutoverYear) {
1390                     // If we are in the cutover year, convert nfd to
1391                     // its calendar date and use dayOfMonth.
1392                     BaseCalendar.Date d = getCalendarDate(nfd);
1393                     dayOfMonth = d.getDayOfMonth();
1394                 } else {
1395                     dayOfMonth = (int)(nfd - month1) + 1;
1396                 }
1397                 set(DAY_OF_MONTH, dayOfMonth);
1398                 return;
1399             }
1400 
1401         case DAY_OF_MONTH:
1402             {
1403                 if (!isCutoverYear(cdate.getNormalizedYear())) {
1404                     max = calsys.getMonthLength(cdate);
1405                     break;
1406                 }
1407 
1408                 // Cutover year handling
1409                 long fd = getCurrentFixedDate();
1410                 long month1 = getFixedDateMonth1(cdate, fd);
1411                 // It may not be a regular month. Convert the date and range to
1412                 // the relative values, perform the roll, and
1413                 // convert the result back to the rolled date.
1414                 int value = getRolledValue((int)(fd - month1), amount, 0, actualMonthLength() - 1);
1415                 BaseCalendar.Date d = getCalendarDate(month1 + value);
1416                 assert d.getMonth()-1 == internalGet(MONTH);
1417                 set(DAY_OF_MONTH, d.getDayOfMonth());
1418                 return;
1419             }
1420 
1421         case DAY_OF_YEAR:
1422             {
1423                 max = getActualMaximum(field);
1424                 if (!isCutoverYear(cdate.getNormalizedYear())) {
1425                     break;
1426                 }
1427 
1428                 // Handle cutover here.
1429                 long fd = getCurrentFixedDate();
1430                 long jan1 = fd - internalGet(DAY_OF_YEAR) + 1;
1431                 int value = getRolledValue((int)(fd - jan1) + 1, amount, min, max);
1432                 BaseCalendar.Date d = getCalendarDate(jan1 + value - 1);
1433                 set(MONTH, d.getMonth() - 1);
1434                 set(DAY_OF_MONTH, d.getDayOfMonth());
1435                 return;
1436             }
1437 
1438         case DAY_OF_WEEK:
1439             {
1440                 if (!isCutoverYear(cdate.getNormalizedYear())) {
1441                     // If the week of year is in the same year, we can
1442                     // just change DAY_OF_WEEK.
1443                     int weekOfYear = internalGet(WEEK_OF_YEAR);
1444                     if (weekOfYear > 1 && weekOfYear < 52) {
1445                         set(WEEK_OF_YEAR, weekOfYear); // update stamp[WEEK_OF_YEAR]
1446                         max = SATURDAY;
1447                         break;
1448                     }
1449                 }
1450 
1451                 // We need to handle it in a different way around year
1452                 // boundaries and in the cutover year. Note that
1453                 // changing era and year values violates the roll
1454                 // rule: not changing larger calendar fields...
1455                 amount %= 7;
1456                 if (amount == 0) {
1457                     return;
1458                 }
1459                 long fd = getCurrentFixedDate();
1460                 long dowFirst = BaseCalendar.getDayOfWeekDateOnOrBefore(fd, getFirstDayOfWeek());
1461                 fd += amount;
1462                 if (fd < dowFirst) {
1463                     fd += 7;
1464                 } else if (fd >= dowFirst + 7) {
1465                     fd -= 7;
1466                 }
1467                 BaseCalendar.Date d = getCalendarDate(fd);
1468                 set(ERA, (d.getNormalizedYear() <= 0 ? BCE : CE));
1469                 set(d.getYear(), d.getMonth() - 1, d.getDayOfMonth());
1470                 return;
1471             }
1472 
1473         case DAY_OF_WEEK_IN_MONTH:
1474             {
1475                 min = 1; // after normalized, min should be 1.
1476                 if (!isCutoverYear(cdate.getNormalizedYear())) {
1477                     int dom = internalGet(DAY_OF_MONTH);
1478                     int monthLength = calsys.getMonthLength(cdate);
1479                     int lastDays = monthLength % 7;
1480                     max = monthLength / 7;
1481                     int x = (dom - 1) % 7;
1482                     if (x < lastDays) {
1483                         max++;
1484                     }
1485                     set(DAY_OF_WEEK, internalGet(DAY_OF_WEEK));
1486                     break;
1487                 }
1488 
1489                 // Cutover year handling
1490                 long fd = getCurrentFixedDate();
1491                 long month1 = getFixedDateMonth1(cdate, fd);
1492                 int monthLength = actualMonthLength();
1493                 int lastDays = monthLength % 7;
1494                 max = monthLength / 7;
1495                 int x = (int)(fd - month1) % 7;
1496                 if (x < lastDays) {
1497                     max++;
1498                 }
1499                 int value = getRolledValue(internalGet(field), amount, min, max) - 1;
1500                 fd = month1 + value * 7 + x;
1501                 BaseCalendar cal = (fd >= gregorianCutoverDate) ? gcal : getJulianCalendarSystem();
1502                 BaseCalendar.Date d = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.NO_TIMEZONE);
1503                 cal.getCalendarDateFromFixedDate(d, fd);
1504                 set(DAY_OF_MONTH, d.getDayOfMonth());
1505                 return;
1506             }
1507         }
1508 
1509         set(field, getRolledValue(internalGet(field), amount, min, max));
1510     }
1511 
1512     /**
1513      * Returns the minimum value for the given calendar field of this
1514      * <code>GregorianCalendar</code> instance. The minimum value is
1515      * defined as the smallest value returned by the {@link
1516      * Calendar#get(int) get} method for any possible time value,
1517      * taking into consideration the current values of the
1518      * {@link Calendar#getFirstDayOfWeek() getFirstDayOfWeek},
1519      * {@link Calendar#getMinimalDaysInFirstWeek() getMinimalDaysInFirstWeek},
1520      * {@link #getGregorianChange() getGregorianChange} and
1521      * {@link Calendar#getTimeZone() getTimeZone} methods.
1522      *
1523      * @param field the calendar field.
1524      * @return the minimum value for the given calendar field.
1525      * @see #getMaximum(int)
1526      * @see #getGreatestMinimum(int)
1527      * @see #getLeastMaximum(int)
1528      * @see #getActualMinimum(int)
1529      * @see #getActualMaximum(int)
1530      */
1531     @Override
1532     public int getMinimum(int field) {
1533         return MIN_VALUES[field];
1534     }
1535 
1536     /**
1537      * Returns the maximum value for the given calendar field of this
1538      * <code>GregorianCalendar</code> instance. The maximum value is
1539      * defined as the largest value returned by the {@link
1540      * Calendar#get(int) get} method for any possible time value,
1541      * taking into consideration the current values of the
1542      * {@link Calendar#getFirstDayOfWeek() getFirstDayOfWeek},
1543      * {@link Calendar#getMinimalDaysInFirstWeek() getMinimalDaysInFirstWeek},
1544      * {@link #getGregorianChange() getGregorianChange} and
1545      * {@link Calendar#getTimeZone() getTimeZone} methods.
1546      *
1547      * @param field the calendar field.
1548      * @return the maximum value for the given calendar field.
1549      * @see #getMinimum(int)
1550      * @see #getGreatestMinimum(int)
1551      * @see #getLeastMaximum(int)
1552      * @see #getActualMinimum(int)
1553      * @see #getActualMaximum(int)
1554      */
1555     @Override
1556     public int getMaximum(int field) {
1557         switch (field) {
1558         case MONTH:
1559         case DAY_OF_MONTH:
1560         case DAY_OF_YEAR:
1561         case WEEK_OF_YEAR:
1562         case WEEK_OF_MONTH:
1563         case DAY_OF_WEEK_IN_MONTH:
1564         case YEAR:
1565             {
1566                 // On or after Gregorian 200-3-1, Julian and Gregorian
1567                 // calendar dates are the same or Gregorian dates are
1568                 // larger (i.e., there is a "gap") after 300-3-1.
1569                 if (gregorianCutoverYear > 200) {
1570                     break;
1571                 }
1572                 // There might be "overlapping" dates.
1573                 GregorianCalendar gc = (GregorianCalendar) clone();
1574                 gc.setLenient(true);
1575                 gc.setTimeInMillis(gregorianCutover);
1576                 int v1 = gc.getActualMaximum(field);
1577                 gc.setTimeInMillis(gregorianCutover-1);
1578                 int v2 = gc.getActualMaximum(field);
1579                 return Math.max(MAX_VALUES[field], Math.max(v1, v2));
1580             }
1581         }
1582         return MAX_VALUES[field];
1583     }
1584 
1585     /**
1586      * Returns the highest minimum value for the given calendar field
1587      * of this <code>GregorianCalendar</code> instance. The highest
1588      * minimum value is defined as the largest value returned by
1589      * {@link #getActualMinimum(int)} for any possible time value,
1590      * taking into consideration the current values of the
1591      * {@link Calendar#getFirstDayOfWeek() getFirstDayOfWeek},
1592      * {@link Calendar#getMinimalDaysInFirstWeek() getMinimalDaysInFirstWeek},
1593      * {@link #getGregorianChange() getGregorianChange} and
1594      * {@link Calendar#getTimeZone() getTimeZone} methods.
1595      *
1596      * @param field the calendar field.
1597      * @return the highest minimum value for the given calendar field.
1598      * @see #getMinimum(int)
1599      * @see #getMaximum(int)
1600      * @see #getLeastMaximum(int)
1601      * @see #getActualMinimum(int)
1602      * @see #getActualMaximum(int)
1603      */
1604     @Override
1605     public int getGreatestMinimum(int field) {
1606         if (field == DAY_OF_MONTH) {
1607             BaseCalendar.Date d = getGregorianCutoverDate();
1608             long mon1 = getFixedDateMonth1(d, gregorianCutoverDate);
1609             d = getCalendarDate(mon1);
1610             return Math.max(MIN_VALUES[field], d.getDayOfMonth());
1611         }
1612         return MIN_VALUES[field];
1613     }
1614 
1615     /**
1616      * Returns the lowest maximum value for the given calendar field
1617      * of this <code>GregorianCalendar</code> instance. The lowest
1618      * maximum value is defined as the smallest value returned by
1619      * {@link #getActualMaximum(int)} for any possible time value,
1620      * taking into consideration the current values of the
1621      * {@link Calendar#getFirstDayOfWeek() getFirstDayOfWeek},
1622      * {@link Calendar#getMinimalDaysInFirstWeek() getMinimalDaysInFirstWeek},
1623      * {@link #getGregorianChange() getGregorianChange} and
1624      * {@link Calendar#getTimeZone() getTimeZone} methods.
1625      *
1626      * @param field the calendar field
1627      * @return the lowest maximum value for the given calendar field.
1628      * @see #getMinimum(int)
1629      * @see #getMaximum(int)
1630      * @see #getGreatestMinimum(int)
1631      * @see #getActualMinimum(int)
1632      * @see #getActualMaximum(int)
1633      */
1634     @Override
1635     public int getLeastMaximum(int field) {
1636         switch (field) {
1637         case MONTH:
1638         case DAY_OF_MONTH:
1639         case DAY_OF_YEAR:
1640         case WEEK_OF_YEAR:
1641         case WEEK_OF_MONTH:
1642         case DAY_OF_WEEK_IN_MONTH:
1643         case YEAR:
1644             {
1645                 GregorianCalendar gc = (GregorianCalendar) clone();
1646                 gc.setLenient(true);
1647                 gc.setTimeInMillis(gregorianCutover);
1648                 int v1 = gc.getActualMaximum(field);
1649                 gc.setTimeInMillis(gregorianCutover-1);
1650                 int v2 = gc.getActualMaximum(field);
1651                 return Math.min(LEAST_MAX_VALUES[field], Math.min(v1, v2));
1652             }
1653         }
1654         return LEAST_MAX_VALUES[field];
1655     }
1656 
1657     /**
1658      * Returns the minimum value that this calendar field could have,
1659      * taking into consideration the given time value and the current
1660      * values of the
1661      * {@link Calendar#getFirstDayOfWeek() getFirstDayOfWeek},
1662      * {@link Calendar#getMinimalDaysInFirstWeek() getMinimalDaysInFirstWeek},
1663      * {@link #getGregorianChange() getGregorianChange} and
1664      * {@link Calendar#getTimeZone() getTimeZone} methods.
1665      *
1666      * <p>For example, if the Gregorian change date is January 10,
1667      * 1970 and the date of this <code>GregorianCalendar</code> is
1668      * January 20, 1970, the actual minimum value of the
1669      * <code>DAY_OF_MONTH</code> field is 10 because the previous date
1670      * of January 10, 1970 is December 27, 1996 (in the Julian
1671      * calendar). Therefore, December 28, 1969 to January 9, 1970
1672      * don't exist.
1673      *
1674      * @param field the calendar field
1675      * @return the minimum of the given field for the time value of
1676      * this <code>GregorianCalendar</code>
1677      * @see #getMinimum(int)
1678      * @see #getMaximum(int)
1679      * @see #getGreatestMinimum(int)
1680      * @see #getLeastMaximum(int)
1681      * @see #getActualMaximum(int)
1682      * @since 1.2
1683      */
1684     @Override
1685     public int getActualMinimum(int field) {
1686         if (field == DAY_OF_MONTH) {
1687             GregorianCalendar gc = getNormalizedCalendar();
1688             int year = gc.cdate.getNormalizedYear();
1689             if (year == gregorianCutoverYear || year == gregorianCutoverYearJulian) {
1690                 long month1 = getFixedDateMonth1(gc.cdate, gc.calsys.getFixedDate(gc.cdate));
1691                 BaseCalendar.Date d = getCalendarDate(month1);
1692                 return d.getDayOfMonth();
1693             }
1694         }
1695         return getMinimum(field);
1696     }
1697 
1698     /**
1699      * Returns the maximum value that this calendar field could have,
1700      * taking into consideration the given time value and the current
1701      * values of the
1702      * {@link Calendar#getFirstDayOfWeek() getFirstDayOfWeek},
1703      * {@link Calendar#getMinimalDaysInFirstWeek() getMinimalDaysInFirstWeek},
1704      * {@link #getGregorianChange() getGregorianChange} and
1705      * {@link Calendar#getTimeZone() getTimeZone} methods.
1706      * For example, if the date of this instance is February 1, 2004,
1707      * the actual maximum value of the <code>DAY_OF_MONTH</code> field
1708      * is 29 because 2004 is a leap year, and if the date of this
1709      * instance is February 1, 2005, it's 28.
1710      *
1711      * <p>This method calculates the maximum value of {@link
1712      * Calendar#WEEK_OF_YEAR WEEK_OF_YEAR} based on the {@link
1713      * Calendar#YEAR YEAR} (calendar year) value, not the <a
1714      * href="#week_year">week year</a>. Call {@link
1715      * #getWeeksInWeekYear()} to get the maximum value of {@code
1716      * WEEK_OF_YEAR} in the week year of this {@code GregorianCalendar}.
1717      *
1718      * @param field the calendar field
1719      * @return the maximum of the given field for the time value of
1720      * this <code>GregorianCalendar</code>
1721      * @see #getMinimum(int)
1722      * @see #getMaximum(int)
1723      * @see #getGreatestMinimum(int)
1724      * @see #getLeastMaximum(int)
1725      * @see #getActualMinimum(int)
1726      * @since 1.2
1727      */
1728     @Override
1729     public int getActualMaximum(int field) {
1730         final int fieldsForFixedMax = ERA_MASK|DAY_OF_WEEK_MASK|HOUR_MASK|AM_PM_MASK|
1731             HOUR_OF_DAY_MASK|MINUTE_MASK|SECOND_MASK|MILLISECOND_MASK|
1732             ZONE_OFFSET_MASK|DST_OFFSET_MASK;
1733         if ((fieldsForFixedMax & (1<<field)) != 0) {
1734             return getMaximum(field);
1735         }
1736 
1737         GregorianCalendar gc = getNormalizedCalendar();
1738         BaseCalendar.Date date = gc.cdate;
1739         BaseCalendar cal = gc.calsys;
1740         int normalizedYear = date.getNormalizedYear();
1741 
1742         int value = -1;
1743         switch (field) {
1744         case MONTH:
1745             {
1746                 if (!gc.isCutoverYear(normalizedYear)) {
1747                     value = DECEMBER;
1748                     break;
1749                 }
1750 
1751                 // January 1 of the next year may or may not exist.
1752                 long nextJan1;
1753                 do {
1754                     nextJan1 = gcal.getFixedDate(++normalizedYear, BaseCalendar.JANUARY, 1, null);
1755                 } while (nextJan1 < gregorianCutoverDate);
1756                 BaseCalendar.Date d = (BaseCalendar.Date) date.clone();
1757                 cal.getCalendarDateFromFixedDate(d, nextJan1 - 1);
1758                 value = d.getMonth() - 1;
1759             }
1760             break;
1761 
1762         case DAY_OF_MONTH:
1763             {
1764                 value = cal.getMonthLength(date);
1765                 if (!gc.isCutoverYear(normalizedYear) || date.getDayOfMonth() == value) {
1766                     break;
1767                 }
1768 
1769                 // Handle cutover year.
1770                 long fd = gc.getCurrentFixedDate();
1771                 if (fd >= gregorianCutoverDate) {
1772                     break;
1773                 }
1774                 int monthLength = gc.actualMonthLength();
1775                 long monthEnd = gc.getFixedDateMonth1(gc.cdate, fd) + monthLength - 1;
1776                 // Convert the fixed date to its calendar date.
1777                 BaseCalendar.Date d = gc.getCalendarDate(monthEnd);
1778                 value = d.getDayOfMonth();
1779             }
1780             break;
1781 
1782         case DAY_OF_YEAR:
1783             {
1784                 if (!gc.isCutoverYear(normalizedYear)) {
1785                     value = cal.getYearLength(date);
1786                     break;
1787                 }
1788 
1789                 // Handle cutover year.
1790                 long jan1;
1791                 if (gregorianCutoverYear == gregorianCutoverYearJulian) {
1792                     BaseCalendar cocal = gc.getCutoverCalendarSystem();
1793                     jan1 = cocal.getFixedDate(normalizedYear, 1, 1, null);
1794                 } else if (normalizedYear == gregorianCutoverYearJulian) {
1795                     jan1 = cal.getFixedDate(normalizedYear, 1, 1, null);
1796                 } else {
1797                     jan1 = gregorianCutoverDate;
1798                 }
1799                 // January 1 of the next year may or may not exist.
1800                 long nextJan1 = gcal.getFixedDate(++normalizedYear, 1, 1, null);
1801                 if (nextJan1 < gregorianCutoverDate) {
1802                     nextJan1 = gregorianCutoverDate;
1803                 }
1804                 assert jan1 <= cal.getFixedDate(date.getNormalizedYear(), date.getMonth(),
1805                                                 date.getDayOfMonth(), date);
1806                 assert nextJan1 >= cal.getFixedDate(date.getNormalizedYear(), date.getMonth(),
1807                                                 date.getDayOfMonth(), date);
1808                 value = (int)(nextJan1 - jan1);
1809             }
1810             break;
1811 
1812         case WEEK_OF_YEAR:
1813             {
1814                 if (!gc.isCutoverYear(normalizedYear)) {
1815                     // Get the day of week of January 1 of the year
1816                     CalendarDate d = cal.newCalendarDate(TimeZone.NO_TIMEZONE);
1817                     d.setDate(date.getYear(), BaseCalendar.JANUARY, 1);
1818                     int dayOfWeek = cal.getDayOfWeek(d);
1819                     // Normalize the day of week with the firstDayOfWeek value
1820                     dayOfWeek -= getFirstDayOfWeek();
1821                     if (dayOfWeek < 0) {
1822                         dayOfWeek += 7;
1823                     }
1824                     value = 52;
1825                     int magic = dayOfWeek + getMinimalDaysInFirstWeek() - 1;
1826                     if ((magic == 6) ||
1827                         (date.isLeapYear() && (magic == 5 || magic == 12))) {
1828                         value++;
1829                     }
1830                     break;
1831                 }
1832 
1833                 if (gc == this) {
1834                     gc = (GregorianCalendar) gc.clone();
1835                 }
1836                 int maxDayOfYear = getActualMaximum(DAY_OF_YEAR);
1837                 gc.set(DAY_OF_YEAR, maxDayOfYear);
1838                 value = gc.get(WEEK_OF_YEAR);
1839                 if (internalGet(YEAR) != gc.getWeekYear()) {
1840                     gc.set(DAY_OF_YEAR, maxDayOfYear - 7);
1841                     value = gc.get(WEEK_OF_YEAR);
1842                 }
1843             }
1844             break;
1845 
1846         case WEEK_OF_MONTH:
1847             {
1848                 if (!gc.isCutoverYear(normalizedYear)) {
1849                     CalendarDate d = cal.newCalendarDate(null);
1850                     d.setDate(date.getYear(), date.getMonth(), 1);
1851                     int dayOfWeek = cal.getDayOfWeek(d);
1852                     int monthLength = cal.getMonthLength(d);
1853                     dayOfWeek -= getFirstDayOfWeek();
1854                     if (dayOfWeek < 0) {
1855                         dayOfWeek += 7;
1856                     }
1857                     int nDaysFirstWeek = 7 - dayOfWeek; // # of days in the first week
1858                     value = 3;
1859                     if (nDaysFirstWeek >= getMinimalDaysInFirstWeek()) {
1860                         value++;
1861                     }
1862                     monthLength -= nDaysFirstWeek + 7 * 3;
1863                     if (monthLength > 0) {
1864                         value++;
1865                         if (monthLength > 7) {
1866                             value++;
1867                         }
1868                     }
1869                     break;
1870                 }
1871 
1872                 // Cutover year handling
1873                 if (gc == this) {
1874                     gc = (GregorianCalendar) gc.clone();
1875                 }
1876                 int y = gc.internalGet(YEAR);
1877                 int m = gc.internalGet(MONTH);
1878                 do {
1879                     value = gc.get(WEEK_OF_MONTH);
1880                     gc.add(WEEK_OF_MONTH, +1);
1881                 } while (gc.get(YEAR) == y && gc.get(MONTH) == m);
1882             }
1883             break;
1884 
1885         case DAY_OF_WEEK_IN_MONTH:
1886             {
1887                 // may be in the Gregorian cutover month
1888                 int ndays, dow1;
1889                 int dow = date.getDayOfWeek();
1890                 if (!gc.isCutoverYear(normalizedYear)) {
1891                     BaseCalendar.Date d = (BaseCalendar.Date) date.clone();
1892                     ndays = cal.getMonthLength(d);
1893                     d.setDayOfMonth(1);
1894                     cal.normalize(d);
1895                     dow1 = d.getDayOfWeek();
1896                 } else {
1897                     // Let a cloned GregorianCalendar take care of the cutover cases.
1898                     if (gc == this) {
1899                         gc = (GregorianCalendar) clone();
1900                     }
1901                     ndays = gc.actualMonthLength();
1902                     gc.set(DAY_OF_MONTH, gc.getActualMinimum(DAY_OF_MONTH));
1903                     dow1 = gc.get(DAY_OF_WEEK);
1904                 }
1905                 int x = dow - dow1;
1906                 if (x < 0) {
1907                     x += 7;
1908                 }
1909                 ndays -= x;
1910                 value = (ndays + 6) / 7;
1911             }
1912             break;
1913 
1914         case YEAR:
1915             /* The year computation is no different, in principle, from the
1916              * others, however, the range of possible maxima is large.  In
1917              * addition, the way we know we've exceeded the range is different.
1918              * For these reasons, we use the special case code below to handle
1919              * this field.
1920              *
1921              * The actual maxima for YEAR depend on the type of calendar:
1922              *
1923              *     Gregorian = May 17, 292275056 BCE - Aug 17, 292278994 CE
1924              *     Julian    = Dec  2, 292269055 BCE - Jan  3, 292272993 CE
1925              *     Hybrid    = Dec  2, 292269055 BCE - Aug 17, 292278994 CE
1926              *
1927              * We know we've exceeded the maximum when either the month, date,
1928              * time, or era changes in response to setting the year.  We don't
1929              * check for month, date, and time here because the year and era are
1930              * sufficient to detect an invalid year setting.  NOTE: If code is
1931              * added to check the month and date in the future for some reason,
1932              * Feb 29 must be allowed to shift to Mar 1 when setting the year.
1933              */
1934             {
1935                 if (gc == this) {
1936                     gc = (GregorianCalendar) clone();
1937                 }
1938 
1939                 // Calculate the millisecond offset from the beginning
1940                 // of the year of this calendar and adjust the max
1941                 // year value if we are beyond the limit in the max
1942                 // year.
1943                 long current = gc.getYearOffsetInMillis();
1944 
1945                 if (gc.internalGetEra() == CE) {
1946                     gc.setTimeInMillis(Long.MAX_VALUE);
1947                     value = gc.get(YEAR);
1948                     long maxEnd = gc.getYearOffsetInMillis();
1949                     if (current > maxEnd) {
1950                         value--;
1951                     }
1952                 } else {
1953                     CalendarSystem mincal = gc.getTimeInMillis() >= gregorianCutover ?
1954                         gcal : getJulianCalendarSystem();
1955                     CalendarDate d = mincal.getCalendarDate(Long.MIN_VALUE, getZone());
1956                     long maxEnd = (cal.getDayOfYear(d) - 1) * 24 + d.getHours();
1957                     maxEnd *= 60;
1958                     maxEnd += d.getMinutes();
1959                     maxEnd *= 60;
1960                     maxEnd += d.getSeconds();
1961                     maxEnd *= 1000;
1962                     maxEnd += d.getMillis();
1963                     value = d.getYear();
1964                     if (value <= 0) {
1965                         assert mincal == gcal;
1966                         value = 1 - value;
1967                     }
1968                     if (current < maxEnd) {
1969                         value--;
1970                     }
1971                 }
1972             }
1973             break;
1974 
1975         default:
1976             throw new ArrayIndexOutOfBoundsException(field);
1977         }
1978         return value;
1979     }
1980 
1981     /**
1982      * Returns the millisecond offset from the beginning of this
1983      * year. This Calendar object must have been normalized.
1984      */
1985     private long getYearOffsetInMillis() {
1986         long t = (internalGet(DAY_OF_YEAR) - 1) * 24;
1987         t += internalGet(HOUR_OF_DAY);
1988         t *= 60;
1989         t += internalGet(MINUTE);
1990         t *= 60;
1991         t += internalGet(SECOND);
1992         t *= 1000;
1993         return t + internalGet(MILLISECOND) -
1994             (internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET));
1995     }
1996 
1997     @Override
1998     public Object clone()
1999     {
2000         GregorianCalendar other = (GregorianCalendar) super.clone();
2001 
2002         other.gdate = (BaseCalendar.Date) gdate.clone();
2003         if (cdate != null) {
2004             if (cdate != gdate) {
2005                 other.cdate = (BaseCalendar.Date) cdate.clone();
2006             } else {
2007                 other.cdate = other.gdate;
2008             }
2009         }
2010         other.originalFields = null;
2011         other.zoneOffsets = null;
2012         return other;
2013     }
2014 
2015     @Override
2016     public TimeZone getTimeZone() {
2017         TimeZone zone = super.getTimeZone();
2018         // To share the zone by CalendarDates
2019         gdate.setZone(zone);
2020         if (cdate != null && cdate != gdate) {
2021             cdate.setZone(zone);
2022         }
2023         return zone;
2024     }
2025 
2026     @Override
2027     public void setTimeZone(TimeZone zone) {
2028         super.setTimeZone(zone);
2029         // To share the zone by CalendarDates
2030         gdate.setZone(zone);
2031         if (cdate != null && cdate != gdate) {
2032             cdate.setZone(zone);
2033         }
2034     }
2035 
2036     /**
2037      * Returns {@code true} indicating this {@code GregorianCalendar}
2038      * supports week dates.
2039      *
2040      * @return {@code true} (always)
2041      * @see #getWeekYear()
2042      * @see #setWeekDate(int,int,int)
2043      * @see #getWeeksInWeekYear()
2044      * @since 1.7
2045      */
2046     @Override
2047     public final boolean isWeekDateSupported() {
2048         return true;
2049     }
2050 
2051     /**
2052      * Returns the <a href="#week_year">week year</a> represented by this
2053      * {@code GregorianCalendar}. The dates in the weeks between 1 and the
2054      * maximum week number of the week year have the same week year value
2055      * that may be one year before or after the {@link Calendar#YEAR YEAR}
2056      * (calendar year) value.
2057      *
2058      * <p>This method calls {@link Calendar#complete()} before
2059      * calculating the week year.
2060      *
2061      * @return the week year represented by this {@code GregorianCalendar}.
2062      *         If the {@link Calendar#ERA ERA} value is {@link #BC}, the year is
2063      *         represented by 0 or a negative number: BC 1 is 0, BC 2
2064      *         is -1, BC 3 is -2, and so on.
2065      * @throws IllegalArgumentException
2066      *         if any of the calendar fields is invalid in non-lenient mode.
2067      * @see #isWeekDateSupported()
2068      * @see #getWeeksInWeekYear()
2069      * @see Calendar#getFirstDayOfWeek()
2070      * @see Calendar#getMinimalDaysInFirstWeek()
2071      * @since 1.7
2072      */
2073     @Override
2074     public int getWeekYear() {
2075         int year = get(YEAR); // implicitly calls complete()
2076         if (internalGetEra() == BCE) {
2077             year = 1 - year;
2078         }
2079 
2080         // Fast path for the Gregorian calendar years that are never
2081         // affected by the Julian-Gregorian transition
2082         if (year > gregorianCutoverYear + 1) {
2083             int weekOfYear = internalGet(WEEK_OF_YEAR);
2084             if (internalGet(MONTH) == JANUARY) {
2085                 if (weekOfYear >= 52) {
2086                     --year;
2087                 }
2088             } else {
2089                 if (weekOfYear == 1) {
2090                     ++year;
2091                 }
2092             }
2093             return year;
2094         }
2095 
2096         // General (slow) path
2097         int dayOfYear = internalGet(DAY_OF_YEAR);
2098         int maxDayOfYear = getActualMaximum(DAY_OF_YEAR);
2099         int minimalDays = getMinimalDaysInFirstWeek();
2100 
2101         // Quickly check the possibility of year adjustments before
2102         // cloning this GregorianCalendar.
2103         if (dayOfYear > minimalDays && dayOfYear < (maxDayOfYear - 6)) {
2104             return year;
2105         }
2106 
2107         // Create a clone to work on the calculation
2108         GregorianCalendar cal = (GregorianCalendar) clone();
2109         cal.setLenient(true);
2110         // Use GMT so that intermediate date calculations won't
2111         // affect the time of day fields.
2112         cal.setTimeZone(TimeZone.getTimeZone("GMT"));
2113         // Go to the first day of the year, which is usually January 1.
2114         cal.set(DAY_OF_YEAR, 1);
2115         cal.complete();
2116 
2117         // Get the first day of the first day-of-week in the year.
2118         int delta = getFirstDayOfWeek() - cal.get(DAY_OF_WEEK);
2119         if (delta != 0) {
2120             if (delta < 0) {
2121                 delta += 7;
2122             }
2123             cal.add(DAY_OF_YEAR, delta);
2124         }
2125         int minDayOfYear = cal.get(DAY_OF_YEAR);
2126         if (dayOfYear < minDayOfYear) {
2127             if (minDayOfYear <= minimalDays) {
2128                 --year;
2129             }
2130         } else {
2131             cal.set(YEAR, year + 1);
2132             cal.set(DAY_OF_YEAR, 1);
2133             cal.complete();
2134             int del = getFirstDayOfWeek() - cal.get(DAY_OF_WEEK);
2135             if (del != 0) {
2136                 if (del < 0) {
2137                     del += 7;
2138                 }
2139                 cal.add(DAY_OF_YEAR, del);
2140             }
2141             minDayOfYear = cal.get(DAY_OF_YEAR) - 1;
2142             if (minDayOfYear == 0) {
2143                 minDayOfYear = 7;
2144             }
2145             if (minDayOfYear >= minimalDays) {
2146                 int days = maxDayOfYear - dayOfYear + 1;
2147                 if (days <= (7 - minDayOfYear)) {
2148                     ++year;
2149                 }
2150             }
2151         }
2152         return year;
2153     }
2154 
2155     /**
2156      * Sets this {@code GregorianCalendar} to the date given by the
2157      * date specifiers - <a href="#week_year">{@code weekYear}</a>,
2158      * {@code weekOfYear}, and {@code dayOfWeek}. {@code weekOfYear}
2159      * follows the <a href="#week_and_year">{@code WEEK_OF_YEAR}
2160      * numbering</a>.  The {@code dayOfWeek} value must be one of the
2161      * {@link Calendar#DAY_OF_WEEK DAY_OF_WEEK} values: {@link
2162      * Calendar#SUNDAY SUNDAY} to {@link Calendar#SATURDAY SATURDAY}.
2163      *
2164      * <p>Note that the numeric day-of-week representation differs from
2165      * the ISO 8601 standard, and that the {@code weekOfYear}
2166      * numbering is compatible with the standard when {@code
2167      * getFirstDayOfWeek()} is {@code MONDAY} and {@code
2168      * getMinimalDaysInFirstWeek()} is 4.
2169      *
2170      * <p>Unlike the {@code set} method, all of the calendar fields
2171      * and the instant of time value are calculated upon return.
2172      *
2173      * <p>If {@code weekOfYear} is out of the valid week-of-year
2174      * range in {@code weekYear}, the {@code weekYear}
2175      * and {@code weekOfYear} values are adjusted in lenient
2176      * mode, or an {@code IllegalArgumentException} is thrown in
2177      * non-lenient mode.
2178      *
2179      * @param weekYear    the week year
2180      * @param weekOfYear  the week number based on {@code weekYear}
2181      * @param dayOfWeek   the day of week value: one of the constants
2182      *                    for the {@link #DAY_OF_WEEK DAY_OF_WEEK} field:
2183      *                    {@link Calendar#SUNDAY SUNDAY}, ...,
2184      *                    {@link Calendar#SATURDAY SATURDAY}.
2185      * @exception IllegalArgumentException
2186      *            if any of the given date specifiers is invalid,
2187      *            or if any of the calendar fields are inconsistent
2188      *            with the given date specifiers in non-lenient mode
2189      * @see GregorianCalendar#isWeekDateSupported()
2190      * @see Calendar#getFirstDayOfWeek()
2191      * @see Calendar#getMinimalDaysInFirstWeek()
2192      * @since 1.7
2193      */
2194     @Override
2195     public void setWeekDate(int weekYear, int weekOfYear, int dayOfWeek) {
2196         if (dayOfWeek < SUNDAY || dayOfWeek > SATURDAY) {
2197             throw new IllegalArgumentException("invalid dayOfWeek: " + dayOfWeek);
2198         }
2199 
2200         // To avoid changing the time of day fields by date
2201         // calculations, use a clone with the GMT time zone.
2202         GregorianCalendar gc = (GregorianCalendar) clone();
2203         gc.setLenient(true);
2204         int era = gc.get(ERA);
2205         gc.clear();
2206         gc.setTimeZone(TimeZone.getTimeZone("GMT"));
2207         gc.set(ERA, era);
2208         gc.set(YEAR, weekYear);
2209         gc.set(WEEK_OF_YEAR, 1);
2210         gc.set(DAY_OF_WEEK, getFirstDayOfWeek());
2211         int days = dayOfWeek - getFirstDayOfWeek();
2212         if (days < 0) {
2213             days += 7;
2214         }
2215         days += 7 * (weekOfYear - 1);
2216         if (days != 0) {
2217             gc.add(DAY_OF_YEAR, days);
2218         } else {
2219             gc.complete();
2220         }
2221 
2222         if (!isLenient() &&
2223             (gc.getWeekYear() != weekYear
2224              || gc.internalGet(WEEK_OF_YEAR) != weekOfYear
2225              || gc.internalGet(DAY_OF_WEEK) != dayOfWeek)) {
2226             throw new IllegalArgumentException();
2227         }
2228 
2229         set(ERA, gc.internalGet(ERA));
2230         set(YEAR, gc.internalGet(YEAR));
2231         set(MONTH, gc.internalGet(MONTH));
2232         set(DAY_OF_MONTH, gc.internalGet(DAY_OF_MONTH));
2233 
2234         // to avoid throwing an IllegalArgumentException in
2235         // non-lenient, set WEEK_OF_YEAR internally
2236         internalSet(WEEK_OF_YEAR, weekOfYear);
2237         complete();
2238     }
2239 
2240     /**
2241      * Returns the number of weeks in the <a href="#week_year">week year</a>
2242      * represented by this {@code GregorianCalendar}.
2243      *
2244      * <p>For example, if this {@code GregorianCalendar}'s date is
2245      * December 31, 2008 with <a href="#iso8601_compatible_setting">the ISO
2246      * 8601 compatible setting</a>, this method will return 53 for the
2247      * period: December 29, 2008 to January 3, 2010 while {@link
2248      * #getActualMaximum(int) getActualMaximum(WEEK_OF_YEAR)} will return
2249      * 52 for the period: December 31, 2007 to December 28, 2008.
2250      *
2251      * @return the number of weeks in the week year.
2252      * @see Calendar#WEEK_OF_YEAR
2253      * @see #getWeekYear()
2254      * @see #getActualMaximum(int)
2255      * @since 1.7
2256      */
2257     @Override
2258     public int getWeeksInWeekYear() {
2259         GregorianCalendar gc = getNormalizedCalendar();
2260         int weekYear = gc.getWeekYear();
2261         if (weekYear == gc.internalGet(YEAR)) {
2262             return gc.getActualMaximum(WEEK_OF_YEAR);
2263         }
2264 
2265         // Use the 2nd week for calculating the max of WEEK_OF_YEAR
2266         if (gc == this) {
2267             gc = (GregorianCalendar) gc.clone();
2268         }
2269         gc.setWeekDate(weekYear, 2, internalGet(DAY_OF_WEEK));
2270         return gc.getActualMaximum(WEEK_OF_YEAR);
2271     }
2272 
2273 /////////////////////////////
2274 // Time => Fields computation
2275 /////////////////////////////
2276 
2277     /**
2278      * The fixed date corresponding to gdate. If the value is
2279      * Long.MIN_VALUE, the fixed date value is unknown. Currently,
2280      * Julian calendar dates are not cached.
2281      */
2282     private transient long cachedFixedDate = Long.MIN_VALUE;
2283 
2284     /**
2285      * Converts the time value (millisecond offset from the <a
2286      * href="Calendar.html#Epoch">Epoch</a>) to calendar field values.
2287      * The time is <em>not</em>
2288      * recomputed first; to recompute the time, then the fields, call the
2289      * <code>complete</code> method.
2290      *
2291      * @see Calendar#complete
2292      */
2293     @Override
2294     protected void computeFields() {
2295         int mask;
2296         if (isPartiallyNormalized()) {
2297             // Determine which calendar fields need to be computed.
2298             mask = getSetStateFields();
2299             int fieldMask = ~mask & ALL_FIELDS;
2300             // We have to call computTime in case calsys == null in
2301             // order to set calsys and cdate. (6263644)
2302             if (fieldMask != 0 || calsys == null) {
2303                 mask |= computeFields(fieldMask,
2304                                       mask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK));
2305                 assert mask == ALL_FIELDS;
2306             }
2307         } else {
2308             mask = ALL_FIELDS;
2309             computeFields(mask, 0);
2310         }
2311         // After computing all the fields, set the field state to `COMPUTED'.
2312         setFieldsComputed(mask);
2313     }
2314 
2315     /**
2316      * This computeFields implements the conversion from UTC
2317      * (millisecond offset from the Epoch) to calendar
2318      * field values. fieldMask specifies which fields to change the
2319      * setting state to COMPUTED, although all fields are set to
2320      * the correct values. This is required to fix 4685354.
2321      *
2322      * @param fieldMask a bit mask to specify which fields to change
2323      * the setting state.
2324      * @param tzMask a bit mask to specify which time zone offset
2325      * fields to be used for time calculations
2326      * @return a new field mask that indicates what field values have
2327      * actually been set.
2328      */
2329     private int computeFields(int fieldMask, int tzMask) {
2330         int zoneOffset = 0;
2331         TimeZone tz = getZone();
2332         if (zoneOffsets == null) {
2333             zoneOffsets = new int[2];
2334         }
2335         if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) {
2336             if (tz instanceof ZoneInfo) {
2337                 zoneOffset = ((ZoneInfo)tz).getOffsets(time, zoneOffsets);
2338             } else {
2339                 zoneOffset = tz.getOffset(time);
2340                 zoneOffsets[0] = tz.getRawOffset();
2341                 zoneOffsets[1] = zoneOffset - zoneOffsets[0];
2342             }
2343         }
2344         if (tzMask != 0) {
2345             if (isFieldSet(tzMask, ZONE_OFFSET)) {
2346                 zoneOffsets[0] = internalGet(ZONE_OFFSET);
2347             }
2348             if (isFieldSet(tzMask, DST_OFFSET)) {
2349                 zoneOffsets[1] = internalGet(DST_OFFSET);
2350             }
2351             zoneOffset = zoneOffsets[0] + zoneOffsets[1];
2352         }
2353 
2354         // By computing time and zoneOffset separately, we can take
2355         // the wider range of time+zoneOffset than the previous
2356         // implementation.
2357         long fixedDate = zoneOffset / ONE_DAY;
2358         int timeOfDay = zoneOffset % (int)ONE_DAY;
2359         fixedDate += time / ONE_DAY;
2360         timeOfDay += (int) (time % ONE_DAY);
2361         if (timeOfDay >= ONE_DAY) {
2362             timeOfDay -= ONE_DAY;
2363             ++fixedDate;
2364         } else {
2365             while (timeOfDay < 0) {
2366                 timeOfDay += ONE_DAY;
2367                 --fixedDate;
2368             }
2369         }
2370         fixedDate += EPOCH_OFFSET;
2371 
2372         int era = CE;
2373         int year;
2374         if (fixedDate >= gregorianCutoverDate) {
2375             // Handle Gregorian dates.
2376             assert cachedFixedDate == Long.MIN_VALUE || gdate.isNormalized()
2377                         : "cache control: not normalized";
2378             assert cachedFixedDate == Long.MIN_VALUE ||
2379                    gcal.getFixedDate(gdate.getNormalizedYear(),
2380                                           gdate.getMonth(),
2381                                           gdate.getDayOfMonth(), gdate)
2382                                 == cachedFixedDate
2383                         : "cache control: inconsictency" +
2384                           ", cachedFixedDate=" + cachedFixedDate +
2385                           ", computed=" +
2386                           gcal.getFixedDate(gdate.getNormalizedYear(),
2387                                                  gdate.getMonth(),
2388                                                  gdate.getDayOfMonth(),
2389                                                  gdate) +
2390                           ", date=" + gdate;
2391 
2392             // See if we can use gdate to avoid date calculation.
2393             if (fixedDate != cachedFixedDate) {
2394                 gcal.getCalendarDateFromFixedDate(gdate, fixedDate);
2395                 cachedFixedDate = fixedDate;
2396             }
2397 
2398             year = gdate.getYear();
2399             if (year <= 0) {
2400                 year = 1 - year;
2401                 era = BCE;
2402             }
2403             calsys = gcal;
2404             cdate = gdate;
2405             assert cdate.getDayOfWeek() > 0 : "dow="+cdate.getDayOfWeek()+", date="+cdate;
2406         } else {
2407             // Handle Julian calendar dates.
2408             calsys = getJulianCalendarSystem();
2409             cdate = (BaseCalendar.Date) jcal.newCalendarDate(getZone());
2410             jcal.getCalendarDateFromFixedDate(cdate, fixedDate);
2411             Era e = cdate.getEra();
2412             if (e == jeras[0]) {
2413                 era = BCE;
2414             }
2415             year = cdate.getYear();
2416         }
2417 
2418         // Always set the ERA and YEAR values.
2419         internalSet(ERA, era);
2420         internalSet(YEAR, year);
2421         int mask = fieldMask | (ERA_MASK|YEAR_MASK);
2422 
2423         int month =  cdate.getMonth() - 1; // 0-based
2424         int dayOfMonth = cdate.getDayOfMonth();
2425 
2426         // Set the basic date fields.
2427         if ((fieldMask & (MONTH_MASK|DAY_OF_MONTH_MASK|DAY_OF_WEEK_MASK))
2428             != 0) {
2429             internalSet(MONTH, month);
2430             internalSet(DAY_OF_MONTH, dayOfMonth);
2431             internalSet(DAY_OF_WEEK, cdate.getDayOfWeek());
2432             mask |= MONTH_MASK|DAY_OF_MONTH_MASK|DAY_OF_WEEK_MASK;
2433         }
2434 
2435         if ((fieldMask & (HOUR_OF_DAY_MASK|AM_PM_MASK|HOUR_MASK
2436                           |MINUTE_MASK|SECOND_MASK|MILLISECOND_MASK)) != 0) {
2437             if (timeOfDay != 0) {
2438                 int hours = timeOfDay / ONE_HOUR;
2439                 internalSet(HOUR_OF_DAY, hours);
2440                 internalSet(AM_PM, hours / 12); // Assume AM == 0
2441                 internalSet(HOUR, hours % 12);
2442                 int r = timeOfDay % ONE_HOUR;
2443                 internalSet(MINUTE, r / ONE_MINUTE);
2444                 r %= ONE_MINUTE;
2445                 internalSet(SECOND, r / ONE_SECOND);
2446                 internalSet(MILLISECOND, r % ONE_SECOND);
2447             } else {
2448                 internalSet(HOUR_OF_DAY, 0);
2449                 internalSet(AM_PM, AM);
2450                 internalSet(HOUR, 0);
2451                 internalSet(MINUTE, 0);
2452                 internalSet(SECOND, 0);
2453                 internalSet(MILLISECOND, 0);
2454             }
2455             mask |= (HOUR_OF_DAY_MASK|AM_PM_MASK|HOUR_MASK
2456                      |MINUTE_MASK|SECOND_MASK|MILLISECOND_MASK);
2457         }
2458 
2459         if ((fieldMask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) != 0) {
2460             internalSet(ZONE_OFFSET, zoneOffsets[0]);
2461             internalSet(DST_OFFSET, zoneOffsets[1]);
2462             mask |= (ZONE_OFFSET_MASK|DST_OFFSET_MASK);
2463         }
2464 
2465         if ((fieldMask & (DAY_OF_YEAR_MASK|WEEK_OF_YEAR_MASK|WEEK_OF_MONTH_MASK|DAY_OF_WEEK_IN_MONTH_MASK)) != 0) {
2466             int normalizedYear = cdate.getNormalizedYear();
2467             long fixedDateJan1 = calsys.getFixedDate(normalizedYear, 1, 1, cdate);
2468             int dayOfYear = (int)(fixedDate - fixedDateJan1) + 1;
2469             long fixedDateMonth1 = fixedDate - dayOfMonth + 1;
2470             int cutoverGap = 0;
2471             int cutoverYear = (calsys == gcal) ? gregorianCutoverYear : gregorianCutoverYearJulian;
2472             int relativeDayOfMonth = dayOfMonth - 1;
2473 
2474             // If we are in the cutover year, we need some special handling.
2475             if (normalizedYear == cutoverYear) {
2476                 // Need to take care of the "missing" days.
2477                 if (gregorianCutoverYearJulian <= gregorianCutoverYear) {
2478                     // We need to find out where we are. The cutover
2479                     // gap could even be more than one year.  (One
2480                     // year difference in ~48667 years.)
2481                     fixedDateJan1 = getFixedDateJan1(cdate, fixedDate);
2482                     if (fixedDate >= gregorianCutoverDate) {
2483                         fixedDateMonth1 = getFixedDateMonth1(cdate, fixedDate);
2484                     }
2485                 }
2486                 int realDayOfYear = (int)(fixedDate - fixedDateJan1) + 1;
2487                 cutoverGap = dayOfYear - realDayOfYear;
2488                 dayOfYear = realDayOfYear;
2489                 relativeDayOfMonth = (int)(fixedDate - fixedDateMonth1);
2490             }
2491             internalSet(DAY_OF_YEAR, dayOfYear);
2492             internalSet(DAY_OF_WEEK_IN_MONTH, relativeDayOfMonth / 7 + 1);
2493 
2494             int weekOfYear = getWeekNumber(fixedDateJan1, fixedDate);
2495 
2496             // The spec is to calculate WEEK_OF_YEAR in the
2497             // ISO8601-style. This creates problems, though.
2498             if (weekOfYear == 0) {
2499                 // If the date belongs to the last week of the
2500                 // previous year, use the week number of "12/31" of
2501                 // the "previous" year. Again, if the previous year is
2502                 // the Gregorian cutover year, we need to take care of
2503                 // it.  Usually the previous day of January 1 is
2504                 // December 31, which is not always true in
2505                 // GregorianCalendar.
2506                 long fixedDec31 = fixedDateJan1 - 1;
2507                 long prevJan1  = fixedDateJan1 - 365;
2508                 if (normalizedYear > (cutoverYear + 1)) {
2509                     if (CalendarUtils.isGregorianLeapYear(normalizedYear - 1)) {
2510                         --prevJan1;
2511                     }
2512                 } else if (normalizedYear <= gregorianCutoverYearJulian) {
2513                     if (CalendarUtils.isJulianLeapYear(normalizedYear - 1)) {
2514                         --prevJan1;
2515                     }
2516                 } else {
2517                     BaseCalendar calForJan1 = calsys;
2518                     //int prevYear = normalizedYear - 1;
2519                     int prevYear = getCalendarDate(fixedDec31).getNormalizedYear();
2520                     if (prevYear == gregorianCutoverYear) {
2521                         calForJan1 = getCutoverCalendarSystem();
2522                         if (calForJan1 == jcal) {
2523                             prevJan1 = calForJan1.getFixedDate(prevYear,
2524                                                                BaseCalendar.JANUARY,
2525                                                                1,
2526                                                                null);
2527                         } else {
2528                             prevJan1 = gregorianCutoverDate;
2529                             calForJan1 = gcal;
2530                         }
2531                     } else if (prevYear <= gregorianCutoverYearJulian) {
2532                         calForJan1 = getJulianCalendarSystem();
2533                         prevJan1 = calForJan1.getFixedDate(prevYear,
2534                                                            BaseCalendar.JANUARY,
2535                                                            1,
2536                                                            null);
2537                     }
2538                 }
2539                 weekOfYear = getWeekNumber(prevJan1, fixedDec31);
2540             } else {
2541                 if (normalizedYear > gregorianCutoverYear ||
2542                     normalizedYear < (gregorianCutoverYearJulian - 1)) {
2543                     // Regular years
2544                     if (weekOfYear >= 52) {
2545                         long nextJan1 = fixedDateJan1 + 365;
2546                         if (cdate.isLeapYear()) {
2547                             nextJan1++;
2548                         }
2549                         long nextJan1st = BaseCalendar.getDayOfWeekDateOnOrBefore(nextJan1 + 6,
2550                                                                                   getFirstDayOfWeek());
2551                         int ndays = (int)(nextJan1st - nextJan1);
2552                         if (ndays >= getMinimalDaysInFirstWeek() && fixedDate >= (nextJan1st - 7)) {
2553                             // The first days forms a week in which the date is included.
2554                             weekOfYear = 1;
2555                         }
2556                     }
2557                 } else {
2558                     BaseCalendar calForJan1 = calsys;
2559                     int nextYear = normalizedYear + 1;
2560                     if (nextYear == (gregorianCutoverYearJulian + 1) &&
2561                         nextYear < gregorianCutoverYear) {
2562                         // In case the gap is more than one year.
2563                         nextYear = gregorianCutoverYear;
2564                     }
2565                     if (nextYear == gregorianCutoverYear) {
2566                         calForJan1 = getCutoverCalendarSystem();
2567                     }
2568 
2569                     long nextJan1;
2570                     if (nextYear > gregorianCutoverYear
2571                         || gregorianCutoverYearJulian == gregorianCutoverYear
2572                         || nextYear == gregorianCutoverYearJulian) {
2573                         nextJan1 = calForJan1.getFixedDate(nextYear,
2574                                                            BaseCalendar.JANUARY,
2575                                                            1,
2576                                                            null);
2577                     } else {
2578                         nextJan1 = gregorianCutoverDate;
2579                         calForJan1 = gcal;
2580                     }
2581 
2582                     long nextJan1st = BaseCalendar.getDayOfWeekDateOnOrBefore(nextJan1 + 6,
2583                                                                               getFirstDayOfWeek());
2584                     int ndays = (int)(nextJan1st - nextJan1);
2585                     if (ndays >= getMinimalDaysInFirstWeek() && fixedDate >= (nextJan1st - 7)) {
2586                         // The first days forms a week in which the date is included.
2587                         weekOfYear = 1;
2588                     }
2589                 }
2590             }
2591             internalSet(WEEK_OF_YEAR, weekOfYear);
2592             internalSet(WEEK_OF_MONTH, getWeekNumber(fixedDateMonth1, fixedDate));
2593             mask |= (DAY_OF_YEAR_MASK|WEEK_OF_YEAR_MASK|WEEK_OF_MONTH_MASK|DAY_OF_WEEK_IN_MONTH_MASK);
2594         }
2595         return mask;
2596     }
2597 
2598     /**
2599      * Returns the number of weeks in a period between fixedDay1 and
2600      * fixedDate. The getFirstDayOfWeek-getMinimalDaysInFirstWeek rule
2601      * is applied to calculate the number of weeks.
2602      *
2603      * @param fixedDay1 the fixed date of the first day of the period
2604      * @param fixedDate the fixed date of the last day of the period
2605      * @return the number of weeks of the given period
2606      */
2607     private int getWeekNumber(long fixedDay1, long fixedDate) {
2608         // We can always use `gcal' since Julian and Gregorian are the
2609         // same thing for this calculation.
2610         long fixedDay1st = Gregorian.getDayOfWeekDateOnOrBefore(fixedDay1 + 6,
2611                                                                 getFirstDayOfWeek());
2612         int ndays = (int)(fixedDay1st - fixedDay1);
2613         assert ndays <= 7;
2614         if (ndays >= getMinimalDaysInFirstWeek()) {
2615             fixedDay1st -= 7;
2616         }
2617         int normalizedDayOfPeriod = (int)(fixedDate - fixedDay1st);
2618         if (normalizedDayOfPeriod >= 0) {
2619             return normalizedDayOfPeriod / 7 + 1;
2620         }
2621         return CalendarUtils.floorDivide(normalizedDayOfPeriod, 7) + 1;
2622     }
2623 
2624     /**
2625      * Converts calendar field values to the time value (millisecond
2626      * offset from the <a href="Calendar.html#Epoch">Epoch</a>).
2627      *
2628      * @exception IllegalArgumentException if any calendar fields are invalid.
2629      */
2630     @Override
2631     protected void computeTime() {
2632         // In non-lenient mode, perform brief checking of calendar
2633         // fields which have been set externally. Through this
2634         // checking, the field values are stored in originalFields[]
2635         // to see if any of them are normalized later.
2636         if (!isLenient()) {
2637             if (originalFields == null) {
2638                 originalFields = new int[FIELD_COUNT];
2639             }
2640             for (int field = 0; field < FIELD_COUNT; field++) {
2641                 int value = internalGet(field);
2642                 if (isExternallySet(field)) {
2643                     // Quick validation for any out of range values
2644                     if (value < getMinimum(field) || value > getMaximum(field)) {
2645                         throw new IllegalArgumentException(getFieldName(field));
2646                     }
2647                 }
2648                 originalFields[field] = value;
2649             }
2650         }
2651 
2652         // Let the super class determine which calendar fields to be
2653         // used to calculate the time.
2654         int fieldMask = selectFields();
2655 
2656         // The year defaults to the epoch start. We don't check
2657         // fieldMask for YEAR because YEAR is a mandatory field to
2658         // determine the date.
2659         int year = isSet(YEAR) ? internalGet(YEAR) : EPOCH_YEAR;
2660 
2661         int era = internalGetEra();
2662         if (era == BCE) {
2663             year = 1 - year;
2664         } else if (era != CE) {
2665             // Even in lenient mode we disallow ERA values other than CE & BCE.
2666             // (The same normalization rule as add()/roll() could be
2667             // applied here in lenient mode. But this checking is kept
2668             // unchanged for compatibility as of 1.5.)
2669             throw new IllegalArgumentException("Invalid era");
2670         }
2671 
2672         // If year is 0 or negative, we need to set the ERA value later.
2673         if (year <= 0 && !isSet(ERA)) {
2674             fieldMask |= ERA_MASK;
2675             setFieldsComputed(ERA_MASK);
2676         }
2677 
2678         // Calculate the time of day. We rely on the convention that
2679         // an UNSET field has 0.
2680         long timeOfDay = 0;
2681         if (isFieldSet(fieldMask, HOUR_OF_DAY)) {
2682             timeOfDay += (long) internalGet(HOUR_OF_DAY);
2683         } else {
2684             timeOfDay += internalGet(HOUR);
2685             // The default value of AM_PM is 0 which designates AM.
2686             if (isFieldSet(fieldMask, AM_PM)) {
2687                 timeOfDay += 12 * internalGet(AM_PM);
2688             }
2689         }
2690         timeOfDay *= 60;
2691         timeOfDay += internalGet(MINUTE);
2692         timeOfDay *= 60;
2693         timeOfDay += internalGet(SECOND);
2694         timeOfDay *= 1000;
2695         timeOfDay += internalGet(MILLISECOND);
2696 
2697         // Convert the time of day to the number of days and the
2698         // millisecond offset from midnight.
2699         long fixedDate = timeOfDay / ONE_DAY;
2700         timeOfDay %= ONE_DAY;
2701         while (timeOfDay < 0) {
2702             timeOfDay += ONE_DAY;
2703             --fixedDate;
2704         }
2705 
2706         // Calculate the fixed date since January 1, 1 (Gregorian).
2707         calculateFixedDate: {
2708             long gfd, jfd;
2709             if (year > gregorianCutoverYear && year > gregorianCutoverYearJulian) {
2710                 gfd = fixedDate + getFixedDate(gcal, year, fieldMask);
2711                 if (gfd >= gregorianCutoverDate) {
2712                     fixedDate = gfd;
2713                     break calculateFixedDate;
2714                 }
2715                 jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask);
2716             } else if (year < gregorianCutoverYear && year < gregorianCutoverYearJulian) {
2717                 jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask);
2718                 if (jfd < gregorianCutoverDate) {
2719                     fixedDate = jfd;
2720                     break calculateFixedDate;
2721                 }
2722                 gfd = jfd;
2723             } else {
2724                 jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask);
2725                 gfd = fixedDate + getFixedDate(gcal, year, fieldMask);
2726             }
2727 
2728             // Now we have to determine which calendar date it is.
2729 
2730             // If the date is relative from the beginning of the year
2731             // in the Julian calendar, then use jfd;
2732             if (isFieldSet(fieldMask, DAY_OF_YEAR) || isFieldSet(fieldMask, WEEK_OF_YEAR)) {
2733                 if (gregorianCutoverYear == gregorianCutoverYearJulian) {
2734                     fixedDate = jfd;
2735                     break calculateFixedDate;
2736                 } else if (year == gregorianCutoverYear) {
2737                     fixedDate = gfd;
2738                     break calculateFixedDate;
2739                 }
2740             }
2741 
2742             if (gfd >= gregorianCutoverDate) {
2743                 if (jfd >= gregorianCutoverDate) {
2744                     fixedDate = gfd;
2745                 } else {
2746                     // The date is in an "overlapping" period. No way
2747                     // to disambiguate it. Determine it using the
2748                     // previous date calculation.
2749                     if (calsys == gcal || calsys == null) {
2750                         fixedDate = gfd;
2751                     } else {
2752                         fixedDate = jfd;
2753                     }
2754                 }
2755             } else {
2756                 if (jfd < gregorianCutoverDate) {
2757                     fixedDate = jfd;
2758                 } else {
2759                     // The date is in a "missing" period.
2760                     if (!isLenient()) {
2761                         throw new IllegalArgumentException("the specified date doesn't exist");
2762                     }
2763                     // Take the Julian date for compatibility, which
2764                     // will produce a Gregorian date.
2765                     fixedDate = jfd;
2766                 }
2767             }
2768         }
2769 
2770         // millis represents local wall-clock time in milliseconds.
2771         long millis = (fixedDate - EPOCH_OFFSET) * ONE_DAY + timeOfDay;
2772 
2773         // Compute the time zone offset and DST offset.  There are two potential
2774         // ambiguities here.  We'll assume a 2:00 am (wall time) switchover time
2775         // for discussion purposes here.
2776         // 1. The transition into DST.  Here, a designated time of 2:00 am - 2:59 am
2777         //    can be in standard or in DST depending.  However, 2:00 am is an invalid
2778         //    representation (the representation jumps from 1:59:59 am Std to 3:00:00 am DST).
2779         //    We assume standard time.
2780         // 2. The transition out of DST.  Here, a designated time of 1:00 am - 1:59 am
2781         //    can be in standard or DST.  Both are valid representations (the rep
2782         //    jumps from 1:59:59 DST to 1:00:00 Std).
2783         //    Again, we assume standard time.
2784         // We use the TimeZone object, unless the user has explicitly set the ZONE_OFFSET
2785         // or DST_OFFSET fields; then we use those fields.
2786         TimeZone zone = getZone();
2787         if (zoneOffsets == null) {
2788             zoneOffsets = new int[2];
2789         }
2790         int tzMask = fieldMask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK);
2791         if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) {
2792             if (zone instanceof ZoneInfo) {
2793                 ((ZoneInfo)zone).getOffsetsByWall(millis, zoneOffsets);
2794             } else {
2795                 int gmtOffset = isFieldSet(fieldMask, ZONE_OFFSET) ?
2796                                     internalGet(ZONE_OFFSET) : zone.getRawOffset();
2797                 zone.getOffsets(millis - gmtOffset, zoneOffsets);
2798             }
2799         }
2800         if (tzMask != 0) {
2801             if (isFieldSet(tzMask, ZONE_OFFSET)) {
2802                 zoneOffsets[0] = internalGet(ZONE_OFFSET);
2803             }
2804             if (isFieldSet(tzMask, DST_OFFSET)) {
2805                 zoneOffsets[1] = internalGet(DST_OFFSET);
2806             }
2807         }
2808 
2809         // Adjust the time zone offset values to get the UTC time.
2810         millis -= zoneOffsets[0] + zoneOffsets[1];
2811 
2812         // Set this calendar's time in milliseconds
2813         time = millis;
2814 
2815         int mask = computeFields(fieldMask | getSetStateFields(), tzMask);
2816 
2817         if (!isLenient()) {
2818             for (int field = 0; field < FIELD_COUNT; field++) {
2819                 if (!isExternallySet(field)) {
2820                     continue;
2821                 }
2822                 if (originalFields[field] != internalGet(field)) {
2823                     String s = originalFields[field] + " -> " + internalGet(field);
2824                     // Restore the original field values
2825                     System.arraycopy(originalFields, 0, fields, 0, fields.length);
2826                     throw new IllegalArgumentException(getFieldName(field) + ": " + s);
2827                 }
2828             }
2829         }
2830         setFieldsNormalized(mask);
2831     }
2832 
2833     /**
2834      * Computes the fixed date under either the Gregorian or the
2835      * Julian calendar, using the given year and the specified calendar fields.
2836      *
2837      * @param cal the CalendarSystem to be used for the date calculation
2838      * @param year the normalized year number, with 0 indicating the
2839      * year 1 BCE, -1 indicating 2 BCE, etc.
2840      * @param fieldMask the calendar fields to be used for the date calculation
2841      * @return the fixed date
2842      * @see Calendar#selectFields
2843      */
2844     private long getFixedDate(BaseCalendar cal, int year, int fieldMask) {
2845         int month = JANUARY;
2846         if (isFieldSet(fieldMask, MONTH)) {
2847             // No need to check if MONTH has been set (no isSet(MONTH)
2848             // call) since its unset value happens to be JANUARY (0).
2849             month = internalGet(MONTH);
2850 
2851             // If the month is out of range, adjust it into range
2852             if (month > DECEMBER) {
2853                 year += month / 12;
2854                 month %= 12;
2855             } else if (month < JANUARY) {
2856                 int[] rem = new int[1];
2857                 year += CalendarUtils.floorDivide(month, 12, rem);
2858                 month = rem[0];
2859             }
2860         }
2861 
2862         // Get the fixed date since Jan 1, 1 (Gregorian). We are on
2863         // the first day of either `month' or January in 'year'.
2864         long fixedDate = cal.getFixedDate(year, month + 1, 1,
2865                                           cal == gcal ? gdate : null);
2866         if (isFieldSet(fieldMask, MONTH)) {
2867             // Month-based calculations
2868             if (isFieldSet(fieldMask, DAY_OF_MONTH)) {
2869                 // We are on the first day of the month. Just add the
2870                 // offset if DAY_OF_MONTH is set. If the isSet call
2871                 // returns false, that means DAY_OF_MONTH has been
2872                 // selected just because of the selected
2873                 // combination. We don't need to add any since the
2874                 // default value is the 1st.
2875                 if (isSet(DAY_OF_MONTH)) {
2876                     // To avoid underflow with DAY_OF_MONTH-1, add
2877                     // DAY_OF_MONTH, then subtract 1.
2878                     fixedDate += internalGet(DAY_OF_MONTH);
2879                     fixedDate--;
2880                 }
2881             } else {
2882                 if (isFieldSet(fieldMask, WEEK_OF_MONTH)) {
2883                     long firstDayOfWeek = BaseCalendar.getDayOfWeekDateOnOrBefore(fixedDate + 6,
2884                                                                                   getFirstDayOfWeek());
2885                     // If we have enough days in the first week, then
2886                     // move to the previous week.
2887                     if ((firstDayOfWeek - fixedDate) >= getMinimalDaysInFirstWeek()) {
2888                         firstDayOfWeek -= 7;
2889                     }
2890                     if (isFieldSet(fieldMask, DAY_OF_WEEK)) {
2891                         firstDayOfWeek = BaseCalendar.getDayOfWeekDateOnOrBefore(firstDayOfWeek + 6,
2892                                                                                  internalGet(DAY_OF_WEEK));
2893                     }
2894                     // In lenient mode, we treat days of the previous
2895                     // months as a part of the specified
2896                     // WEEK_OF_MONTH. See 4633646.
2897                     fixedDate = firstDayOfWeek + 7 * (internalGet(WEEK_OF_MONTH) - 1);
2898                 } else {
2899                     int dayOfWeek;
2900                     if (isFieldSet(fieldMask, DAY_OF_WEEK)) {
2901                         dayOfWeek = internalGet(DAY_OF_WEEK);
2902                     } else {
2903                         dayOfWeek = getFirstDayOfWeek();
2904                     }
2905                     // We are basing this on the day-of-week-in-month.  The only
2906                     // trickiness occurs if the day-of-week-in-month is
2907                     // negative.
2908                     int dowim;
2909                     if (isFieldSet(fieldMask, DAY_OF_WEEK_IN_MONTH)) {
2910                         dowim = internalGet(DAY_OF_WEEK_IN_MONTH);
2911                     } else {
2912                         dowim = 1;
2913                     }
2914                     if (dowim >= 0) {
2915                         fixedDate = BaseCalendar.getDayOfWeekDateOnOrBefore(fixedDate + (7 * dowim) - 1,
2916                                                                             dayOfWeek);
2917                     } else {
2918                         // Go to the first day of the next week of
2919                         // the specified week boundary.
2920                         int lastDate = monthLength(month, year) + (7 * (dowim + 1));
2921                         // Then, get the day of week date on or before the last date.
2922                         fixedDate = BaseCalendar.getDayOfWeekDateOnOrBefore(fixedDate + lastDate - 1,
2923                                                                             dayOfWeek);
2924                     }
2925                 }
2926             }
2927         } else {
2928             if (year == gregorianCutoverYear && cal == gcal
2929                 && fixedDate < gregorianCutoverDate
2930                 && gregorianCutoverYear != gregorianCutoverYearJulian) {
2931                 // January 1 of the year doesn't exist.  Use
2932                 // gregorianCutoverDate as the first day of the
2933                 // year.
2934                 fixedDate = gregorianCutoverDate;
2935             }
2936             // We are on the first day of the year.
2937             if (isFieldSet(fieldMask, DAY_OF_YEAR)) {
2938                 // Add the offset, then subtract 1. (Make sure to avoid underflow.)
2939                 fixedDate += internalGet(DAY_OF_YEAR);
2940                 fixedDate--;
2941             } else {
2942                 long firstDayOfWeek = BaseCalendar.getDayOfWeekDateOnOrBefore(fixedDate + 6,
2943                                                                               getFirstDayOfWeek());
2944                 // If we have enough days in the first week, then move
2945                 // to the previous week.
2946                 if ((firstDayOfWeek - fixedDate) >= getMinimalDaysInFirstWeek()) {
2947                     firstDayOfWeek -= 7;
2948                 }
2949                 if (isFieldSet(fieldMask, DAY_OF_WEEK)) {
2950                     int dayOfWeek = internalGet(DAY_OF_WEEK);
2951                     if (dayOfWeek != getFirstDayOfWeek()) {
2952                         firstDayOfWeek = BaseCalendar.getDayOfWeekDateOnOrBefore(firstDayOfWeek + 6,
2953                                                                                  dayOfWeek);
2954                     }
2955                 }
2956                 fixedDate = firstDayOfWeek + 7 * ((long)internalGet(WEEK_OF_YEAR) - 1);
2957             }
2958         }
2959 
2960         return fixedDate;
2961     }
2962 
2963     /**
2964      * Returns this object if it's normalized (all fields and time are
2965      * in sync). Otherwise, a cloned object is returned after calling
2966      * complete() in lenient mode.
2967      */
2968     private GregorianCalendar getNormalizedCalendar() {
2969         GregorianCalendar gc;
2970         if (isFullyNormalized()) {
2971             gc = this;
2972         } else {
2973             // Create a clone and normalize the calendar fields
2974             gc = (GregorianCalendar) this.clone();
2975             gc.setLenient(true);
2976             gc.complete();
2977         }
2978         return gc;
2979     }
2980 
2981     /**
2982      * Returns the Julian calendar system instance (singleton). 'jcal'
2983      * and 'jeras' are set upon the return.
2984      */
2985     private static synchronized BaseCalendar getJulianCalendarSystem() {
2986         if (jcal == null) {
2987             jcal = (JulianCalendar) CalendarSystem.forName("julian");
2988             jeras = jcal.getEras();
2989         }
2990         return jcal;
2991     }
2992 
2993     /**
2994      * Returns the calendar system for dates before the cutover date
2995      * in the cutover year. If the cutover date is January 1, the
2996      * method returns Gregorian. Otherwise, Julian.
2997      */
2998     private BaseCalendar getCutoverCalendarSystem() {
2999         if (gregorianCutoverYearJulian < gregorianCutoverYear) {
3000             return gcal;
3001         }
3002         return getJulianCalendarSystem();
3003     }
3004 
3005     /**
3006      * Determines if the specified year (normalized) is the Gregorian
3007      * cutover year. This object must have been normalized.
3008      */
3009     private boolean isCutoverYear(int normalizedYear) {
3010         int cutoverYear = (calsys == gcal) ? gregorianCutoverYear : gregorianCutoverYearJulian;
3011         return normalizedYear == cutoverYear;
3012     }
3013 
3014     /**
3015      * Returns the fixed date of the first day of the year (usually
3016      * January 1) before the specified date.
3017      *
3018      * @param date the date for which the first day of the year is
3019      * calculated. The date has to be in the cut-over year (Gregorian
3020      * or Julian).
3021      * @param fixedDate the fixed date representation of the date
3022      */
3023     private long getFixedDateJan1(BaseCalendar.Date date, long fixedDate) {
3024         assert date.getNormalizedYear() == gregorianCutoverYear ||
3025             date.getNormalizedYear() == gregorianCutoverYearJulian;
3026         if (gregorianCutoverYear != gregorianCutoverYearJulian) {
3027             if (fixedDate >= gregorianCutoverDate) {
3028                 // Dates before the cutover date don't exist
3029                 // in the same (Gregorian) year. So, no
3030                 // January 1 exists in the year. Use the
3031                 // cutover date as the first day of the year.
3032                 return gregorianCutoverDate;
3033             }
3034         }
3035         // January 1 of the normalized year should exist.
3036         BaseCalendar juliancal = getJulianCalendarSystem();
3037         return juliancal.getFixedDate(date.getNormalizedYear(), BaseCalendar.JANUARY, 1, null);
3038     }
3039 
3040     /**
3041      * Returns the fixed date of the first date of the month (usually
3042      * the 1st of the month) before the specified date.
3043      *
3044      * @param date the date for which the first day of the month is
3045      * calculated. The date has to be in the cut-over year (Gregorian
3046      * or Julian).
3047      * @param fixedDate the fixed date representation of the date
3048      */
3049     private long getFixedDateMonth1(BaseCalendar.Date date, long fixedDate) {
3050         assert date.getNormalizedYear() == gregorianCutoverYear ||
3051             date.getNormalizedYear() == gregorianCutoverYearJulian;
3052         BaseCalendar.Date gCutover = getGregorianCutoverDate();
3053         if (gCutover.getMonth() == BaseCalendar.JANUARY
3054             && gCutover.getDayOfMonth() == 1) {
3055             // The cutover happened on January 1.
3056             return fixedDate - date.getDayOfMonth() + 1;
3057         }
3058 
3059         long fixedDateMonth1;
3060         // The cutover happened sometime during the year.
3061         if (date.getMonth() == gCutover.getMonth()) {
3062             // The cutover happened in the month.
3063             BaseCalendar.Date jLastDate = getLastJulianDate();
3064             if (gregorianCutoverYear == gregorianCutoverYearJulian
3065                 && gCutover.getMonth() == jLastDate.getMonth()) {
3066                 // The "gap" fits in the same month.
3067                 fixedDateMonth1 = jcal.getFixedDate(date.getNormalizedYear(),
3068                                                     date.getMonth(),
3069                                                     1,
3070                                                     null);
3071             } else {
3072                 // Use the cutover date as the first day of the month.
3073                 fixedDateMonth1 = gregorianCutoverDate;
3074             }
3075         } else {
3076             // The cutover happened before the month.
3077             fixedDateMonth1 = fixedDate - date.getDayOfMonth() + 1;
3078         }
3079 
3080         return fixedDateMonth1;
3081     }
3082 
3083     /**
3084      * Returns a CalendarDate produced from the specified fixed date.
3085      *
3086      * @param fd the fixed date
3087      */
3088     private BaseCalendar.Date getCalendarDate(long fd) {
3089         BaseCalendar cal = (fd >= gregorianCutoverDate) ? gcal : getJulianCalendarSystem();
3090         BaseCalendar.Date d = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.NO_TIMEZONE);
3091         cal.getCalendarDateFromFixedDate(d, fd);
3092         return d;
3093     }
3094 
3095     /**
3096      * Returns the Gregorian cutover date as a BaseCalendar.Date. The
3097      * date is a Gregorian date.
3098      */
3099     private BaseCalendar.Date getGregorianCutoverDate() {
3100         return getCalendarDate(gregorianCutoverDate);
3101     }
3102 
3103     /**
3104      * Returns the day before the Gregorian cutover date as a
3105      * BaseCalendar.Date. The date is a Julian date.
3106      */
3107     private BaseCalendar.Date getLastJulianDate() {
3108         return getCalendarDate(gregorianCutoverDate - 1);
3109     }
3110 
3111     /**
3112      * Returns the length of the specified month in the specified
3113      * year. The year number must be normalized.
3114      *
3115      * @see #isLeapYear(int)
3116      */
3117     private int monthLength(int month, int year) {
3118         return isLeapYear(year) ? LEAP_MONTH_LENGTH[month] : MONTH_LENGTH[month];
3119     }
3120 
3121     /**
3122      * Returns the length of the specified month in the year provided
3123      * by internalGet(YEAR).
3124      *
3125      * @see #isLeapYear(int)
3126      */
3127     private int monthLength(int month) {
3128         int year = internalGet(YEAR);
3129         if (internalGetEra() == BCE) {
3130             year = 1 - year;
3131         }
3132         return monthLength(month, year);
3133     }
3134 
3135     private int actualMonthLength() {
3136         int year = cdate.getNormalizedYear();
3137         if (year != gregorianCutoverYear && year != gregorianCutoverYearJulian) {
3138             return calsys.getMonthLength(cdate);
3139         }
3140         BaseCalendar.Date date = (BaseCalendar.Date) cdate.clone();
3141         long fd = calsys.getFixedDate(date);
3142         long month1 = getFixedDateMonth1(date, fd);
3143         long next1 = month1 + calsys.getMonthLength(date);
3144         if (next1 < gregorianCutoverDate) {
3145             return (int)(next1 - month1);
3146         }
3147         if (cdate != gdate) {
3148             date = (BaseCalendar.Date) gcal.newCalendarDate(TimeZone.NO_TIMEZONE);
3149         }
3150         gcal.getCalendarDateFromFixedDate(date, next1);
3151         next1 = getFixedDateMonth1(date, next1);
3152         return (int)(next1 - month1);
3153     }
3154 
3155     /**
3156      * Returns the length (in days) of the specified year. The year
3157      * must be normalized.
3158      */
3159     private int yearLength(int year) {
3160         return isLeapYear(year) ? 366 : 365;
3161     }
3162 
3163     /**
3164      * Returns the length (in days) of the year provided by
3165      * internalGet(YEAR).
3166      */
3167     private int yearLength() {
3168         int year = internalGet(YEAR);
3169         if (internalGetEra() == BCE) {
3170             year = 1 - year;
3171         }
3172         return yearLength(year);
3173     }
3174 
3175     /**
3176      * After adjustments such as add(MONTH), add(YEAR), we don't want the
3177      * month to jump around.  E.g., we don't want Jan 31 + 1 month to go to Mar
3178      * 3, we want it to go to Feb 28.  Adjustments which might run into this
3179      * problem call this method to retain the proper month.
3180      */
3181     private void pinDayOfMonth() {
3182         int year = internalGet(YEAR);
3183         int monthLen;
3184         if (year > gregorianCutoverYear || year < gregorianCutoverYearJulian) {
3185             monthLen = monthLength(internalGet(MONTH));
3186         } else {
3187             GregorianCalendar gc = getNormalizedCalendar();
3188             monthLen = gc.getActualMaximum(DAY_OF_MONTH);
3189         }
3190         int dom = internalGet(DAY_OF_MONTH);
3191         if (dom > monthLen) {
3192             set(DAY_OF_MONTH, monthLen);
3193         }
3194     }
3195 
3196     /**
3197      * Returns the fixed date value of this object. The time value and
3198      * calendar fields must be in synch.
3199      */
3200     private long getCurrentFixedDate() {
3201         return (calsys == gcal) ? cachedFixedDate : calsys.getFixedDate(cdate);
3202     }
3203 
3204     /**
3205      * Returns the new value after 'roll'ing the specified value and amount.
3206      */
3207     private static int getRolledValue(int value, int amount, int min, int max) {
3208         assert value >= min && value <= max;
3209         int range = max - min + 1;
3210         amount %= range;
3211         int n = value + amount;
3212         if (n > max) {
3213             n -= range;
3214         } else if (n < min) {
3215             n += range;
3216         }
3217         assert n >= min && n <= max;
3218         return n;
3219     }
3220 
3221     /**
3222      * Returns the ERA.  We need a special method for this because the
3223      * default ERA is CE, but a zero (unset) ERA is BCE.
3224      */
3225     private int internalGetEra() {
3226         return isSet(ERA) ? internalGet(ERA) : CE;
3227     }
3228 
3229     /**
3230      * Updates internal state.
3231      */
3232     private void readObject(ObjectInputStream stream)
3233             throws IOException, ClassNotFoundException {
3234         stream.defaultReadObject();
3235         if (gdate == null) {
3236             gdate = (BaseCalendar.Date) gcal.newCalendarDate(getZone());
3237             cachedFixedDate = Long.MIN_VALUE;
3238         }
3239         setGregorianChange(gregorianCutover);
3240     }
3241 
3242     /**
3243      * Converts this object to a {@code ZonedDateTime} that represents
3244      * the same point on the time-line as this {@code GregorianCalendar}.
3245      * <p>
3246      * Since this object supports a Julian-Gregorian cutover date and
3247      * {@code ZonedDateTime} does not, it is possible that the resulting year,
3248      * month and day will have different values.  The result will represent the
3249      * correct date in the ISO calendar system, which will also be the same value
3250      * for Modified Julian Days.
3251      *
3252      * @return a zoned date-time representing the same point on the time-line
3253      *  as this gregorian calendar
3254      * @since 1.8
3255      */
3256     public ZonedDateTime toZonedDateTime() {
3257         return ZonedDateTime.ofInstant(Instant.ofEpochMilli(getTimeInMillis()),
3258                                        getTimeZone().toZoneId());
3259     }
3260 
3261     /**
3262      * Obtains an instance of {@code GregorianCalendar} with the default locale
3263      * from a {@code ZonedDateTime} object.
3264      * <p>
3265      * Since {@code ZonedDateTime} does not support a Julian-Gregorian cutover
3266      * date and uses ISO calendar system, the return GregorianCalendar is a pure
3267      * Gregorian calendar and uses ISO 8601 standard for week definitions,
3268      * which has {@code MONDAY} as the {@link Calendar#getFirstDayOfWeek()
3269      * FirstDayOfWeek} and {@code 4} as the value of the
3270      * {@link Calendar#getMinimalDaysInFirstWeek() MinimalDaysInFirstWeek}.
3271      * <p>
3272      * {@code ZoneDateTime} can store points on the time-line further in the
3273      * future and further in the past than {@code GregorianCalendar}. In this
3274      * scenario, this method will throw an {@code IllegalArgumentException}
3275      * exception.
3276      *
3277      * @param zdt  the zoned date-time object to convert
3278      * @return  the gregorian calendar representing the same point on the
3279      *  time-line as the zoned date-time provided
3280      * @exception NullPointerException if {@code zdt} is null
3281      * @exception IllegalArgumentException if the zoned date-time is too
3282      * large to represent as a {@code GregorianCalendar}
3283      * @since 1.8
3284      */
3285     public static GregorianCalendar from(ZonedDateTime zdt) {
3286         GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone(zdt.getZone()));
3287         cal.setGregorianChange(new Date(Long.MIN_VALUE));
3288         cal.setFirstDayOfWeek(MONDAY);
3289         cal.setMinimalDaysInFirstWeek(4);
3290         try {
3291             cal.setTimeInMillis(Math.addExact(Math.multiplyExact(zdt.toEpochSecond(), 1000),
3292                                               zdt.get(ChronoField.MILLI_OF_SECOND)));
3293         } catch (ArithmeticException ex) {
3294             throw new IllegalArgumentException(ex);
3295         }
3296         return cal;
3297     }
3298 }