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 int currentYearSkew = 10;
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int lastYearSkew = 0;
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to the current date and
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * time with the default {@code Locale} and {@code TimeZone}.
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar() {
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this(TimeZone.getDefault(), Locale.getDefault());
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to midnight in the default
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code TimeZone} and {@code Locale} on the specified date.
237f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param year
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the year.
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param month
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the month.
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param day
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the day of the month.
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar(int year, int month, int day) {
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(TimeZone.getDefault(), Locale.getDefault());
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        set(year, month, day);
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to the specified date and
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * time in the default {@code TimeZone} and {@code Locale}.
253f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param year
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the year.
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param month
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the month.
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param day
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the day of the month.
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param hour
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the hour.
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param minute
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the minute.
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar(int year, int month, int day, int hour, int minute) {
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(TimeZone.getDefault(), Locale.getDefault());
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        set(year, month, day, hour, minute);
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to the specified date and
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * time in the default {@code TimeZone} and {@code Locale}.
273f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param year
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the year.
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param month
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the month.
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param day
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the day of the month.
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param hour
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the hour.
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param minute
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the minute.
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param second
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the second.
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar(int year, int month, int day, int hour,
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int minute, int second) {
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(TimeZone.getDefault(), Locale.getDefault());
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        set(year, month, day, hour, minute, second);
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    GregorianCalendar(long milliseconds) {
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this(false);
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setTimeInMillis(milliseconds);
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to the current date and
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * time and using the specified {@code Locale} and the default {@code TimeZone}.
301f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param locale
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Locale}.
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar(Locale locale) {
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this(TimeZone.getDefault(), locale);
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to the current date and
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * time and using the specified {@code TimeZone} and the default {@code Locale}.
312f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param timezone
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code TimeZone}.
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar(TimeZone timezone) {
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this(timezone, Locale.getDefault());
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code GregorianCalendar} initialized to the current date and
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * time and using the specified {@code TimeZone} and {@code Locale}.
323f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param timezone
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code TimeZone}.
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param locale
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Locale}.
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GregorianCalendar(TimeZone timezone, Locale locale) {
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(timezone, locale);
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setTimeInMillis(System.currentTimeMillis());
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    GregorianCalendar(boolean ignored) {
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(TimeZone.getDefault());
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setFirstDayOfWeek(SUNDAY);
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setMinimalDaysInFirstWeek(1);
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Adds the specified amount to a {@code Calendar} field.
342f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code Calendar} field to modify.
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param value
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the amount to add to the field.
347f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
348f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @throws IllegalArgumentException
349f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *                if the specified field is DST_OFFSET or ZONE_OFFSET.
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void add(int field, int value) {
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (value == 0) {
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (field < 0 || field >= ZONE_OFFSET) {
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException();
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (field == ERA) {
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            complete();
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (fields[ERA] == AD) {
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (value >= 0) {
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return;
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(ERA, BC);
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (value <= 0) {
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return;
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(ERA, AD);
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            complete();
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (field == YEAR || field == MONTH) {
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            complete();
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (field == MONTH) {
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int month = fields[MONTH] + value;
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (month < 0) {
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    value = (month - 11) / 12;
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    month = 12 + (month % 12);
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    value = month / 12;
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(MONTH, month % 12);
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            set(YEAR, fields[YEAR] + value);
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int days = daysInMonth(isLeapYear(fields[YEAR]), fields[MONTH]);
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (fields[DATE] > days) {
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(DATE, days);
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            complete();
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long multiplier = 0;
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        getTimeInMillis(); // Update the time
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (field) {
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case MILLISECOND:
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                time += value;
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case SECOND:
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                time += value * 1000L;
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case MINUTE:
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                time += value * 60000L;
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case HOUR:
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case HOUR_OF_DAY:
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                time += value * 3600000L;
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case AM_PM:
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                multiplier = 43200000L;
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DATE:
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DAY_OF_YEAR:
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DAY_OF_WEEK:
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                multiplier = 86400000L;
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_YEAR:
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_MONTH:
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DAY_OF_WEEK_IN_MONTH:
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                multiplier = 604800000L;
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
428996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson
429996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        if (multiplier == 0) {
430996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson            areFieldsSet = false;
431996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson            complete();
432996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson            return;
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
434996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson
435996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        long delta = value * multiplier;
436996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson
437996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        /*
438996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * Attempt to keep the hour and minute constant when we've crossed a DST
439996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * boundary and the user's units are AM_PM or larger. The typical
440996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * consequence is that calls to add(DATE, 1) will add 23, 24 or 25 hours
441996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * depending on whether the DST goes forward, constant, or backward.
442996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         *
443996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * We know we've crossed a DST boundary if the new time will have a
444996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * different timezone offset. Adjust by adding the difference of the two
445996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * offsets. We don't adjust when doing so prevents the change from
446996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         * crossing the boundary.
447996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson         */
448996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        int zoneOffset = getTimeZone().getRawOffset();
449996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        int offsetBefore = getOffset(time + zoneOffset);
450996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        int offsetAfter = getOffset(time + zoneOffset + delta);
451996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        int dstDelta = offsetBefore - offsetAfter;
452996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        if (getOffset(time + zoneOffset + delta + dstDelta) == offsetAfter) {
453996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson            delta += dstDelta;
454996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        }
455996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson
456996083c82dd18f09ac014d8ad2d40eeec85f6b24Jesse Wilson        time += delta;
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        areFieldsSet = false;
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        complete();
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
4611baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson    private void fullFieldsCalc(long timeVal, int zoneOffset) {
4621baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson        int millis = (int) (time % 86400000);
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long days = timeVal / 86400000;
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (millis < 0) {
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += 86400000;
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days--;
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Cannot add ZONE_OFFSET to time as it might overflow
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        millis += zoneOffset;
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (millis < 0) {
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += 86400000;
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days--;
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (millis >= 86400000) {
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis -= 86400000;
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days++;
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dayOfYear = computeYearAndDay(days, timeVal + zoneOffset);
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DAY_OF_YEAR] = dayOfYear;
482f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        if(fields[YEAR] == changeYear && gregorianCutover <= timeVal + zoneOffset){
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            dayOfYear += currentYearSkew;
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int month = dayOfYear / 32;
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean leapYear = isLeapYear(fields[YEAR]);
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int date = dayOfYear - daysInYear(leapYear, month);
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (date > daysInMonth(leapYear, month)) {
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            date -= daysInMonth(leapYear, month);
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            month++;
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DAY_OF_WEEK] = mod7(days - 3) + 1;
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dstOffset = fields[YEAR] <= 0 ? 0 : getTimeZone().getOffset(AD,
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fields[YEAR], month, date, fields[DAY_OF_WEEK], millis);
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (fields[YEAR] > 0) {
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            dstOffset -= zoneOffset;
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DST_OFFSET] = dstOffset;
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (dstOffset != 0) {
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long oldDays = days;
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += dstOffset;
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (millis < 0) {
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis += 86400000;
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days--;
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (millis >= 86400000) {
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                millis -= 86400000;
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days++;
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (oldDays != days) {
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                dayOfYear = computeYearAndDay(days, timeVal - zoneOffset
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        + dstOffset);
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fields[DAY_OF_YEAR] = dayOfYear;
513f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if(fields[YEAR] == changeYear && gregorianCutover <= timeVal - zoneOffset + dstOffset){
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfYear += currentYearSkew;
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                month = dayOfYear / 32;
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                leapYear = isLeapYear(fields[YEAR]);
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                date = dayOfYear - daysInYear(leapYear, month);
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (date > daysInMonth(leapYear, month)) {
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    date -= daysInMonth(leapYear, month);
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    month++;
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fields[DAY_OF_WEEK] = mod7(days - 3) + 1;
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[MILLISECOND] = (millis % 1000);
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        millis /= 1000;
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[SECOND] = (millis % 60);
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        millis /= 60;
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[MINUTE] = (millis % 60);
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        millis /= 60;
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[HOUR_OF_DAY] = (millis % 24);
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[AM_PM] = fields[HOUR_OF_DAY] > 11 ? 1 : 0;
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[HOUR] = fields[HOUR_OF_DAY] % 12;
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (fields[YEAR] <= 0) {
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[ERA] = BC;
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[YEAR] = -fields[YEAR] + 1;
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[ERA] = AD;
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[MONTH] = month;
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DATE] = date;
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[DAY_OF_WEEK_IN_MONTH] = (date - 1) / 7 + 1;
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[WEEK_OF_MONTH] = (date - 1 + mod7(days - date - 2
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - (getFirstDayOfWeek() - 1))) / 7 + 1;
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int daysFromStart = mod7(days - 3 - (fields[DAY_OF_YEAR] - 1)
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - (getFirstDayOfWeek() - 1));
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int week = (fields[DAY_OF_YEAR] - 1 + daysFromStart) / 7
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                + (7 - daysFromStart >= getMinimalDaysInFirstWeek() ? 1 : 0);
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (week == 0) {
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_YEAR] = 7 - mod7(daysFromStart
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    - (isLeapYear(fields[YEAR] - 1) ? 2 : 1)) >= getMinimalDaysInFirstWeek() ? 53
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    : 52;
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (fields[DAY_OF_YEAR] >= (leapYear ? 367 : 366)
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - mod7(daysFromStart + (leapYear ? 2 : 1))) {
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_YEAR] = 7 - mod7(daysFromStart + (leapYear ? 2 : 1)) >= getMinimalDaysInFirstWeek() ? 1
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    : week;
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fields[WEEK_OF_YEAR] = week;
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void computeFields() {
56769bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        TimeZone timeZone = getTimeZone();
56869bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        int dstOffset = timeZone.inDaylightTime(new Date(time)) ? timeZone.getDSTSavings() : 0;
56969bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        int zoneOffset = timeZone.getRawOffset();
57069bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        fields[DST_OFFSET] = dstOffset;
57169bcb487b7317dde579a8ddc1a8094040ed7ae2bElliott Hughes        fields[ZONE_OFFSET] = zoneOffset;
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
5731baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson        fullFieldsCalc(time, zoneOffset);
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0; i < FIELD_COUNT; i++) {
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isSet[i] = true;
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void computeTime() {
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isLenient()) {
583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[HOUR_OF_DAY]) {
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (fields[HOUR_OF_DAY] < 0 || fields[HOUR_OF_DAY] > 23) {
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11)) {
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[MINUTE] && (fields[MINUTE] < 0 || fields[MINUTE] > 59)) {
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[SECOND] && (fields[SECOND] < 0 || fields[SECOND] > 59)) {
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[MILLISECOND]
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[MILLISECOND] < 0 || fields[MILLISECOND] > 999)) {
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[WEEK_OF_YEAR]
601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[WEEK_OF_YEAR] < 1 || fields[WEEK_OF_YEAR] > 53)) {
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[DAY_OF_WEEK]
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[DAY_OF_WEEK] < 1 || fields[DAY_OF_WEEK] > 7)) {
606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[DAY_OF_WEEK_IN_MONTH]
609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[DAY_OF_WEEK_IN_MONTH] < 1 || fields[DAY_OF_WEEK_IN_MONTH] > 6)) {
610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[WEEK_OF_MONTH]
613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (fields[WEEK_OF_MONTH] < 1 || fields[WEEK_OF_MONTH] > 6)) {
614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[AM_PM] && fields[AM_PM] != AM && fields[AM_PM] != PM) {
617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11)) {
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[YEAR]) {
623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSet[ERA] && fields[ERA] == BC
624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && (fields[YEAR] < 1 || fields[YEAR] > 292269054)) {
625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (fields[YEAR] < 1 || fields[YEAR] > 292278994) {
627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[MONTH] && (fields[MONTH] < 0 || fields[MONTH] > 11)) {
631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long timeVal;
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long hour = 0;
637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[HOUR_OF_DAY] && lastTimeFieldSet != HOUR) {
638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            hour = fields[HOUR_OF_DAY];
639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (isSet[HOUR]) {
640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            hour = (fields[AM_PM] * 12) + fields[HOUR];
641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        timeVal = hour * 3600000;
643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[MINUTE]) {
645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            timeVal += ((long) fields[MINUTE]) * 60000;
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[SECOND]) {
648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            timeVal += ((long) fields[SECOND]) * 1000;
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[MILLISECOND]) {
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            timeVal += fields[MILLISECOND];
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long days;
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int year = isSet[YEAR] ? fields[YEAR] : 1970;
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isSet[ERA]) {
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Always test for valid ERA, even if the Calendar is lenient
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (fields[ERA] != BC && fields[ERA] != AD) {
659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException();
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (fields[ERA] == BC) {
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                year = 1 - year;
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean weekMonthSet = isSet[WEEK_OF_MONTH]
667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || isSet[DAY_OF_WEEK_IN_MONTH];
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean useMonth = (isSet[DATE] || isSet[MONTH] || weekMonthSet)
669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && lastDateFieldSet != DAY_OF_YEAR;
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (useMonth
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && (lastDateFieldSet == DAY_OF_WEEK || lastDateFieldSet == WEEK_OF_YEAR)) {
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isSet[WEEK_OF_YEAR] && isSet[DAY_OF_WEEK]) {
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                useMonth = lastDateFieldSet != WEEK_OF_YEAR && weekMonthSet
674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && isSet[DAY_OF_WEEK];
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (isSet[DAY_OF_YEAR]) {
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                useMonth = isSet[DATE] && isSet[MONTH];
677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (useMonth) {
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int month = fields[MONTH];
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year += month / 12;
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            month %= 12;
684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (month < 0) {
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                year--;
686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                month += 12;
687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean leapYear = isLeapYear(year);
689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = daysFromBaseYear(year) + daysInYear(leapYear, month);
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean useDate = isSet[DATE];
691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (useDate
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && (lastDateFieldSet == DAY_OF_WEEK
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || lastDateFieldSet == WEEK_OF_MONTH || lastDateFieldSet == DAY_OF_WEEK_IN_MONTH)) {
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                useDate = !(isSet[DAY_OF_WEEK] && weekMonthSet);
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (useDate) {
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!isLenient()
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && (fields[DATE] < 1 || fields[DATE] > daysInMonth(
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                leapYear, month))) {
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days += fields[DATE] - 1;
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int dayOfWeek;
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSet[DAY_OF_WEEK]) {
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfWeek = fields[DAY_OF_WEEK] - 1;
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfWeek = getFirstDayOfWeek() - 1;
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSet[WEEK_OF_MONTH]
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && lastDateFieldSet != DAY_OF_WEEK_IN_MONTH) {
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += (fields[WEEK_OF_MONTH] - 1) * 7
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            + mod7(skew + dayOfWeek - (days - 3)) - skew;
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (isSet[DAY_OF_WEEK_IN_MONTH]) {
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (fields[DAY_OF_WEEK_IN_MONTH] >= 0) {
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        days += mod7(dayOfWeek - (days - 3))
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                + (fields[DAY_OF_WEEK_IN_MONTH] - 1) * 7;
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        days += daysInMonth(leapYear, month)
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                + mod7(dayOfWeek
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                        - (days + daysInMonth(leapYear, month) - 3))
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                + fields[DAY_OF_WEEK_IN_MONTH] * 7;
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
725f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                } else if (isSet[DAY_OF_WEEK]) {
726f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
727f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    days += mod7(mod7(skew + dayOfWeek - (days - 3)) - skew);
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean useWeekYear = isSet[WEEK_OF_YEAR]
732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && lastDateFieldSet != DAY_OF_YEAR;
733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (useWeekYear && isSet[DAY_OF_YEAR]) {
734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                useWeekYear = isSet[DAY_OF_WEEK];
735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = daysFromBaseYear(year);
737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (useWeekYear) {
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int dayOfWeek;
739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSet[DAY_OF_WEEK]) {
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfWeek = fields[DAY_OF_WEEK] - 1;
741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    dayOfWeek = getFirstDayOfWeek() - 1;
743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days += (fields[WEEK_OF_YEAR] - 1) * 7
746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        + mod7(skew + dayOfWeek - (days - 3)) - skew;
747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (7 - skew < getMinimalDaysInFirstWeek()) {
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += 7;
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (isSet[DAY_OF_YEAR]) {
751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!isLenient()
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && (fields[DAY_OF_YEAR] < 1 || fields[DAY_OF_YEAR] > (365 + (isLeapYear(year) ? 1
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                : 0)))) {
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalArgumentException();
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days += fields[DAY_OF_YEAR] - 1;
757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (isSet[DAY_OF_WEEK]) {
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days += mod7(fields[DAY_OF_WEEK] - 1 - (days - 3));
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        lastDateFieldSet = 0;
762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        timeVal += days * 86400000;
764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Use local time to compare with the gregorian change
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year == changeYear
766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && timeVal >= gregorianCutover + julianError() * 86400000L) {
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            timeVal -= julianError() * 86400000L;
768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // It is not possible to simply subtract getOffset(timeVal) from timeVal
771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // to get UTC.
772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // The trick is needed for the moment when DST transition occurs,
773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // say 1:00 is a transition time when DST offset becomes +1 hour,
774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // then wall time in the interval 1:00 - 2:00 is invalid and is
775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // treated as UTC time.
776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long timeValWithoutDST = timeVal - getOffset(timeVal)
777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                + getTimeZone().getRawOffset();
778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        timeVal -= getOffset(timeValWithoutDST);
779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Need to update wall time in fields, since it was invalid due to DST
780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // transition
781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.time = timeVal;
782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (timeValWithoutDST != timeVal) {
783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            computeFields();
784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            areFieldsSet = true;
785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int computeYearAndDay(long dayCount, long localTime) {
789adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int year = 1970;
790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long days = dayCount;
791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (localTime < gregorianCutover) {
792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days -= julianSkew;
793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int approxYears;
795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while ((approxYears = (int) (days / 365)) != 0) {
797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year = year + approxYears;
798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = dayCount - daysFromBaseYear(year);
799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (days < 0) {
801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year = year - 1;
802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = days + daysInYear(year);
803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fields[YEAR] = year;
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (int) days + 1;
806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
8081baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson    private long daysFromBaseYear(long year) {
809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year >= 1970) {
810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long days = (year - 1970) * 365 + ((year - 1969) / 4);
811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (year > changeYear) {
812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days -= ((year - 1901) / 100) - ((year - 1601) / 400);
813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
8141baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson                if (year == changeYear) {
815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += currentYearSkew;
8161baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson                } else if (year == changeYear - 1) {
817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += lastYearSkew;
8181baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson                } else {
819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    days += julianSkew;
820adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return days;
823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (year <= changeYear) {
824adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return (year - 1970) * 365 + ((year - 1972) / 4) + julianSkew;
825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (year - 1970) * 365 + ((year - 1972) / 4)
827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - ((year - 2000) / 100) + ((year - 2000) / 400);
828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
829f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int daysInMonth() {
831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return daysInMonth(isLeapYear(fields[YEAR]), fields[MONTH]);
832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int daysInMonth(boolean leapYear, int month) {
835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (leapYear && month == FEBRUARY) {
836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return DaysInMonth[month] + 1;
837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return DaysInMonth[month];
840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int daysInYear(int year) {
843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int daysInYear = isLeapYear(year) ? 366 : 365;
844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year == changeYear) {
845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            daysInYear -= currentYearSkew;
846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year == changeYear - 1) {
848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            daysInYear -= lastYearSkew;
849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return daysInYear;
851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int daysInYear(boolean leapYear, int month) {
854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (leapYear && month > FEBRUARY) {
855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return DaysInYear[month] + 1;
856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return DaysInYear[month];
859adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
8621baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson     * Returns true if {@code object} is a GregorianCalendar with the same
8631baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson     * properties.
864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
8651baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson    @Override public boolean equals(Object object) {
866deacd761e85ee4d75a6adbdd63225fc4a6d3088dElliott Hughes        if (!(object instanceof GregorianCalendar)) {
867deacd761e85ee4d75a6adbdd63225fc4a6d3088dElliott Hughes            return false;
868deacd761e85ee4d75a6adbdd63225fc4a6d3088dElliott Hughes        }
869deacd761e85ee4d75a6adbdd63225fc4a6d3088dElliott Hughes        if (object == this) {
870deacd761e85ee4d75a6adbdd63225fc4a6d3088dElliott Hughes            return true;
871deacd761e85ee4d75a6adbdd63225fc4a6d3088dElliott Hughes        }
872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.equals(object)
873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && gregorianCutover == ((GregorianCalendar) object).gregorianCutover;
874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
8761baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson    @Override public int getActualMaximum(int field) {
877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int value;
878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((value = maximums[field]) == leastMaximums[field]) {
879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return value;
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        complete();
883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long orgTime = time;
884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int result = 0;
885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (field) {
886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_YEAR:
887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(DATE, 31);
888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(MONTH, DECEMBER);
889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = get(WEEK_OF_YEAR);
890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (result == 1) {
891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    set(DATE, 31 - 7);
892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = get(WEEK_OF_YEAR);
893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                areFieldsSet = false;
895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case WEEK_OF_MONTH:
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                set(DATE, daysInMonth());
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = get(WEEK_OF_MONTH);
899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                areFieldsSet = false;
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DATE:
902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return daysInMonth();
903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DAY_OF_YEAR:
904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return daysInYear(fields[YEAR]);
905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DAY_OF_WEEK_IN_MONTH:
906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = get(DAY_OF_WEEK_IN_MONTH)
907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        + ((daysInMonth() - get(DATE)) / 7);
908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case YEAR:
910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                GregorianCalendar clone = (GregorianCalendar) clone();
911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (get(ERA) == AD) {
912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    clone.setTimeInMillis(Long.MAX_VALUE);
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    clone.setTimeInMillis(Long.MIN_VALUE);
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = clone.get(YEAR);
917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                clone.set(YEAR, get(YEAR));
918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (clone.before(this)) {
919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result--;
920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DST_OFFSET:
923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result = getMaximum(DST_OFFSET);
924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        time = orgTime;
927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the minimum value of the specified field for the current date. For
932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the gregorian calendar, this value is the same as
933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code getMinimum()}.
934f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the minimum value of the specified field.
938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getActualMinimum(int field) {
941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return getMinimum(field);
942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the greatest minimum value of the specified field. For the gregorian
946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * calendar, this value is the same as {@code getMinimum()}.
947f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the greatest minimum value of the specified field.
951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getGreatestMinimum(int field) {
954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return minimums[field];
955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the gregorian change date of this calendar. This is the date on
959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * which the gregorian calendar came into effect.
960f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
961adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a {@code Date} which represents the gregorian change date.
962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final Date getGregorianChange() {
964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new Date(gregorianCutover);
965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
966adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the smallest maximum value of the specified field. For example, 28
969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for the day of month field.
970f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
971adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the smallest maximum value of the specified field.
974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
976adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getLeastMaximum(int field) {
977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // return value for WEEK_OF_YEAR should make corresponding changes when
978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // the gregorian change date have been reset.
979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (gregorianCutover != defaultGregorianCutover
980adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && field == WEEK_OF_YEAR) {
981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            long currentTimeInMillis = time;
982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            setTimeInMillis(gregorianCutover);
983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int actual = getActualMaximum(field);
984adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            setTimeInMillis(currentTimeInMillis);
985adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return actual;
986adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return leastMaximums[field];
988adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
989adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
991adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the greatest maximum value of the specified field. For example, 31
992adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for the day of month field.
993f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
994adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
995adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
996adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the greatest maximum value of the specified field.
997adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
998adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
999adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getMaximum(int field) {
1000adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return maximums[field];
1001adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1002adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1003adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1004adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the smallest minimum value of the specified field.
1005f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1006adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1007adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field.
1008adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the smallest minimum value of the specified field.
1009adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1010adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1011adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getMinimum(int field) {
1012adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return minimums[field];
1013adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1014adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
101518aa2ce5993b2f06e1d4d60c90d92fe4650b1d75Elliott Hughes    private int getOffset(long localTime) {
1016adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        TimeZone timeZone = getTimeZone();
1017adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1018adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long dayCount = localTime / 86400000;
1019adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int millis = (int) (localTime % 86400000);
1020adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (millis < 0) {
1021adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            millis += 86400000;
1022adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            dayCount--;
1023adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1024adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1025adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int year = 1970;
1026adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long days = dayCount;
1027adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (localTime < gregorianCutover) {
1028adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days -= julianSkew;
1029adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1030adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int approxYears;
1031adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1032adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while ((approxYears = (int) (days / 365)) != 0) {
1033adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year = year + approxYears;
1034adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = dayCount - daysFromBaseYear(year);
1035adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1036adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (days < 0) {
1037adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            year = year - 1;
1038adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            days = days + 365 + (isLeapYear(year) ? 1 : 0);
1039adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (year == changeYear && localTime < gregorianCutover) {
1040adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                days -= julianError();
1041adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1042adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1043adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year <= 0) {
1044adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return timeZone.getRawOffset();
1045adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1046adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dayOfYear = (int) days + 1;
1047adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1048adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int month = dayOfYear / 32;
1049adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean leapYear = isLeapYear(year);
1050adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int date = dayOfYear - daysInYear(leapYear, month);
1051adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (date > daysInMonth(leapYear, month)) {
1052adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            date -= daysInMonth(leapYear, month);
1053adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            month++;
1054adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1055adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dayOfWeek = mod7(dayCount - 3) + 1;
10561baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson        return timeZone.getOffset(AD, year, month, date, dayOfWeek, millis);
1057adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1058adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
10591baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson    @Override public int hashCode() {
1060adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.hashCode()
1061adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                + ((int) (gregorianCutover >>> 32) ^ (int) gregorianCutover);
1062adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1063adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1064adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
10651baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson     * Returns true if {@code year} is a leap year.
1066adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1067adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isLeapYear(int year) {
1068adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (year > changeYear) {
1069adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
1070adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1071adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1072adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return year % 4 == 0;
1073adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1074adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1075adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int julianError() {
1076adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return changeYear / 100 - changeYear / 400 - 2;
1077adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1078adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1079adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int mod(int value, int mod) {
1080adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int rem = value % mod;
1081adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (value < 0 && rem < 0) {
1082adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return rem + mod;
1083adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1084adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return rem;
1085adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1086adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1087adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int mod7(long num1) {
1088adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int rem = (int) (num1 % 7);
1089adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (num1 < 0 && rem < 0) {
1090adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return rem + 7;
1091adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1092adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return rem;
1093adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1094adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1095adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1096adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Adds the specified amount the specified field and wraps the value of the
1097adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * field when it goes beyond the maximum or minimum value for the current
1098adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * date. Other fields will be adjusted as required to maintain a consistent
1099adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * date.
1100f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field to roll.
1103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param value
1104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the amount to add.
1105f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1106f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @throws IllegalArgumentException
1107f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *                if an invalid field is specified.
1108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void roll(int field, int value) {
1111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (value == 0) {
1112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
1113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (field < 0 || field >= ZONE_OFFSET) {
1115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException();
1116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        complete();
1119f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        int days, day, mod, maxWeeks, newWeek;
1120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int max = -1;
1121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (field) {
1122f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case YEAR:
1123f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = maximums[field];
1124f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1125f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case WEEK_OF_YEAR:
1126f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            days = daysInYear(fields[YEAR]);
1127f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            day = DAY_OF_YEAR;
1128f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            mod = mod7(fields[DAY_OF_WEEK] - fields[day]
1129f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    - (getFirstDayOfWeek() - 1));
1130f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            maxWeeks = (days - 1 + mod) / 7 + 1;
1131f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
1132f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (newWeek == maxWeeks) {
1133f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                int addDays = (newWeek - fields[field]) * 7;
1134f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (fields[day] > addDays && fields[day] + addDays > days) {
1135f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, 1);
1136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
1137f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, newWeek - 1);
1138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1139f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else if (newWeek == 1) {
1140f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
1141f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (week > 1) {
1142f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, 1);
1143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
1144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    set(field, newWeek);
1145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1146f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else {
1147f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                set(field, newWeek);
1148f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
1149f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1150f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case WEEK_OF_MONTH:
1151f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            days = daysInMonth();
1152f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            day = DATE;
1153f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            mod = mod7(fields[DAY_OF_WEEK] - fields[day]
1154f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    - (getFirstDayOfWeek() - 1));
1155f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            maxWeeks = (days - 1 + mod) / 7 + 1;
1156f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
1157f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (newWeek == maxWeeks) {
1158f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (fields[day] + (newWeek - fields[field]) * 7 > days) {
1159f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(day, days);
1160f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                } else {
1161f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, newWeek);
1162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1163f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else if (newWeek == 1) {
1164f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
1165f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (week > 1) {
1166f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(day, 1);
1167f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                } else {
1168f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    set(field, newWeek);
1169f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                }
1170f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else {
1171f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                set(field, newWeek);
1172f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
1173f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1174f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case DATE:
1175f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = daysInMonth();
1176f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1177f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case DAY_OF_YEAR:
1178f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = daysInYear(fields[YEAR]);
1179f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1180f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case DAY_OF_WEEK:
1181f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = maximums[field];
1182f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            lastDateFieldSet = WEEK_OF_MONTH;
1183f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1184f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case DAY_OF_WEEK_IN_MONTH:
1185f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            max = (fields[DATE] + ((daysInMonth() - fields[DATE]) / 7 * 7) - 1) / 7 + 1;
1186f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1187f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
1188f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case ERA:
1189f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case MONTH:
1190f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case AM_PM:
1191f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case HOUR:
1192f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case HOUR_OF_DAY:
1193f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case MINUTE:
1194f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case SECOND:
1195f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        case MILLISECOND:
1196f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            set(field, mod(fields[field] + value, maximums[field] + 1));
1197f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (field == MONTH && fields[DATE] > daysInMonth()) {
1198f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                set(DATE, daysInMonth());
1199f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else if (field == AM_PM) {
1200f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                lastTimeFieldSet = HOUR;
1201f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
1202f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            break;
1203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (max != -1) {
1205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            set(field, mod(fields[field] - 1 + value, max) + 1);
1206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        complete();
1208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Increments or decrements the specified field and wraps the value of the
1212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * field when it goes beyond the maximum or minimum value for the current
1213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * date. Other fields will be adjusted as required to maintain a consistent
1214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * date. For example, March 31 will roll to April 30 when rolling the month
1215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * field.
1216f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param field
1218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the field to roll.
1219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param increment
1220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            {@code true} to increment the field, {@code false} to
1221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            decrement.
1222f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @throws IllegalArgumentException
1223f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *                if an invalid field is specified.
1224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void roll(int field, boolean increment) {
1227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        roll(field, increment ? 1 : -1);
1228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the gregorian change date of this calendar.
1232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setGregorianChange(Date date) {
1234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        gregorianCutover = date.getTime();
123578c3de051d68b703af480778c100ca335690b250Elliott Hughes        GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
1236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        cal.setTime(date);
1237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        changeYear = cal.get(YEAR);
1238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (cal.get(ERA) == BC) {
1239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            changeYear = 1 - changeYear;
1240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        julianSkew = ((changeYear - 2000) / 400) + julianError()
1242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - ((changeYear - 2000) / 100);
1243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int dayOfYear = cal.get(DAY_OF_YEAR);
1244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (dayOfYear < julianSkew) {
1245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            currentYearSkew = dayOfYear-1;
1246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            lastYearSkew = julianSkew - dayOfYear + 1;
1247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
1248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            lastYearSkew = 0;
1249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            currentYearSkew = julianSkew;
1250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void writeObject(ObjectOutputStream stream) throws IOException {
1254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        stream.defaultWriteObject();
1255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
12571baa4fcbfe3c22e5f06a4fee48f520162d23270fJesse Wilson    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
1258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        stream.defaultReadObject();
1259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setGregorianChange(new Date(gregorianCutover));
1260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
1262