GregorianCalendar.java revision 18aa2ce5993b2f06e1d4d60c90d92fe4650b1d75
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.util;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectInputStream;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectOutputStream;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code GregorianCalendar} is a concrete subclass of {@link Calendar}
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and provides the standard calendar used by most of the world.
27f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The standard (Gregorian) calendar has 2 eras, BC and AD.
30f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This implementation handles a single discontinuity, which corresponds by
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * default to the date the Gregorian calendar was instituted (October 15, 1582
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * in some countries, later in others). The cutover date may be changed by the
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * caller by calling {@code setGregorianChange()}.
36f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Historically, in those countries which adopted the Gregorian calendar first,
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * October 4, 1582 was thus followed by October 15, 1582. This calendar models
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this correctly. Before the Gregorian cutover, {@code GregorianCalendar}
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * implements the Julian calendar. The only difference between the Gregorian and
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the Julian calendar is the leap year rule. The Julian calendar specifies leap
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * years every four years, whereas the Gregorian calendar omits century years
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * which are not divisible by 400.
45f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code GregorianCalendar} implements <em>proleptic</em> Gregorian
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and Julian calendars. That is, dates are computed by extrapolating the
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * current rules indefinitely far backward and forward in time. As a result,
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code GregorianCalendar} may be used for all years to generate
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * meaningful and consistent results. However, dates obtained using
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code GregorianCalendar} are historically accurate only from March 1,
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 4 AD onward, when modern Julian calendar rules were adopted. Before this
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * date, leap year rules were applied irregularly, and before 45 BC the Julian
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * calendar did not even exist.
56f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Prior to the institution of the Gregorian calendar, New Year's Day was March
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 25. To avoid confusion, this calendar always uses January 1. A manual
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * adjustment may be made if desired for dates that are prior to the Gregorian
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * changeover and which fall between January 1 and March 24.
62f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Values calculated for the {@code WEEK_OF_YEAR} field range from 1 to
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 53. Week 1 for a year is the earliest seven day period starting on
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code getFirstDayOfWeek()} that contains at least
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code getMinimalDaysInFirstWeek()} days from that year. It thus
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * depends on the values of {@code getMinimalDaysInFirstWeek()},
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code getFirstDayOfWeek()}, and the day of the week of January 1.
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Weeks between week 1 of one year and week 1 of the following year are
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * numbered sequentially from 2 to 52 or 53 (as needed).
72f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * For example, January 1, 1998 was a Thursday. If
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code getFirstDayOfWeek()} is {@code MONDAY} and
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code getMinimalDaysInFirstWeek()} is 4 (these are the values
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reflecting ISO 8601 and many national standards), then week 1 of 1998 starts
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * on December 29, 1997, and ends on January 4, 1998. If, however,
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code getFirstDayOfWeek()} is {@code SUNDAY}, then week 1 of
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 1998 starts on January 4, 1998, and ends on January 10, 1998; the first three
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * days of 1998 then are part of week 53 of 1997.
82f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Values calculated for the {@code WEEK_OF_MONTH} field range from 0 or
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 1 to 4 or 5. Week 1 of a month (the days with <code>WEEK_OF_MONTH =
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 1</code>)
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * is the earliest set of at least {@code getMinimalDaysInFirstWeek()}
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contiguous days in that month, ending on the day before
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code getFirstDayOfWeek()}. Unlike week 1 of a year, week 1 of a
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * month may be shorter than 7 days, need not start on
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code getFirstDayOfWeek()}, and will not include days of the
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * previous month. Days of a month before week 1 have a
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code WEEK_OF_MONTH} of 0.
94f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * For example, if {@code getFirstDayOfWeek()} is {@code SUNDAY}
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and {@code getMinimalDaysInFirstWeek()} is 4, then the first week of
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * January 1998 is Sunday, January 4 through Saturday, January 10. These days
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * have a {@code WEEK_OF_MONTH} of 1. Thursday, January 1 through
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Saturday, January 3 have a {@code WEEK_OF_MONTH} of 0. If
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code getMinimalDaysInFirstWeek()} is changed to 3, then January 1
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * through January 3 have a {@code WEEK_OF_MONTH} of 1.
103f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <strong>Example:</strong> <blockquote>
106f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <pre>
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * // get the supported ids for GMT-08:00 (Pacific Standard Time)
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * // if no ids were returned, something is wrong. get out.
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if (ids.length == 0)
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     System.exit(0);
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  // begin output
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("Current Time");
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * // create a Pacific Standard Time time zone
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * // set up rules for daylight savings time
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * // create a GregorianCalendar with the Pacific Daylight time zone
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * // and the current date and time
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Calendar calendar = new GregorianCalendar(pdt);
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Date trialTime = new Date();
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * calendar.setTime(trialTime);
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * // print out a bunch of interesting things
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("ERA: " + calendar.get(Calendar.ERA));
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("YEAR: " + calendar.get(Calendar.YEAR));
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("MONTH: " + calendar.get(Calendar.MONTH));
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("WEEK_OF_YEAR: " + calendar.get(Calendar.WEEK_OF_YEAR));
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("WEEK_OF_MONTH: " + calendar.get(Calendar.WEEK_OF_MONTH));
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("DATE: " + calendar.get(Calendar.DATE));
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("DAY_OF_MONTH: " + calendar.get(Calendar.DAY_OF_MONTH));
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("DAY_OF_YEAR: " + calendar.get(Calendar.DAY_OF_YEAR));
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("DAY_OF_WEEK: " + calendar.get(Calendar.DAY_OF_WEEK));
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("DAY_OF_WEEK_IN_MONTH: "
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *                    + calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("AM_PM: " + calendar.get(Calendar.AM_PM));
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("HOUR: " + calendar.get(Calendar.HOUR));
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("HOUR_OF_DAY: " + calendar.get(Calendar.HOUR_OF_DAY));
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("MINUTE: " + calendar.get(Calendar.MINUTE));
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("SECOND: " + calendar.get(Calendar.SECOND));
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("MILLISECOND: " + calendar.get(Calendar.MILLISECOND));
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("ZONE_OFFSET: "
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *                    + (calendar.get(Calendar.ZONE_OFFSET)/(60*60*1000)));
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("DST_OFFSET: "
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *                    + (calendar.get(Calendar.DST_OFFSET)/(60*60*1000)));
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("Current Time, with hour reset to 3");
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * calendar.clear(Calendar.HOUR_OF_DAY); // so doesn't override
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * calendar.set(Calendar.HOUR, 3);
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("ERA: " + calendar.get(Calendar.ERA));
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("YEAR: " + calendar.get(Calendar.YEAR));
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("MONTH: " + calendar.get(Calendar.MONTH));
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("WEEK_OF_YEAR: " + calendar.get(Calendar.WEEK_OF_YEAR));
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("WEEK_OF_MONTH: " + calendar.get(Calendar.WEEK_OF_MONTH));
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("DATE: " + calendar.get(Calendar.DATE));
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("DAY_OF_MONTH: " + calendar.get(Calendar.DAY_OF_MONTH));
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("DAY_OF_YEAR: " + calendar.get(Calendar.DAY_OF_YEAR));
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("DAY_OF_WEEK: " + calendar.get(Calendar.DAY_OF_WEEK));
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("DAY_OF_WEEK_IN_MONTH: "
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *                    + calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("AM_PM: " + calendar.get(Calendar.AM_PM));
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("HOUR: " + calendar.get(Calendar.HOUR));
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("HOUR_OF_DAY: " + calendar.get(Calendar.HOUR_OF_DAY));
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("MINUTE: " + calendar.get(Calendar.MINUTE));
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("SECOND: " + calendar.get(Calendar.SECOND));
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("MILLISECOND: " + calendar.get(Calendar.MILLISECOND));
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("ZONE_OFFSET: "
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        + (calendar.get(Calendar.ZONE_OFFSET)/(60*60*1000))); // in hours
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * System.out.println("DST_OFFSET: "
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        + (calendar.get(Calendar.DST_OFFSET)/(60*60*1000))); // in hours
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </pre>
178f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </blockquote>
180f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see Calendar
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see TimeZone
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class GregorianCalendar extends Calendar {
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long serialVersionUID = -8125100834729963327L;
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Value for the BC era.
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int BC = 0;
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Value for the AD era.
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int AD = 1;
197f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long defaultGregorianCutover = -12219292800000l;
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private long gregorianCutover = defaultGregorianCutover;
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient int changeYear = 1582;
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient int julianSkew = ((changeYear - 2000) / 400)
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            + julianError() - ((changeYear - 2000) / 100);
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static byte[] DaysInMonth = new byte[] { 31, 28, 31, 30, 31, 30, 31, 31,
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            30, 31, 30, 31 };
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static int[] DaysInYear = new int[] { 0, 31, 59, 90, 120, 151, 181,
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            212, 243, 273, 304, 334 };
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static int[] maximums = new int[] { 1, 292278994, 11, 53, 6, 31,
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            366, 7, 6, 1, 11, 23, 59, 59, 999, 14 * 3600 * 1000, 7200000 };
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static int[] minimums = new int[] { 0, 1, 0, 1, 0, 1, 1, 1, 1, 0,
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            0, 0, 0, 0, 0, -13 * 3600 * 1000, 0 };
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static int[] leastMaximums = new int[] { 1, 292269054, 11, 50, 3,
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            28, 355, 7, 3, 1, 11, 23, 59, 59, 999, 50400000, 1200000 };
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean isCached;
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int cachedFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private long nextMidnightMillis = 0L;
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private long lastMidnightMillis = 0L;
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int currentYearSkew = 10;
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int lastYearSkew = 0;
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to the current date and
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * time with the default {@code Locale} and {@code TimeZone}.
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar() {
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this(TimeZone.getDefault(), Locale.getDefault());
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to midnight in the default
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code TimeZone} and {@code Locale} on the specified date.
245f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param year
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the year.
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param month
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the month.
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param day
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the day of the month.
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar(int year, int month, int day) {
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(TimeZone.getDefault(), Locale.getDefault());
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        set(year, month, day);
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to the specified date and
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * time in the default {@code TimeZone} and {@code Locale}.
261f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param year
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the year.
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param month
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the month.
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param day
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the day of the month.
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param hour
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the hour.
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param minute
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the minute.
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar(int year, int month, int day, int hour, int minute) {
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(TimeZone.getDefault(), Locale.getDefault());
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        set(year, month, day, hour, minute);
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to the specified date and
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * time in the default {@code TimeZone} and {@code Locale}.
281f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param year
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the year.
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param month
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the month.
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param day
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the day of the month.
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param hour
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the hour.
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param minute
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the minute.
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param second
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the second.
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar(int year, int month, int day, int hour,
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int minute, int second) {
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(TimeZone.getDefault(), Locale.getDefault());
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        set(year, month, day, hour, minute, second);
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    GregorianCalendar(long milliseconds) {
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this(false);
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setTimeInMillis(milliseconds);
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to the current date and
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * time and using the specified {@code Locale} and the default {@code TimeZone}.
309f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param locale
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Locale}.
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar(Locale locale) {
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this(TimeZone.getDefault(), locale);
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to the current date and
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * time and using the specified {@code TimeZone} and the default {@code Locale}.
320f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param timezone
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code TimeZone}.
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar(TimeZone timezone) {
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this(timezone, Locale.getDefault());
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to the current date and
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * time and using the specified {@code TimeZone} and {@code Locale}.
331f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param timezone
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code TimeZone}.
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param locale
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Locale}.
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar(TimeZone timezone, Locale locale) {
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(timezone, locale);
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setTimeInMillis(System.currentTimeMillis());
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    GregorianCalendar(boolean ignored) {
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(TimeZone.getDefault());
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setFirstDayOfWeek(SUNDAY);
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setMinimalDaysInFirstWeek(1);
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Adds the specified amount to a {@code Calendar} field.
350f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Calendar} field to modify.
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param value
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the amount to add to the field.
355f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
356f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @throws IllegalArgumentException
357f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *                if the specified field is DST_OFFSET or ZONE_OFFSET.
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void add(int field, int value) {
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (value == 0) {
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (field < 0 || field >= ZONE_OFFSET) {
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException();
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (field == ERA) {
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            complete();
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (fields[ERA] == AD) {
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (value >= 0) {
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return;
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(ERA, BC);
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (value <= 0) {
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return;
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(ERA, AD);
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            complete();
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (field == YEAR || field == MONTH) {
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            complete();
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (field == MONTH) {
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int month = fields[MONTH] + value;
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (month < 0) {
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    value = (month - 11) / 12;
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    month = 12 + (month % 12);
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    value = month / 12;
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(MONTH, month % 12);
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            set(YEAR, fields[YEAR] + value);
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int days = daysInMonth(isLeapYear(fields[YEAR]), fields[MONTH]);
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (fields[DATE] > days) {
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(DATE, days);
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            complete();
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long multiplier = 0;
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        getTimeInMillis(); // Update the time
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (field) {
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case MILLISECOND:
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                time += value;
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case SECOND:
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                time += value * 1000L;
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case MINUTE:
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                time += value * 60000L;
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case HOUR:
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case HOUR_OF_DAY:
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                time += value * 3600000L;
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case AM_PM:
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                multiplier = 43200000L;
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DATE:
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DAY_OF_YEAR:
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DAY_OF_WEEK:
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                multiplier = 86400000L;
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_YEAR:
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_MONTH:
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DAY_OF_WEEK_IN_MONTH:
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                multiplier = 604800000L;
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (multiplier > 0) {
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int zoneOffset = getTimeZone().getRawOffset();
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int offset = getOffset(time + zoneOffset);
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            time += value * multiplier;
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int newOffset = getOffset(time + zoneOffset);
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Adjust for moving over a DST boundary
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (newOffset != offset) {
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                time += offset - newOffset;
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        areFieldsSet = false;
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        complete();
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates new instance of {@code GregorianCalendar} with the same properties.
454f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a shallow copy of this {@code GregorianCalendar}.
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Object clone() {
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        GregorianCalendar thisClone = (GregorianCalendar) super.clone();
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        thisClone.cachedFields = cachedFields.clone();
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return thisClone;
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final void fullFieldsCalc(long timeVal, int millis, int zoneOffset) {
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long days = timeVal / 86400000;
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (millis < 0) {
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += 86400000;
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days--;
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Cannot add ZONE_OFFSET to time as it might overflow
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        millis += zoneOffset;
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (millis < 0) {
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += 86400000;
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days--;
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (millis >= 86400000) {
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis -= 86400000;
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days++;
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dayOfYear = computeYearAndDay(days, timeVal + zoneOffset);
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DAY_OF_YEAR] = dayOfYear;
484f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        if(fields[YEAR] == changeYear && gregorianCutover <= timeVal + zoneOffset){
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            dayOfYear += currentYearSkew;
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int month = dayOfYear / 32;
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean leapYear = isLeapYear(fields[YEAR]);
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int date = dayOfYear - daysInYear(leapYear, month);
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (date > daysInMonth(leapYear, month)) {
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            date -= daysInMonth(leapYear, month);
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            month++;
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DAY_OF_WEEK] = mod7(days - 3) + 1;
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dstOffset = fields[YEAR] <= 0 ? 0 : getTimeZone().getOffset(AD,
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fields[YEAR], month, date, fields[DAY_OF_WEEK], millis);
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (fields[YEAR] > 0) {
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            dstOffset -= zoneOffset;
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DST_OFFSET] = dstOffset;
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (dstOffset != 0) {
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long oldDays = days;
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += dstOffset;
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (millis < 0) {
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis += 86400000;
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days--;
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (millis >= 86400000) {
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis -= 86400000;
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days++;
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (oldDays != days) {
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                dayOfYear = computeYearAndDay(days, timeVal - zoneOffset
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        + dstOffset);
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fields[DAY_OF_YEAR] = dayOfYear;
515f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if(fields[YEAR] == changeYear && gregorianCutover <= timeVal - zoneOffset + dstOffset){
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfYear += currentYearSkew;
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                month = dayOfYear / 32;
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                leapYear = isLeapYear(fields[YEAR]);
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                date = dayOfYear - daysInYear(leapYear, month);
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (date > daysInMonth(leapYear, month)) {
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    date -= daysInMonth(leapYear, month);
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    month++;
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fields[DAY_OF_WEEK] = mod7(days - 3) + 1;
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[MILLISECOND] = (millis % 1000);
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        millis /= 1000;
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[SECOND] = (millis % 60);
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        millis /= 60;
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[MINUTE] = (millis % 60);
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        millis /= 60;
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[HOUR_OF_DAY] = (millis % 24);
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[AM_PM] = fields[HOUR_OF_DAY] > 11 ? 1 : 0;
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[HOUR] = fields[HOUR_OF_DAY] % 12;
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (fields[YEAR] <= 0) {
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[ERA] = BC;
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[YEAR] = -fields[YEAR] + 1;
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[ERA] = AD;
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[MONTH] = month;
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DATE] = date;
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DAY_OF_WEEK_IN_MONTH] = (date - 1) / 7 + 1;
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[WEEK_OF_MONTH] = (date - 1 + mod7(days - date - 2
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - (getFirstDayOfWeek() - 1))) / 7 + 1;
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int daysFromStart = mod7(days - 3 - (fields[DAY_OF_YEAR] - 1)
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - (getFirstDayOfWeek() - 1));
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int week = (fields[DAY_OF_YEAR] - 1 + daysFromStart) / 7
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                + (7 - daysFromStart >= getMinimalDaysInFirstWeek() ? 1 : 0);
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (week == 0) {
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_YEAR] = 7 - mod7(daysFromStart
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    - (isLeapYear(fields[YEAR] - 1) ? 2 : 1)) >= getMinimalDaysInFirstWeek() ? 53
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    : 52;
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (fields[DAY_OF_YEAR] >= (leapYear ? 367 : 366)
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - mod7(daysFromStart + (leapYear ? 2 : 1))) {
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_YEAR] = 7 - mod7(daysFromStart + (leapYear ? 2 : 1)) >= getMinimalDaysInFirstWeek() ? 1
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    : week;
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_YEAR] = week;
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final void cachedFieldsCheckAndGet(long timeVal,
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long newTimeMillis, long newTimeMillisAdjusted, int millis,
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int zoneOffset) {
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dstOffset = fields[DST_OFFSET];
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isCached
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || newTimeMillis >= nextMidnightMillis
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || newTimeMillis <= lastMidnightMillis
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || cachedFields[4] != zoneOffset
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || (dstOffset == 0 && (newTimeMillisAdjusted >= nextMidnightMillis))
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || (dstOffset != 0 && (newTimeMillisAdjusted <= lastMidnightMillis))) {
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fullFieldsCalc(timeVal, millis, zoneOffset);
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isCached = false;
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[YEAR] = cachedFields[0];
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[MONTH] = cachedFields[1];
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[DATE] = cachedFields[2];
583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[DAY_OF_WEEK] = cachedFields[3];
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[ERA] = cachedFields[5];
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_YEAR] = cachedFields[6];
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_MONTH] = cachedFields[7];
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[DAY_OF_YEAR] = cachedFields[8];
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[DAY_OF_WEEK_IN_MONTH] = cachedFields[9];
589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void computeFields() {
59469bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        TimeZone timeZone = getTimeZone();
59569bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        int dstOffset = timeZone.inDaylightTime(new Date(time)) ? timeZone.getDSTSavings() : 0;
59669bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        int zoneOffset = timeZone.getRawOffset();
59769bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        fields[DST_OFFSET] = dstOffset;
59869bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        fields[ZONE_OFFSET] = zoneOffset;
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int millis = (int) (time % 86400000);
601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int savedMillis = millis;
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // compute without a change in daylight saving time
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int offset = zoneOffset + dstOffset;
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long newTime = time + offset;
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (time > 0L && newTime < 0L && offset > 0) {
607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            newTime = 0x7fffffffffffffffL;
608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (time < 0L && newTime > 0L && offset < 0) {
609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            newTime = 0x8000000000000000L;
610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
61269bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        // FIXME: I don't think this caching ever really gets used, because it requires that the
61369bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        // time zone doesn't use daylight savings (ever). So unless you're somewhere like Taiwan...
614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isCached) {
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (millis < 0) {
616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis += 86400000;
617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Cannot add ZONE_OFFSET to time as it might overflow
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += zoneOffset;
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += dstOffset;
622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (millis < 0) {
624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis += 86400000;
625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (millis >= 86400000) {
626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis -= 86400000;
627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[MILLISECOND] = (millis % 1000);
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis /= 1000;
631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[SECOND] = (millis % 60);
632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis /= 60;
633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[MINUTE] = (millis % 60);
634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis /= 60;
635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[HOUR_OF_DAY] = (millis % 24);
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis /= 24;
637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[AM_PM] = fields[HOUR_OF_DAY] > 11 ? 1 : 0;
638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[HOUR] = fields[HOUR_OF_DAY] % 12;
639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
64069bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes            // FIXME: this has to be wrong; useDaylightTime doesn't mean what they think it means!
641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long newTimeAdjusted = newTime;
64269bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes            if (timeZone.useDaylightTime()) {
643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // BEGIN android-changed: removed unnecessary cast
64469bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes                int dstSavings = timeZone.getDSTSavings();
645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // END android-changed
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                newTimeAdjusted += (dstOffset == 0) ? dstSavings : -dstSavings;
647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (newTime > 0L && newTimeAdjusted < 0L && dstOffset == 0) {
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                newTimeAdjusted = 0x7fffffffffffffffL;
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (newTime < 0L && newTimeAdjusted > 0L && dstOffset != 0) {
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                newTimeAdjusted = 0x8000000000000000L;
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFieldsCheckAndGet(time, newTime, newTimeAdjusted,
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    savedMillis, zoneOffset);
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fullFieldsCalc(time, savedMillis, zoneOffset);
659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0; i < FIELD_COUNT; i++) {
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isSet[i] = true;
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Caching
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isCached
667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && newTime != 0x7fffffffffffffffL
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && newTime != 0x8000000000000000L
66969bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes                && (!timeZone.useDaylightTime() || timeZone instanceof SimpleTimeZone)) {
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int cacheMillis = 0;
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[0] = fields[YEAR];
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[1] = fields[MONTH];
674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[2] = fields[DATE];
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[3] = fields[DAY_OF_WEEK];
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[4] = zoneOffset;
677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[5] = fields[ERA];
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[6] = fields[WEEK_OF_YEAR];
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[7] = fields[WEEK_OF_MONTH];
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[8] = fields[DAY_OF_YEAR];
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[9] = fields[DAY_OF_WEEK_IN_MONTH];
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cacheMillis += (23 - fields[HOUR_OF_DAY]) * 60 * 60 * 1000;
684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cacheMillis += (59 - fields[MINUTE]) * 60 * 1000;
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cacheMillis += (59 - fields[SECOND]) * 1000;
686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nextMidnightMillis = newTime + cacheMillis;
687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cacheMillis = fields[HOUR_OF_DAY] * 60 * 60 * 1000;
689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cacheMillis += fields[MINUTE] * 60 * 1000;
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cacheMillis += fields[SECOND] * 1000;
691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            lastMidnightMillis = newTime - cacheMillis;
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isCached = true;
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void computeTime() {
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isLenient()) {
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[HOUR_OF_DAY]) {
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (fields[HOUR_OF_DAY] < 0 || fields[HOUR_OF_DAY] > 23) {
702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11)) {
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[MINUTE] && (fields[MINUTE] < 0 || fields[MINUTE] > 59)) {
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[SECOND] && (fields[SECOND] < 0 || fields[SECOND] > 59)) {
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[MILLISECOND]
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[MILLISECOND] < 0 || fields[MILLISECOND] > 999)) {
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[WEEK_OF_YEAR]
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[WEEK_OF_YEAR] < 1 || fields[WEEK_OF_YEAR] > 53)) {
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[DAY_OF_WEEK]
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[DAY_OF_WEEK] < 1 || fields[DAY_OF_WEEK] > 7)) {
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[DAY_OF_WEEK_IN_MONTH]
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[DAY_OF_WEEK_IN_MONTH] < 1 || fields[DAY_OF_WEEK_IN_MONTH] > 6)) {
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[WEEK_OF_MONTH]
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[WEEK_OF_MONTH] < 1 || fields[WEEK_OF_MONTH] > 6)) {
731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[AM_PM] && fields[AM_PM] != AM && fields[AM_PM] != PM) {
734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11)) {
737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[YEAR]) {
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSet[ERA] && fields[ERA] == BC
741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && (fields[YEAR] < 1 || fields[YEAR] > 292269054)) {
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (fields[YEAR] < 1 || fields[YEAR] > 292278994) {
744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[MONTH] && (fields[MONTH] < 0 || fields[MONTH] > 11)) {
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long timeVal;
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long hour = 0;
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[HOUR_OF_DAY] && lastTimeFieldSet != HOUR) {
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            hour = fields[HOUR_OF_DAY];
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (isSet[HOUR]) {
757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            hour = (fields[AM_PM] * 12) + fields[HOUR];
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        timeVal = hour * 3600000;
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[MINUTE]) {
762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            timeVal += ((long) fields[MINUTE]) * 60000;
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[SECOND]) {
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            timeVal += ((long) fields[SECOND]) * 1000;
766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[MILLISECOND]) {
768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            timeVal += fields[MILLISECOND];
769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long days;
772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int year = isSet[YEAR] ? fields[YEAR] : 1970;
773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[ERA]) {
774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Always test for valid ERA, even if the Calendar is lenient
775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (fields[ERA] != BC && fields[ERA] != AD) {
776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (fields[ERA] == BC) {
779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                year = 1 - year;
780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean weekMonthSet = isSet[WEEK_OF_MONTH]
784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || isSet[DAY_OF_WEEK_IN_MONTH];
785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean useMonth = (isSet[DATE] || isSet[MONTH] || weekMonthSet)
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && lastDateFieldSet != DAY_OF_YEAR;
787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (useMonth
788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && (lastDateFieldSet == DAY_OF_WEEK || lastDateFieldSet == WEEK_OF_YEAR)) {
789adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[WEEK_OF_YEAR] && isSet[DAY_OF_WEEK]) {
790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                useMonth = lastDateFieldSet != WEEK_OF_YEAR && weekMonthSet
791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && isSet[DAY_OF_WEEK];
792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (isSet[DAY_OF_YEAR]) {
793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                useMonth = isSet[DATE] && isSet[MONTH];
794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (useMonth) {
798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int month = fields[MONTH];
799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year += month / 12;
800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            month %= 12;
801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (month < 0) {
802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                year--;
803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                month += 12;
804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean leapYear = isLeapYear(year);
806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = daysFromBaseYear(year) + daysInYear(leapYear, month);
807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean useDate = isSet[DATE];
808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (useDate
809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (lastDateFieldSet == DAY_OF_WEEK
810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || lastDateFieldSet == WEEK_OF_MONTH || lastDateFieldSet == DAY_OF_WEEK_IN_MONTH)) {
811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                useDate = !(isSet[DAY_OF_WEEK] && weekMonthSet);
812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (useDate) {
814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!isLenient()
815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && (fields[DATE] < 1 || fields[DATE] > daysInMonth(
816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                leapYear, month))) {
817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days += fields[DATE] - 1;
820adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int dayOfWeek;
822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSet[DAY_OF_WEEK]) {
823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfWeek = fields[DAY_OF_WEEK] - 1;
824adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfWeek = getFirstDayOfWeek() - 1;
826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSet[WEEK_OF_MONTH]
828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && lastDateFieldSet != DAY_OF_WEEK_IN_MONTH) {
829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += (fields[WEEK_OF_MONTH] - 1) * 7
831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            + mod7(skew + dayOfWeek - (days - 3)) - skew;
832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (isSet[DAY_OF_WEEK_IN_MONTH]) {
833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (fields[DAY_OF_WEEK_IN_MONTH] >= 0) {
834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        days += mod7(dayOfWeek - (days - 3))
835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                + (fields[DAY_OF_WEEK_IN_MONTH] - 1) * 7;
836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        days += daysInMonth(leapYear, month)
838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                + mod7(dayOfWeek
839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                        - (days + daysInMonth(leapYear, month) - 3))
840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                + fields[DAY_OF_WEEK_IN_MONTH] * 7;
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
842f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                } else if (isSet[DAY_OF_WEEK]) {
843f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
844f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    days += mod7(mod7(skew + dayOfWeek - (days - 3)) - skew);
845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean useWeekYear = isSet[WEEK_OF_YEAR]
849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && lastDateFieldSet != DAY_OF_YEAR;
850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (useWeekYear && isSet[DAY_OF_YEAR]) {
851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                useWeekYear = isSet[DAY_OF_WEEK];
852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = daysFromBaseYear(year);
854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (useWeekYear) {
855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int dayOfWeek;
856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSet[DAY_OF_WEEK]) {
857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfWeek = fields[DAY_OF_WEEK] - 1;
858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
859adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfWeek = getFirstDayOfWeek() - 1;
860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days += (fields[WEEK_OF_YEAR] - 1) * 7
863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        + mod7(skew + dayOfWeek - (days - 3)) - skew;
864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (7 - skew < getMinimalDaysInFirstWeek()) {
865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += 7;
866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (isSet[DAY_OF_YEAR]) {
868adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!isLenient()
869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && (fields[DAY_OF_YEAR] < 1 || fields[DAY_OF_YEAR] > (365 + (isLeapYear(year) ? 1
870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                : 0)))) {
871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days += fields[DAY_OF_YEAR] - 1;
874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (isSet[DAY_OF_WEEK]) {
875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days += mod7(fields[DAY_OF_WEEK] - 1 - (days - 3));
876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        lastDateFieldSet = 0;
879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        timeVal += days * 86400000;
881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Use local time to compare with the gregorian change
882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year == changeYear
883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && timeVal >= gregorianCutover + julianError() * 86400000L) {
884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            timeVal -= julianError() * 86400000L;
885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // It is not possible to simply subtract getOffset(timeVal) from timeVal
888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // to get UTC.
889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // The trick is needed for the moment when DST transition occurs,
890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // say 1:00 is a transition time when DST offset becomes +1 hour,
891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // then wall time in the interval 1:00 - 2:00 is invalid and is
892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // treated as UTC time.
893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long timeValWithoutDST = timeVal - getOffset(timeVal)
894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                + getTimeZone().getRawOffset();
895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        timeVal -= getOffset(timeValWithoutDST);
896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Need to update wall time in fields, since it was invalid due to DST
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // transition
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.time = timeVal;
899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (timeValWithoutDST != timeVal) {
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            computeFields();
901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            areFieldsSet = true;
902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int computeYearAndDay(long dayCount, long localTime) {
906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int year = 1970;
907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long days = dayCount;
908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (localTime < gregorianCutover) {
909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days -= julianSkew;
910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int approxYears;
912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while ((approxYears = (int) (days / 365)) != 0) {
914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year = year + approxYears;
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = dayCount - daysFromBaseYear(year);
916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (days < 0) {
918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year = year - 1;
919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = days + daysInYear(year);
920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[YEAR] = year;
922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (int) days + 1;
923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private long daysFromBaseYear(int iyear) {
926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long year = iyear;
927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year >= 1970) {
929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long days = (year - 1970) * 365 + ((year - 1969) / 4);
930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (year > changeYear) {
931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days -= ((year - 1901) / 100) - ((year - 1601) / 400);
932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if(year == changeYear){
934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += currentYearSkew;
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }else if(year == changeYear -1){
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += lastYearSkew;
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }else{
938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += julianSkew;
939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return days;
942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (year <= changeYear) {
943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return (year - 1970) * 365 + ((year - 1972) / 4) + julianSkew;
944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (year - 1970) * 365 + ((year - 1972) / 4)
946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - ((year - 2000) / 100) + ((year - 2000) / 400);
947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
948f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int daysInMonth() {
950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return daysInMonth(isLeapYear(fields[YEAR]), fields[MONTH]);
951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int daysInMonth(boolean leapYear, int month) {
954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (leapYear && month == FEBRUARY) {
955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return DaysInMonth[month] + 1;
956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return DaysInMonth[month];
959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
960adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
961adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int daysInYear(int year) {
962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int daysInYear = isLeapYear(year) ? 366 : 365;
963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year == changeYear) {
964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            daysInYear -= currentYearSkew;
965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
966adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year == changeYear - 1) {
967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            daysInYear -= lastYearSkew;
968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return daysInYear;
970adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
971adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int daysInYear(boolean leapYear, int month) {
973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (leapYear && month > FEBRUARY) {
974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return DaysInYear[month] + 1;
975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
976adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return DaysInYear[month];
978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
980adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Compares the specified {@code Object} to this {@code GregorianCalendar} and returns whether
982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * they are equal. To be equal, the {@code Object} must be an instance of {@code GregorianCalendar} and
983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * have the same properties.
984f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
985adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param object
986adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Object} to compare with this {@code GregorianCalendar}.
987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if {@code object} is equal to this
988adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code GregorianCalendar}, {@code false} otherwise.
989f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @throws IllegalArgumentException
990f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *                if the time is not set and the time cannot be computed
991adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *                from the current field values.
992adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #hashCode
993adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
994adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
995adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean equals(Object object) {
996adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.equals(object)
997adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && gregorianCutover == ((GregorianCalendar) object).gregorianCutover;
998adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
999adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1000adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1001adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the maximum value of the specified field for the current date. For
1002adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * example, the maximum number of days in the current month.
1003f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1004adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1005adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
1006adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the maximum value of the specified field.
1007adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1008adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1009adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getActualMaximum(int field) {
1010adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int value;
1011adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((value = maximums[field]) == leastMaximums[field]) {
1012adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return value;
1013adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1014adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1015adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (field) {
1016adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_YEAR:
1017adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_MONTH:
1018adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                isCached = false;
1019adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
1020adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1021adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1022adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        complete();
1023adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long orgTime = time;
1024adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int result = 0;
1025adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (field) {
1026adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_YEAR:
1027adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(DATE, 31);
1028adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(MONTH, DECEMBER);
1029adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = get(WEEK_OF_YEAR);
1030adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (result == 1) {
1031adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    set(DATE, 31 - 7);
1032adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = get(WEEK_OF_YEAR);
1033adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1034adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                areFieldsSet = false;
1035adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
1036adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_MONTH:
1037adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(DATE, daysInMonth());
1038adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = get(WEEK_OF_MONTH);
1039adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                areFieldsSet = false;
1040adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
1041adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DATE:
1042adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return daysInMonth();
1043adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DAY_OF_YEAR:
1044adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return daysInYear(fields[YEAR]);
1045adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DAY_OF_WEEK_IN_MONTH:
1046adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = get(DAY_OF_WEEK_IN_MONTH)
1047adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        + ((daysInMonth() - get(DATE)) / 7);
1048adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
1049adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case YEAR:
1050adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                GregorianCalendar clone = (GregorianCalendar) clone();
1051adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (get(ERA) == AD) {
1052adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    clone.setTimeInMillis(Long.MAX_VALUE);
1053adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
1054adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    clone.setTimeInMillis(Long.MIN_VALUE);
1055adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1056adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = clone.get(YEAR);
1057adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                clone.set(YEAR, get(YEAR));
1058adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (clone.before(this)) {
1059adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result--;
1060adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1061adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
1062adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DST_OFFSET:
1063adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = getMaximum(DST_OFFSET);
1064adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
1065adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1066adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        time = orgTime;
1067adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
1068adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1069adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1070adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1071adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the minimum value of the specified field for the current date. For
1072adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the gregorian calendar, this value is the same as
1073adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code getMinimum()}.
1074f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1075adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1076adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
1077adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the minimum value of the specified field.
1078adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1079adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1080adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getActualMinimum(int field) {
1081adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return getMinimum(field);
1082adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1083adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1084adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1085adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the greatest minimum value of the specified field. For the gregorian
1086adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * calendar, this value is the same as {@code getMinimum()}.
1087f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1088adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1089adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
1090adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the greatest minimum value of the specified field.
1091adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1092adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1093adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getGreatestMinimum(int field) {
1094adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return minimums[field];
1095adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1096adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1097adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1098adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the gregorian change date of this calendar. This is the date on
1099adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * which the gregorian calendar came into effect.
1100f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a {@code Date} which represents the gregorian change date.
1102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final Date getGregorianChange() {
1104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new Date(gregorianCutover);
1105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the smallest maximum value of the specified field. For example, 28
1109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for the day of month field.
1110f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
1113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the smallest maximum value of the specified field.
1114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getLeastMaximum(int field) {
1117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // return value for WEEK_OF_YEAR should make corresponding changes when
1118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // the gregorian change date have been reset.
1119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (gregorianCutover != defaultGregorianCutover
1120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && field == WEEK_OF_YEAR) {
1121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long currentTimeInMillis = time;
1122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            setTimeInMillis(gregorianCutover);
1123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int actual = getActualMaximum(field);
1124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            setTimeInMillis(currentTimeInMillis);
1125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return actual;
1126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return leastMaximums[field];
1128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the greatest maximum value of the specified field. For example, 31
1132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for the day of month field.
1133f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
1136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the greatest maximum value of the specified field.
1137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getMaximum(int field) {
1140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return maximums[field];
1141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the smallest minimum value of the specified field.
1145f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
1148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the smallest minimum value of the specified field.
1149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getMinimum(int field) {
1152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return minimums[field];
1153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
115518aa2ce5993b2f06e1d4d60c90d92fe4650b1d75Elliott Hughes    private int getOffset(long localTime) {
1156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        TimeZone timeZone = getTimeZone();
1157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!timeZone.useDaylightTime()) {
1158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return timeZone.getRawOffset();
1159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long dayCount = localTime / 86400000;
1162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int millis = (int) (localTime % 86400000);
1163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (millis < 0) {
1164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += 86400000;
1165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            dayCount--;
1166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int year = 1970;
1169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long days = dayCount;
1170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (localTime < gregorianCutover) {
1171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days -= julianSkew;
1172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int approxYears;
1174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while ((approxYears = (int) (days / 365)) != 0) {
1176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year = year + approxYears;
1177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = dayCount - daysFromBaseYear(year);
1178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (days < 0) {
1180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year = year - 1;
1181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = days + 365 + (isLeapYear(year) ? 1 : 0);
1182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (year == changeYear && localTime < gregorianCutover) {
1183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days -= julianError();
1184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year <= 0) {
1187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return timeZone.getRawOffset();
1188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dayOfYear = (int) days + 1;
1190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int month = dayOfYear / 32;
1192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean leapYear = isLeapYear(year);
1193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int date = dayOfYear - daysInYear(leapYear, month);
1194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (date > daysInMonth(leapYear, month)) {
1195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            date -= daysInMonth(leapYear, month);
1196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            month++;
1197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dayOfWeek = mod7(dayCount - 3) + 1;
1199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int offset = timeZone.getOffset(AD, year, month, date, dayOfWeek,
1200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis);
1201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return offset;
1202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an integer hash code for the receiver. Objects which are equal
1206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * return the same value for this method.
1207f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the receiver's hash.
1209f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #equals
1211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int hashCode() {
1214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.hashCode()
1215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                + ((int) (gregorianCutover >>> 32) ^ (int) gregorianCutover);
1216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether the specified year is a leap year.
1220f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param year
1222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the year.
1223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the specified year is a leap year, {@code false}
1224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         otherwise.
1225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isLeapYear(int year) {
1227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year > changeYear) {
1228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
1229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return year % 4 == 0;
1232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int julianError() {
1235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return changeYear / 100 - changeYear / 400 - 2;
1236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int mod(int value, int mod) {
1239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int rem = value % mod;
1240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (value < 0 && rem < 0) {
1241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return rem + mod;
1242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return rem;
1244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int mod7(long num1) {
1247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int rem = (int) (num1 % 7);
1248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (num1 < 0 && rem < 0) {
1249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return rem + 7;
1250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return rem;
1252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Adds the specified amount the specified field and wraps the value of the
1256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * field when it goes beyond the maximum or minimum value for the current
1257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * date. Other fields will be adjusted as required to maintain a consistent
1258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * date.
1259f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field to roll.
1262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param value
1263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the amount to add.
1264f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1265f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @throws IllegalArgumentException
1266f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *                if an invalid field is specified.
1267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void roll(int field, int value) {
1270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (value == 0) {
1271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
1272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (field < 0 || field >= ZONE_OFFSET) {
1274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException();
1275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
1278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        complete();
1280f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        int days, day, mod, maxWeeks, newWeek;
1281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int max = -1;
1282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (field) {
1283f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case YEAR:
1284f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = maximums[field];
1285f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1286f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case WEEK_OF_YEAR:
1287f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            days = daysInYear(fields[YEAR]);
1288f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            day = DAY_OF_YEAR;
1289f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            mod = mod7(fields[DAY_OF_WEEK] - fields[day]
1290f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    - (getFirstDayOfWeek() - 1));
1291f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            maxWeeks = (days - 1 + mod) / 7 + 1;
1292f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
1293f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (newWeek == maxWeeks) {
1294f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                int addDays = (newWeek - fields[field]) * 7;
1295f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (fields[day] > addDays && fields[day] + addDays > days) {
1296f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, 1);
1297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
1298f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, newWeek - 1);
1299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1300f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else if (newWeek == 1) {
1301f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
1302f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (week > 1) {
1303f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, 1);
1304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
1305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    set(field, newWeek);
1306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1307f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else {
1308f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                set(field, newWeek);
1309f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
1310f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1311f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case WEEK_OF_MONTH:
1312f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            days = daysInMonth();
1313f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            day = DATE;
1314f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            mod = mod7(fields[DAY_OF_WEEK] - fields[day]
1315f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    - (getFirstDayOfWeek() - 1));
1316f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            maxWeeks = (days - 1 + mod) / 7 + 1;
1317f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
1318f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (newWeek == maxWeeks) {
1319f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (fields[day] + (newWeek - fields[field]) * 7 > days) {
1320f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(day, days);
1321f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                } else {
1322f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, newWeek);
1323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1324f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else if (newWeek == 1) {
1325f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
1326f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (week > 1) {
1327f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(day, 1);
1328f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                } else {
1329f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, newWeek);
1330f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                }
1331f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else {
1332f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                set(field, newWeek);
1333f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
1334f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1335f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case DATE:
1336f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = daysInMonth();
1337f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1338f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case DAY_OF_YEAR:
1339f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = daysInYear(fields[YEAR]);
1340f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1341f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case DAY_OF_WEEK:
1342f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = maximums[field];
1343f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            lastDateFieldSet = WEEK_OF_MONTH;
1344f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1345f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case DAY_OF_WEEK_IN_MONTH:
1346f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = (fields[DATE] + ((daysInMonth() - fields[DATE]) / 7 * 7) - 1) / 7 + 1;
1347f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1348f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1349f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case ERA:
1350f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case MONTH:
1351f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case AM_PM:
1352f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case HOUR:
1353f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case HOUR_OF_DAY:
1354f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case MINUTE:
1355f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case SECOND:
1356f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case MILLISECOND:
1357f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            set(field, mod(fields[field] + value, maximums[field] + 1));
1358f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (field == MONTH && fields[DATE] > daysInMonth()) {
1359f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                set(DATE, daysInMonth());
1360f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else if (field == AM_PM) {
1361f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                lastTimeFieldSet = HOUR;
1362f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
1363f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (max != -1) {
1366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            set(field, mod(fields[field] - 1 + value, max) + 1);
1367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        complete();
1369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Increments or decrements the specified field and wraps the value of the
1373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * field when it goes beyond the maximum or minimum value for the current
1374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * date. Other fields will be adjusted as required to maintain a consistent
1375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * date. For example, March 31 will roll to April 30 when rolling the month
1376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * field.
1377f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field to roll.
1380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param increment
1381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            {@code true} to increment the field, {@code false} to
1382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            decrement.
1383f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @throws IllegalArgumentException
1384f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *                if an invalid field is specified.
1385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void roll(int field, boolean increment) {
1388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        roll(field, increment ? 1 : -1);
1389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the gregorian change date of this calendar.
1393f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param date
1395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a {@code Date} which represents the gregorian change date.
1396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setGregorianChange(Date date) {
1398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        gregorianCutover = date.getTime();
1399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        GregorianCalendar cal = new GregorianCalendar(TimeZone.GMT);
1400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        cal.setTime(date);
1401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        changeYear = cal.get(YEAR);
1402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (cal.get(ERA) == BC) {
1403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            changeYear = 1 - changeYear;
1404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        julianSkew = ((changeYear - 2000) / 400) + julianError()
1406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - ((changeYear - 2000) / 100);
1407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
1408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dayOfYear = cal.get(DAY_OF_YEAR);
1409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (dayOfYear < julianSkew) {
1410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            currentYearSkew = dayOfYear-1;
1411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            lastYearSkew = julianSkew - dayOfYear + 1;
1412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
1413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            lastYearSkew = 0;
1414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            currentYearSkew = julianSkew;
1415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
1417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void writeObject(ObjectOutputStream stream) throws IOException {
1420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        stream.defaultWriteObject();
1421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void readObject(ObjectInputStream stream) throws IOException,
1424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ClassNotFoundException {
1425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        stream.defaultReadObject();
1427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setGregorianChange(new Date(gregorianCutover));
1428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
1429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setFirstDayOfWeek(int value) {
1433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super.setFirstDayOfWeek(value);
1434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
1435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setMinimalDaysInFirstWeek(int value) {
1439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super.setMinimalDaysInFirstWeek(value);
1440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
1441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
1443