GregorianCalendar.java revision 996083c82dd18f09ac014d8ad2d40eeec85f6b24
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
224171dc20afe5071d5cbfad7103903bfa2c1f8d00fElliott Hughes    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        }
438996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson
439996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        if (multiplier == 0) {
440996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson            areFieldsSet = false;
441996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson            complete();
442996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson            return;
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
444996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson
445996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        long delta = value * multiplier;
446996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson
447996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        /*
448996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * Attempt to keep the hour and minute constant when we've crossed a DST
449996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * boundary and the user's units are AM_PM or larger. The typical
450996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * consequence is that calls to add(DATE, 1) will add 23, 24 or 25 hours
451996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * depending on whether the DST goes forward, constant, or backward.
452996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         *
453996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * We know we've crossed a DST boundary if the new time will have a
454996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * different timezone offset. Adjust by adding the difference of the two
455996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * offsets. We don't adjust when doing so prevents the change from
456996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * crossing the boundary.
457996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         */
458996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        int zoneOffset = getTimeZone().getRawOffset();
459996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        int offsetBefore = getOffset(time + zoneOffset);
460996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        int offsetAfter = getOffset(time + zoneOffset + delta);
461996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        int dstDelta = offsetBefore - offsetAfter;
462996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        if (getOffset(time + zoneOffset + delta + dstDelta) == offsetAfter) {
463996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson            delta += dstDelta;
464996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        }
465996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson
466996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        time += delta;
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        areFieldsSet = false;
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        complete();
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates new instance of {@code GregorianCalendar} with the same properties.
473f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a shallow copy of this {@code GregorianCalendar}.
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Object clone() {
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        GregorianCalendar thisClone = (GregorianCalendar) super.clone();
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        thisClone.cachedFields = cachedFields.clone();
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return thisClone;
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final void fullFieldsCalc(long timeVal, int millis, int zoneOffset) {
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long days = timeVal / 86400000;
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (millis < 0) {
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += 86400000;
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days--;
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Cannot add ZONE_OFFSET to time as it might overflow
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        millis += zoneOffset;
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (millis < 0) {
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += 86400000;
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days--;
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (millis >= 86400000) {
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis -= 86400000;
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days++;
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dayOfYear = computeYearAndDay(days, timeVal + zoneOffset);
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DAY_OF_YEAR] = dayOfYear;
503f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        if(fields[YEAR] == changeYear && gregorianCutover <= timeVal + zoneOffset){
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            dayOfYear += currentYearSkew;
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int month = dayOfYear / 32;
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean leapYear = isLeapYear(fields[YEAR]);
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int date = dayOfYear - daysInYear(leapYear, month);
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (date > daysInMonth(leapYear, month)) {
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            date -= daysInMonth(leapYear, month);
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            month++;
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DAY_OF_WEEK] = mod7(days - 3) + 1;
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dstOffset = fields[YEAR] <= 0 ? 0 : getTimeZone().getOffset(AD,
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fields[YEAR], month, date, fields[DAY_OF_WEEK], millis);
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (fields[YEAR] > 0) {
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            dstOffset -= zoneOffset;
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DST_OFFSET] = dstOffset;
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (dstOffset != 0) {
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long oldDays = days;
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += dstOffset;
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (millis < 0) {
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis += 86400000;
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days--;
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (millis >= 86400000) {
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis -= 86400000;
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days++;
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (oldDays != days) {
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                dayOfYear = computeYearAndDay(days, timeVal - zoneOffset
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        + dstOffset);
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fields[DAY_OF_YEAR] = dayOfYear;
534f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if(fields[YEAR] == changeYear && gregorianCutover <= timeVal - zoneOffset + dstOffset){
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfYear += currentYearSkew;
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                month = dayOfYear / 32;
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                leapYear = isLeapYear(fields[YEAR]);
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                date = dayOfYear - daysInYear(leapYear, month);
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (date > daysInMonth(leapYear, month)) {
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    date -= daysInMonth(leapYear, month);
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    month++;
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fields[DAY_OF_WEEK] = mod7(days - 3) + 1;
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[MILLISECOND] = (millis % 1000);
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        millis /= 1000;
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[SECOND] = (millis % 60);
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        millis /= 60;
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[MINUTE] = (millis % 60);
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        millis /= 60;
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[HOUR_OF_DAY] = (millis % 24);
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[AM_PM] = fields[HOUR_OF_DAY] > 11 ? 1 : 0;
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[HOUR] = fields[HOUR_OF_DAY] % 12;
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (fields[YEAR] <= 0) {
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[ERA] = BC;
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[YEAR] = -fields[YEAR] + 1;
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[ERA] = AD;
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[MONTH] = month;
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DATE] = date;
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DAY_OF_WEEK_IN_MONTH] = (date - 1) / 7 + 1;
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[WEEK_OF_MONTH] = (date - 1 + mod7(days - date - 2
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - (getFirstDayOfWeek() - 1))) / 7 + 1;
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int daysFromStart = mod7(days - 3 - (fields[DAY_OF_YEAR] - 1)
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - (getFirstDayOfWeek() - 1));
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int week = (fields[DAY_OF_YEAR] - 1 + daysFromStart) / 7
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                + (7 - daysFromStart >= getMinimalDaysInFirstWeek() ? 1 : 0);
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (week == 0) {
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_YEAR] = 7 - mod7(daysFromStart
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    - (isLeapYear(fields[YEAR] - 1) ? 2 : 1)) >= getMinimalDaysInFirstWeek() ? 53
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    : 52;
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (fields[DAY_OF_YEAR] >= (leapYear ? 367 : 366)
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - mod7(daysFromStart + (leapYear ? 2 : 1))) {
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_YEAR] = 7 - mod7(daysFromStart + (leapYear ? 2 : 1)) >= getMinimalDaysInFirstWeek() ? 1
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    : week;
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_YEAR] = week;
583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final void cachedFieldsCheckAndGet(long timeVal,
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long newTimeMillis, long newTimeMillisAdjusted, int millis,
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int zoneOffset) {
589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dstOffset = fields[DST_OFFSET];
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isCached
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || newTimeMillis >= nextMidnightMillis
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || newTimeMillis <= lastMidnightMillis
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || cachedFields[4] != zoneOffset
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || (dstOffset == 0 && (newTimeMillisAdjusted >= nextMidnightMillis))
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || (dstOffset != 0 && (newTimeMillisAdjusted <= lastMidnightMillis))) {
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fullFieldsCalc(timeVal, millis, zoneOffset);
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isCached = false;
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[YEAR] = cachedFields[0];
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[MONTH] = cachedFields[1];
601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[DATE] = cachedFields[2];
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[DAY_OF_WEEK] = cachedFields[3];
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[ERA] = cachedFields[5];
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_YEAR] = cachedFields[6];
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_MONTH] = cachedFields[7];
606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[DAY_OF_YEAR] = cachedFields[8];
607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[DAY_OF_WEEK_IN_MONTH] = cachedFields[9];
608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void computeFields() {
61369bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        TimeZone timeZone = getTimeZone();
61469bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        int dstOffset = timeZone.inDaylightTime(new Date(time)) ? timeZone.getDSTSavings() : 0;
61569bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        int zoneOffset = timeZone.getRawOffset();
61669bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        fields[DST_OFFSET] = dstOffset;
61769bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        fields[ZONE_OFFSET] = zoneOffset;
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int millis = (int) (time % 86400000);
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int savedMillis = millis;
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // compute without a change in daylight saving time
622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int offset = zoneOffset + dstOffset;
623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long newTime = time + offset;
624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (time > 0L && newTime < 0L && offset > 0) {
626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            newTime = 0x7fffffffffffffffL;
627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (time < 0L && newTime > 0L && offset < 0) {
628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            newTime = 0x8000000000000000L;
629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
63169bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        // FIXME: I don't think this caching ever really gets used, because it requires that the
63269bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        // time zone doesn't use daylight savings (ever). So unless you're somewhere like Taiwan...
633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isCached) {
634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (millis < 0) {
635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis += 86400000;
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Cannot add ZONE_OFFSET to time as it might overflow
639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += zoneOffset;
640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += dstOffset;
641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (millis < 0) {
643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis += 86400000;
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (millis >= 86400000) {
645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis -= 86400000;
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[MILLISECOND] = (millis % 1000);
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis /= 1000;
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[SECOND] = (millis % 60);
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis /= 60;
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[MINUTE] = (millis % 60);
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis /= 60;
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[HOUR_OF_DAY] = (millis % 24);
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis /= 24;
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[AM_PM] = fields[HOUR_OF_DAY] > 11 ? 1 : 0;
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[HOUR] = fields[HOUR_OF_DAY] % 12;
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
65969bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes            // FIXME: this has to be wrong; useDaylightTime doesn't mean what they think it means!
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long newTimeAdjusted = newTime;
66169bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes            if (timeZone.useDaylightTime()) {
66269bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes                int dstSavings = timeZone.getDSTSavings();
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                newTimeAdjusted += (dstOffset == 0) ? dstSavings : -dstSavings;
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (newTime > 0L && newTimeAdjusted < 0L && dstOffset == 0) {
667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                newTimeAdjusted = 0x7fffffffffffffffL;
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (newTime < 0L && newTimeAdjusted > 0L && dstOffset != 0) {
669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                newTimeAdjusted = 0x8000000000000000L;
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFieldsCheckAndGet(time, newTime, newTimeAdjusted,
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    savedMillis, zoneOffset);
674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fullFieldsCalc(time, savedMillis, zoneOffset);
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0; i < FIELD_COUNT; i++) {
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isSet[i] = true;
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Caching
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isCached
684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && newTime != 0x7fffffffffffffffL
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && newTime != 0x8000000000000000L
68669bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes                && (!timeZone.useDaylightTime() || timeZone instanceof SimpleTimeZone)) {
687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int cacheMillis = 0;
688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[0] = fields[YEAR];
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[1] = fields[MONTH];
691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[2] = fields[DATE];
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[3] = fields[DAY_OF_WEEK];
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[4] = zoneOffset;
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[5] = fields[ERA];
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[6] = fields[WEEK_OF_YEAR];
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[7] = fields[WEEK_OF_MONTH];
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[8] = fields[DAY_OF_YEAR];
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cachedFields[9] = fields[DAY_OF_WEEK_IN_MONTH];
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cacheMillis += (23 - fields[HOUR_OF_DAY]) * 60 * 60 * 1000;
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cacheMillis += (59 - fields[MINUTE]) * 60 * 1000;
702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cacheMillis += (59 - fields[SECOND]) * 1000;
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nextMidnightMillis = newTime + cacheMillis;
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cacheMillis = fields[HOUR_OF_DAY] * 60 * 60 * 1000;
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cacheMillis += fields[MINUTE] * 60 * 1000;
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cacheMillis += fields[SECOND] * 1000;
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            lastMidnightMillis = newTime - cacheMillis;
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isCached = true;
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void computeTime() {
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isLenient()) {
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[HOUR_OF_DAY]) {
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (fields[HOUR_OF_DAY] < 0 || fields[HOUR_OF_DAY] > 23) {
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11)) {
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[MINUTE] && (fields[MINUTE] < 0 || fields[MINUTE] > 59)) {
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[SECOND] && (fields[SECOND] < 0 || fields[SECOND] > 59)) {
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[MILLISECOND]
731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[MILLISECOND] < 0 || fields[MILLISECOND] > 999)) {
732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[WEEK_OF_YEAR]
735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[WEEK_OF_YEAR] < 1 || fields[WEEK_OF_YEAR] > 53)) {
736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[DAY_OF_WEEK]
739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[DAY_OF_WEEK] < 1 || fields[DAY_OF_WEEK] > 7)) {
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[DAY_OF_WEEK_IN_MONTH]
743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[DAY_OF_WEEK_IN_MONTH] < 1 || fields[DAY_OF_WEEK_IN_MONTH] > 6)) {
744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[WEEK_OF_MONTH]
747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[WEEK_OF_MONTH] < 1 || fields[WEEK_OF_MONTH] > 6)) {
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[AM_PM] && fields[AM_PM] != AM && fields[AM_PM] != PM) {
751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11)) {
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[YEAR]) {
757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSet[ERA] && fields[ERA] == BC
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && (fields[YEAR] < 1 || fields[YEAR] > 292269054)) {
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (fields[YEAR] < 1 || fields[YEAR] > 292278994) {
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[MONTH] && (fields[MONTH] < 0 || fields[MONTH] > 11)) {
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long timeVal;
770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long hour = 0;
771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[HOUR_OF_DAY] && lastTimeFieldSet != HOUR) {
772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            hour = fields[HOUR_OF_DAY];
773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (isSet[HOUR]) {
774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            hour = (fields[AM_PM] * 12) + fields[HOUR];
775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        timeVal = hour * 3600000;
777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[MINUTE]) {
779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            timeVal += ((long) fields[MINUTE]) * 60000;
780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[SECOND]) {
782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            timeVal += ((long) fields[SECOND]) * 1000;
783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[MILLISECOND]) {
785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            timeVal += fields[MILLISECOND];
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long days;
789adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int year = isSet[YEAR] ? fields[YEAR] : 1970;
790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[ERA]) {
791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Always test for valid ERA, even if the Calendar is lenient
792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (fields[ERA] != BC && fields[ERA] != AD) {
793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (fields[ERA] == BC) {
796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                year = 1 - year;
797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean weekMonthSet = isSet[WEEK_OF_MONTH]
801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || isSet[DAY_OF_WEEK_IN_MONTH];
802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean useMonth = (isSet[DATE] || isSet[MONTH] || weekMonthSet)
803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && lastDateFieldSet != DAY_OF_YEAR;
804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (useMonth
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && (lastDateFieldSet == DAY_OF_WEEK || lastDateFieldSet == WEEK_OF_YEAR)) {
806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[WEEK_OF_YEAR] && isSet[DAY_OF_WEEK]) {
807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                useMonth = lastDateFieldSet != WEEK_OF_YEAR && weekMonthSet
808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && isSet[DAY_OF_WEEK];
809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (isSet[DAY_OF_YEAR]) {
810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                useMonth = isSet[DATE] && isSet[MONTH];
811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (useMonth) {
815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int month = fields[MONTH];
816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year += month / 12;
817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            month %= 12;
818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (month < 0) {
819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                year--;
820adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                month += 12;
821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean leapYear = isLeapYear(year);
823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = daysFromBaseYear(year) + daysInYear(leapYear, month);
824adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean useDate = isSet[DATE];
825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (useDate
826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (lastDateFieldSet == DAY_OF_WEEK
827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || lastDateFieldSet == WEEK_OF_MONTH || lastDateFieldSet == DAY_OF_WEEK_IN_MONTH)) {
828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                useDate = !(isSet[DAY_OF_WEEK] && weekMonthSet);
829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (useDate) {
831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!isLenient()
832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && (fields[DATE] < 1 || fields[DATE] > daysInMonth(
833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                leapYear, month))) {
834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days += fields[DATE] - 1;
837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int dayOfWeek;
839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSet[DAY_OF_WEEK]) {
840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfWeek = fields[DAY_OF_WEEK] - 1;
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfWeek = getFirstDayOfWeek() - 1;
843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSet[WEEK_OF_MONTH]
845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && lastDateFieldSet != DAY_OF_WEEK_IN_MONTH) {
846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += (fields[WEEK_OF_MONTH] - 1) * 7
848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            + mod7(skew + dayOfWeek - (days - 3)) - skew;
849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (isSet[DAY_OF_WEEK_IN_MONTH]) {
850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (fields[DAY_OF_WEEK_IN_MONTH] >= 0) {
851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        days += mod7(dayOfWeek - (days - 3))
852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                + (fields[DAY_OF_WEEK_IN_MONTH] - 1) * 7;
853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        days += daysInMonth(leapYear, month)
855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                + mod7(dayOfWeek
856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                        - (days + daysInMonth(leapYear, month) - 3))
857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                + fields[DAY_OF_WEEK_IN_MONTH] * 7;
858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
859f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                } else if (isSet[DAY_OF_WEEK]) {
860f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
861f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    days += mod7(mod7(skew + dayOfWeek - (days - 3)) - skew);
862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean useWeekYear = isSet[WEEK_OF_YEAR]
866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && lastDateFieldSet != DAY_OF_YEAR;
867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (useWeekYear && isSet[DAY_OF_YEAR]) {
868adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                useWeekYear = isSet[DAY_OF_WEEK];
869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = daysFromBaseYear(year);
871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (useWeekYear) {
872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int dayOfWeek;
873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSet[DAY_OF_WEEK]) {
874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfWeek = fields[DAY_OF_WEEK] - 1;
875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfWeek = getFirstDayOfWeek() - 1;
877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days += (fields[WEEK_OF_YEAR] - 1) * 7
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        + mod7(skew + dayOfWeek - (days - 3)) - skew;
881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (7 - skew < getMinimalDaysInFirstWeek()) {
882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += 7;
883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (isSet[DAY_OF_YEAR]) {
885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!isLenient()
886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && (fields[DAY_OF_YEAR] < 1 || fields[DAY_OF_YEAR] > (365 + (isLeapYear(year) ? 1
887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                : 0)))) {
888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days += fields[DAY_OF_YEAR] - 1;
891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (isSet[DAY_OF_WEEK]) {
892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days += mod7(fields[DAY_OF_WEEK] - 1 - (days - 3));
893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        lastDateFieldSet = 0;
896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        timeVal += days * 86400000;
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Use local time to compare with the gregorian change
899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year == changeYear
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && timeVal >= gregorianCutover + julianError() * 86400000L) {
901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            timeVal -= julianError() * 86400000L;
902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // It is not possible to simply subtract getOffset(timeVal) from timeVal
905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // to get UTC.
906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // The trick is needed for the moment when DST transition occurs,
907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // say 1:00 is a transition time when DST offset becomes +1 hour,
908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // then wall time in the interval 1:00 - 2:00 is invalid and is
909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // treated as UTC time.
910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long timeValWithoutDST = timeVal - getOffset(timeVal)
911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                + getTimeZone().getRawOffset();
912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        timeVal -= getOffset(timeValWithoutDST);
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Need to update wall time in fields, since it was invalid due to DST
914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // transition
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.time = timeVal;
916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (timeValWithoutDST != timeVal) {
917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            computeFields();
918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            areFieldsSet = true;
919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int computeYearAndDay(long dayCount, long localTime) {
923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int year = 1970;
924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long days = dayCount;
925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (localTime < gregorianCutover) {
926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days -= julianSkew;
927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int approxYears;
929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while ((approxYears = (int) (days / 365)) != 0) {
931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year = year + approxYears;
932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = dayCount - daysFromBaseYear(year);
933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (days < 0) {
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year = year - 1;
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = days + daysInYear(year);
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[YEAR] = year;
939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (int) days + 1;
940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private long daysFromBaseYear(int iyear) {
943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long year = iyear;
944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year >= 1970) {
946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long days = (year - 1970) * 365 + ((year - 1969) / 4);
947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (year > changeYear) {
948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days -= ((year - 1901) / 100) - ((year - 1601) / 400);
949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if(year == changeYear){
951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += currentYearSkew;
952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }else if(year == changeYear -1){
953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += lastYearSkew;
954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }else{
955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += julianSkew;
956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return days;
959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (year <= changeYear) {
960adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return (year - 1970) * 365 + ((year - 1972) / 4) + julianSkew;
961adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (year - 1970) * 365 + ((year - 1972) / 4)
963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - ((year - 2000) / 100) + ((year - 2000) / 400);
964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
965f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
966adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int daysInMonth() {
967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return daysInMonth(isLeapYear(fields[YEAR]), fields[MONTH]);
968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
970adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int daysInMonth(boolean leapYear, int month) {
971adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (leapYear && month == FEBRUARY) {
972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return DaysInMonth[month] + 1;
973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return DaysInMonth[month];
976adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int daysInYear(int year) {
979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int daysInYear = isLeapYear(year) ? 366 : 365;
980adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year == changeYear) {
981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            daysInYear -= currentYearSkew;
982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year == changeYear - 1) {
984adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            daysInYear -= lastYearSkew;
985adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
986adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return daysInYear;
987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
988adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
989adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int daysInYear(boolean leapYear, int month) {
990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (leapYear && month > FEBRUARY) {
991adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return DaysInYear[month] + 1;
992adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
993adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
994adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return DaysInYear[month];
995adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
996adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
997adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
998adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Compares the specified {@code Object} to this {@code GregorianCalendar} and returns whether
999adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * they are equal. To be equal, the {@code Object} must be an instance of {@code GregorianCalendar} and
1000adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * have the same properties.
1001f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1002adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param object
1003adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Object} to compare with this {@code GregorianCalendar}.
1004adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if {@code object} is equal to this
1005adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code GregorianCalendar}, {@code false} otherwise.
1006f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @throws IllegalArgumentException
1007f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *                if the time is not set and the time cannot be computed
1008adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *                from the current field values.
1009adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #hashCode
1010adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1011adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1012adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean equals(Object object) {
1013deacd761e85ee4d75a6adbdd63225fc4a6d3088dElliott Hughes        if (!(object instanceof GregorianCalendar)) {
1014deacd761e85ee4d75a6adbdd63225fc4a6d3088dElliott Hughes            return false;
1015deacd761e85ee4d75a6adbdd63225fc4a6d3088dElliott Hughes        }
1016deacd761e85ee4d75a6adbdd63225fc4a6d3088dElliott Hughes        if (object == this) {
1017deacd761e85ee4d75a6adbdd63225fc4a6d3088dElliott Hughes            return true;
1018deacd761e85ee4d75a6adbdd63225fc4a6d3088dElliott Hughes        }
1019adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.equals(object)
1020adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && gregorianCutover == ((GregorianCalendar) object).gregorianCutover;
1021adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1022adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1023adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1024adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the maximum value of the specified field for the current date. For
1025adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * example, the maximum number of days in the current month.
1026f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1027adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1028adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
1029adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the maximum value of the specified field.
1030adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1031adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1032adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getActualMaximum(int field) {
1033adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int value;
1034adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((value = maximums[field]) == leastMaximums[field]) {
1035adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return value;
1036adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1037adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1038adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (field) {
1039adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_YEAR:
1040adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_MONTH:
1041adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                isCached = false;
1042adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
1043adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1044adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1045adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        complete();
1046adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long orgTime = time;
1047adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int result = 0;
1048adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (field) {
1049adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_YEAR:
1050adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(DATE, 31);
1051adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(MONTH, DECEMBER);
1052adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = get(WEEK_OF_YEAR);
1053adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (result == 1) {
1054adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    set(DATE, 31 - 7);
1055adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = get(WEEK_OF_YEAR);
1056adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1057adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                areFieldsSet = false;
1058adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
1059adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_MONTH:
1060adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(DATE, daysInMonth());
1061adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = get(WEEK_OF_MONTH);
1062adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                areFieldsSet = false;
1063adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
1064adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DATE:
1065adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return daysInMonth();
1066adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DAY_OF_YEAR:
1067adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return daysInYear(fields[YEAR]);
1068adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DAY_OF_WEEK_IN_MONTH:
1069adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = get(DAY_OF_WEEK_IN_MONTH)
1070adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        + ((daysInMonth() - get(DATE)) / 7);
1071adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
1072adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case YEAR:
1073adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                GregorianCalendar clone = (GregorianCalendar) clone();
1074adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (get(ERA) == AD) {
1075adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    clone.setTimeInMillis(Long.MAX_VALUE);
1076adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
1077adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    clone.setTimeInMillis(Long.MIN_VALUE);
1078adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1079adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = clone.get(YEAR);
1080adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                clone.set(YEAR, get(YEAR));
1081adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (clone.before(this)) {
1082adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result--;
1083adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1084adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
1085adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DST_OFFSET:
1086adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = getMaximum(DST_OFFSET);
1087adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
1088adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1089adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        time = orgTime;
1090adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
1091adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1092adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1093adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1094adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the minimum value of the specified field for the current date. For
1095adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the gregorian calendar, this value is the same as
1096adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code getMinimum()}.
1097f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1098adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1099adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
1100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the minimum value of the specified field.
1101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getActualMinimum(int field) {
1104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return getMinimum(field);
1105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the greatest minimum value of the specified field. For the gregorian
1109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * calendar, this value is the same as {@code getMinimum()}.
1110f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
1113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the greatest minimum value of the specified field.
1114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getGreatestMinimum(int field) {
1117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return minimums[field];
1118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the gregorian change date of this calendar. This is the date on
1122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * which the gregorian calendar came into effect.
1123f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a {@code Date} which represents the gregorian change date.
1125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final Date getGregorianChange() {
1127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new Date(gregorianCutover);
1128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the smallest maximum value of the specified field. For example, 28
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 smallest maximum value of the specified field.
1137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getLeastMaximum(int field) {
1140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // return value for WEEK_OF_YEAR should make corresponding changes when
1141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // the gregorian change date have been reset.
1142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (gregorianCutover != defaultGregorianCutover
1143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && field == WEEK_OF_YEAR) {
1144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long currentTimeInMillis = time;
1145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            setTimeInMillis(gregorianCutover);
1146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int actual = getActualMaximum(field);
1147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            setTimeInMillis(currentTimeInMillis);
1148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return actual;
1149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return leastMaximums[field];
1151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the greatest maximum value of the specified field. For example, 31
1155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for the day of month field.
1156f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
1159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the greatest maximum value of the specified field.
1160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getMaximum(int field) {
1163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return maximums[field];
1164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the smallest minimum value of the specified field.
1168f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
1171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the smallest minimum value of the specified field.
1172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getMinimum(int field) {
1175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return minimums[field];
1176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
117818aa2ce5993b2f06e1d4d60c90d92fe4650b1d75Elliott Hughes    private int getOffset(long localTime) {
1179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        TimeZone timeZone = getTimeZone();
1180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!timeZone.useDaylightTime()) {
1181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return timeZone.getRawOffset();
1182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long dayCount = localTime / 86400000;
1185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int millis = (int) (localTime % 86400000);
1186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (millis < 0) {
1187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += 86400000;
1188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            dayCount--;
1189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int year = 1970;
1192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long days = dayCount;
1193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (localTime < gregorianCutover) {
1194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days -= julianSkew;
1195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int approxYears;
1197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while ((approxYears = (int) (days / 365)) != 0) {
1199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year = year + approxYears;
1200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = dayCount - daysFromBaseYear(year);
1201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (days < 0) {
1203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year = year - 1;
1204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = days + 365 + (isLeapYear(year) ? 1 : 0);
1205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (year == changeYear && localTime < gregorianCutover) {
1206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days -= julianError();
1207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year <= 0) {
1210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return timeZone.getRawOffset();
1211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dayOfYear = (int) days + 1;
1213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int month = dayOfYear / 32;
1215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean leapYear = isLeapYear(year);
1216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int date = dayOfYear - daysInYear(leapYear, month);
1217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (date > daysInMonth(leapYear, month)) {
1218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            date -= daysInMonth(leapYear, month);
1219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            month++;
1220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dayOfWeek = mod7(dayCount - 3) + 1;
1222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int offset = timeZone.getOffset(AD, year, month, date, dayOfWeek,
1223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis);
1224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return offset;
1225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an integer hash code for the receiver. Objects which are equal
1229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * return the same value for this method.
1230f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the receiver's hash.
1232f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #equals
1234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int hashCode() {
1237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.hashCode()
1238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                + ((int) (gregorianCutover >>> 32) ^ (int) gregorianCutover);
1239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether the specified year is a leap year.
1243f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param year
1245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the year.
1246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the specified year is a leap year, {@code false}
1247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         otherwise.
1248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isLeapYear(int year) {
1250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year > changeYear) {
1251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
1252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return year % 4 == 0;
1255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int julianError() {
1258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return changeYear / 100 - changeYear / 400 - 2;
1259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int mod(int value, int mod) {
1262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int rem = value % mod;
1263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (value < 0 && rem < 0) {
1264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return rem + mod;
1265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return rem;
1267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int mod7(long num1) {
1270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int rem = (int) (num1 % 7);
1271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (num1 < 0 && rem < 0) {
1272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return rem + 7;
1273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return rem;
1275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Adds the specified amount the specified field and wraps the value of the
1279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * field when it goes beyond the maximum or minimum value for the current
1280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * date. Other fields will be adjusted as required to maintain a consistent
1281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * date.
1282f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field to roll.
1285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param value
1286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the amount to add.
1287f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1288f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @throws IllegalArgumentException
1289f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *                if an invalid field is specified.
1290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void roll(int field, int value) {
1293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (value == 0) {
1294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
1295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (field < 0 || field >= ZONE_OFFSET) {
1297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException();
1298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
1301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        complete();
1303f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        int days, day, mod, maxWeeks, newWeek;
1304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int max = -1;
1305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (field) {
1306f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case YEAR:
1307f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = maximums[field];
1308f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1309f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case WEEK_OF_YEAR:
1310f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            days = daysInYear(fields[YEAR]);
1311f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            day = DAY_OF_YEAR;
1312f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            mod = mod7(fields[DAY_OF_WEEK] - fields[day]
1313f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    - (getFirstDayOfWeek() - 1));
1314f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            maxWeeks = (days - 1 + mod) / 7 + 1;
1315f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
1316f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (newWeek == maxWeeks) {
1317f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                int addDays = (newWeek - fields[field]) * 7;
1318f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (fields[day] > addDays && fields[day] + addDays > days) {
1319f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, 1);
1320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
1321f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, newWeek - 1);
1322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1323f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else if (newWeek == 1) {
1324f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
1325f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (week > 1) {
1326f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, 1);
1327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
1328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    set(field, newWeek);
1329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1330f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else {
1331f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                set(field, newWeek);
1332f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
1333f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1334f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case WEEK_OF_MONTH:
1335f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            days = daysInMonth();
1336f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            day = DATE;
1337f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            mod = mod7(fields[DAY_OF_WEEK] - fields[day]
1338f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    - (getFirstDayOfWeek() - 1));
1339f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            maxWeeks = (days - 1 + mod) / 7 + 1;
1340f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
1341f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (newWeek == maxWeeks) {
1342f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (fields[day] + (newWeek - fields[field]) * 7 > days) {
1343f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(day, days);
1344f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                } else {
1345f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, newWeek);
1346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1347f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else if (newWeek == 1) {
1348f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
1349f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (week > 1) {
1350f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(day, 1);
1351f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                } else {
1352f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, newWeek);
1353f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                }
1354f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else {
1355f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                set(field, newWeek);
1356f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
1357f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1358f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case DATE:
1359f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = daysInMonth();
1360f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1361f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case DAY_OF_YEAR:
1362f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = daysInYear(fields[YEAR]);
1363f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1364f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case DAY_OF_WEEK:
1365f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = maximums[field];
1366f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            lastDateFieldSet = WEEK_OF_MONTH;
1367f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1368f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case DAY_OF_WEEK_IN_MONTH:
1369f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = (fields[DATE] + ((daysInMonth() - fields[DATE]) / 7 * 7) - 1) / 7 + 1;
1370f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1371f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1372f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case ERA:
1373f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case MONTH:
1374f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case AM_PM:
1375f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case HOUR:
1376f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case HOUR_OF_DAY:
1377f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case MINUTE:
1378f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case SECOND:
1379f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case MILLISECOND:
1380f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            set(field, mod(fields[field] + value, maximums[field] + 1));
1381f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (field == MONTH && fields[DATE] > daysInMonth()) {
1382f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                set(DATE, daysInMonth());
1383f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else if (field == AM_PM) {
1384f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                lastTimeFieldSet = HOUR;
1385f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
1386f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (max != -1) {
1389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            set(field, mod(fields[field] - 1 + value, max) + 1);
1390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        complete();
1392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Increments or decrements the specified field and wraps the value of the
1396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * field when it goes beyond the maximum or minimum value for the current
1397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * date. Other fields will be adjusted as required to maintain a consistent
1398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * date. For example, March 31 will roll to April 30 when rolling the month
1399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * field.
1400f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field to roll.
1403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param increment
1404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            {@code true} to increment the field, {@code false} to
1405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            decrement.
1406f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @throws IllegalArgumentException
1407f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *                if an invalid field is specified.
1408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void roll(int field, boolean increment) {
1411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        roll(field, increment ? 1 : -1);
1412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the gregorian change date of this calendar.
1416f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param date
1418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a {@code Date} which represents the gregorian change date.
1419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setGregorianChange(Date date) {
1421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        gregorianCutover = date.getTime();
1422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        GregorianCalendar cal = new GregorianCalendar(TimeZone.GMT);
1423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        cal.setTime(date);
1424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        changeYear = cal.get(YEAR);
1425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (cal.get(ERA) == BC) {
1426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            changeYear = 1 - changeYear;
1427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        julianSkew = ((changeYear - 2000) / 400) + julianError()
1429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - ((changeYear - 2000) / 100);
1430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
1431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dayOfYear = cal.get(DAY_OF_YEAR);
1432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (dayOfYear < julianSkew) {
1433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            currentYearSkew = dayOfYear-1;
1434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            lastYearSkew = julianSkew - dayOfYear + 1;
1435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
1436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            lastYearSkew = 0;
1437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            currentYearSkew = julianSkew;
1438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
1440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void writeObject(ObjectOutputStream stream) throws IOException {
1443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        stream.defaultWriteObject();
1444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void readObject(ObjectInputStream stream) throws IOException,
1447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ClassNotFoundException {
1448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        stream.defaultReadObject();
1450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setGregorianChange(new Date(gregorianCutover));
1451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
1452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setFirstDayOfWeek(int value) {
1456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super.setFirstDayOfWeek(value);
1457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
1458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setMinimalDaysInFirstWeek(int value) {
1462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super.setMinimalDaysInFirstWeek(value);
1463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isCached = false;
1464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
1466