2 * Copyright (C) 1996-2010, International Business Machines
\r
3 * Corporation and others. All Rights Reserved.
\r
6 package com.ibm.icu.util;
\r
8 import java.io.IOException;
\r
9 import java.io.ObjectInputStream;
\r
10 import java.io.ObjectOutputStream;
\r
11 import java.io.Serializable;
\r
12 import java.text.StringCharacterIterator;
\r
13 import java.util.ArrayList;
\r
14 import java.util.Date;
\r
15 import java.util.Hashtable;
\r
16 import java.util.Locale;
\r
17 import java.util.MissingResourceException;
\r
18 import java.util.Set;
\r
20 import com.ibm.icu.impl.CalendarData;
\r
21 import com.ibm.icu.impl.CalendarUtil;
\r
22 import com.ibm.icu.impl.ICUCache;
\r
23 import com.ibm.icu.impl.ICUResourceBundle;
\r
24 import com.ibm.icu.impl.SimpleCache;
\r
25 import com.ibm.icu.text.DateFormat;
\r
26 import com.ibm.icu.text.DateFormatSymbols;
\r
27 import com.ibm.icu.text.MessageFormat;
\r
28 import com.ibm.icu.text.SimpleDateFormat;
\r
31 * {@icuenhanced java.util.Calendar}.{@icu _usage_}
\r
33 * <p><code>Calendar</code> is an abstract base class for converting between
\r
34 * a <code>Date</code> object and a set of integer fields such as
\r
35 * <code>YEAR</code>, <code>MONTH</code>, <code>DAY</code>, <code>HOUR</code>,
\r
36 * and so on. (A <code>Date</code> object represents a specific instant in
\r
37 * time with millisecond precision. See
\r
39 * for information about the <code>Date</code> class.)
\r
41 * <p>Subclasses of <code>Calendar</code> interpret a <code>Date</code>
\r
42 * according to the rules of a specific calendar system. ICU4J contains
\r
43 * several subclasses implementing different international calendar systems.
\r
46 * Like other locale-sensitive classes, <code>Calendar</code> provides a
\r
47 * class method, <code>getInstance</code>, for getting a generally useful
\r
48 * object of this type. <code>Calendar</code>'s <code>getInstance</code> method
\r
49 * returns a calendar of a type appropriate to the locale, whose
\r
50 * time fields have been initialized with the current date and time:
\r
52 * <pre>Calendar rightNow = Calendar.getInstance()</pre>
\r
55 * <p>When a <code>ULocale</code> is used by <code>getInstance</code>, its
\r
56 * '<code>calendar</code>' tag and value are retrieved if present. If a recognized
\r
57 * value is supplied, a calendar is provided and configured as appropriate.
\r
58 * Currently recognized tags are "buddhist", "chinese", "coptic", "ethiopic",
\r
59 * "gregorian", "hebrew", "islamic", "islamic-civil", "japanese", and "roc". For
\r
60 * example: <blockquote>
\r
61 * <pre>Calendar cal = Calendar.getInstance(new ULocale("en_US@calendar=japanese"));</pre>
\r
62 * </blockquote> will return an instance of JapaneseCalendar (using en_US conventions for
\r
63 * minimum days in first week, start day of week, et cetera).
\r
65 * <p>A <code>Calendar</code> object can produce all the time field values
\r
66 * needed to implement the date-time formatting for a particular language and
\r
67 * calendar style (for example, Japanese-Gregorian, Japanese-Traditional).
\r
68 * <code>Calendar</code> defines the range of values returned by certain fields,
\r
69 * as well as their meaning. For example, the first month of the year has value
\r
70 * <code>MONTH</code> == <code>JANUARY</code> for all calendars. Other values
\r
71 * are defined by the concrete subclass, such as <code>ERA</code> and
\r
72 * <code>YEAR</code>. See individual field documentation and subclass
\r
73 * documentation for details.
\r
75 * <p>When a <code>Calendar</code> is <em>lenient</em>, it accepts a wider range
\r
76 * of field values than it produces. For example, a lenient
\r
77 * <code>GregorianCalendar</code> interprets <code>MONTH</code> ==
\r
78 * <code>JANUARY</code>, <code>DAY_OF_MONTH</code> == 32 as February 1. A
\r
79 * non-lenient <code>GregorianCalendar</code> throws an exception when given
\r
80 * out-of-range field settings. When calendars recompute field values for
\r
81 * return by <code>get()</code>, they normalize them. For example, a
\r
82 * <code>GregorianCalendar</code> always produces <code>DAY_OF_MONTH</code>
\r
83 * values between 1 and the length of the month.
\r
85 * <p><code>Calendar</code> defines a locale-specific seven day week using two
\r
86 * parameters: the first day of the week and the minimal days in first week
\r
87 * (from 1 to 7). These numbers are taken from the locale resource data when a
\r
88 * <code>Calendar</code> is constructed. They may also be specified explicitly
\r
91 * <p>When setting or getting the <code>WEEK_OF_MONTH</code> or
\r
92 * <code>WEEK_OF_YEAR</code> fields, <code>Calendar</code> must determine the
\r
93 * first week of the month or year as a reference point. The first week of a
\r
94 * month or year is defined as the earliest seven day period beginning on
\r
95 * <code>getFirstDayOfWeek()</code> and containing at least
\r
96 * <code>getMinimalDaysInFirstWeek()</code> days of that month or year. Weeks
\r
97 * numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow
\r
98 * it. Note that the normalized numbering returned by <code>get()</code> may be
\r
99 * different. For example, a specific <code>Calendar</code> subclass may
\r
100 * designate the week before week 1 of a year as week <em>n</em> of the previous
\r
103 * <p> When computing a <code>Date</code> from time fields, two special
\r
104 * circumstances may arise: there may be insufficient information to compute the
\r
105 * <code>Date</code> (such as only year and month but no day in the month), or
\r
106 * there may be inconsistent information (such as "Tuesday, July 15, 1996" --
\r
107 * July 15, 1996 is actually a Monday).
\r
109 * <p><strong>Insufficient information.</strong> The calendar will use default
\r
110 * information to specify the missing fields. This may vary by calendar; for
\r
111 * the Gregorian calendar, the default for a field is the same as that of the
\r
112 * start of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc.
\r
114 * <p><strong>Inconsistent information.</strong> If fields conflict, the calendar
\r
115 * will give preference to fields set more recently. For example, when
\r
116 * determining the day, the calendar will look for one of the following
\r
117 * combinations of fields. The most recent combination, as determined by the
\r
118 * most recently set single field, will be used.
\r
122 * MONTH + DAY_OF_MONTH
\r
123 * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
\r
124 * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
\r
126 * DAY_OF_WEEK + WEEK_OF_YEAR</pre>
\r
129 * For the time of day:
\r
134 * AM_PM + HOUR</pre>
\r
137 * <p><strong>Note:</strong> for some non-Gregorian calendars, different
\r
138 * fields may be necessary for complete disambiguation. For example, a full
\r
139 * specification of the historial Arabic astronomical calendar requires year,
\r
140 * month, day-of-month <em>and</em> day-of-week in some cases.
\r
142 * <p><strong>Note:</strong> There are certain possible ambiguities in
\r
143 * interpretation of certain singular times, which are resolved in the
\r
146 * <li> 24:00:00 "belongs" to the following day. That is,
\r
147 * 23:59 on Dec 31, 1969 < 24:00 on Jan 1, 1970 < 24:01:00 on Jan 1, 1970
\r
149 * <li> Although historically not precise, midnight also belongs to "am",
\r
150 * and noon belongs to "pm", so on the same day,
\r
151 * 12:00 am (midnight) < 12:01 am, and 12:00 pm (noon) < 12:01 pm
\r
154 * <p>The date or time format strings are not part of the definition of a
\r
155 * calendar, as those must be modifiable or overridable by the user at
\r
156 * runtime. Use {@link DateFormat}
\r
159 * <p><strong>Field manipulation methods</strong></p>
\r
161 * <p><code>Calendar</code> fields can be changed using three methods:
\r
162 * <code>set()</code>, <code>add()</code>, and <code>roll()</code>.</p>
\r
164 * <p><strong><code>set(f, value)</code></strong> changes field
\r
165 * <code>f</code> to <code>value</code>. In addition, it sets an
\r
166 * internal member variable to indicate that field <code>f</code> has
\r
167 * been changed. Although field <code>f</code> is changed immediately,
\r
168 * the calendar's milliseconds is not recomputed until the next call to
\r
169 * <code>get()</code>, <code>getTime()</code>, or
\r
170 * <code>getTimeInMillis()</code> is made. Thus, multiple calls to
\r
171 * <code>set()</code> do not trigger multiple, unnecessary
\r
172 * computations. As a result of changing a field using
\r
173 * <code>set()</code>, other fields may also change, depending on the
\r
174 * field, the field value, and the calendar system. In addition,
\r
175 * <code>get(f)</code> will not necessarily return <code>value</code>
\r
176 * after the fields have been recomputed. The specifics are determined by
\r
177 * the concrete calendar class.</p>
\r
179 * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
\r
180 * originally set to August 31, 1999. Calling <code>set(Calendar.MONTH,
\r
181 * Calendar.SEPTEMBER)</code> sets the calendar to September 31,
\r
182 * 1999. This is a temporary internal representation that resolves to
\r
183 * October 1, 1999 if <code>getTime()</code>is then called. However, a
\r
184 * call to <code>set(Calendar.DAY_OF_MONTH, 30)</code> before the call to
\r
185 * <code>getTime()</code> sets the calendar to September 30, 1999, since
\r
186 * no recomputation occurs after <code>set()</code> itself.</p>
\r
188 * <p><strong><code>add(f, delta)</code></strong> adds <code>delta</code>
\r
189 * to field <code>f</code>. This is equivalent to calling <code>set(f,
\r
190 * get(f) + delta)</code> with two adjustments:</p>
\r
193 * <p><strong>Add rule 1</strong>. The value of field <code>f</code>
\r
194 * after the call minus the value of field <code>f</code> before the
\r
195 * call is <code>delta</code>, modulo any overflow that has occurred in
\r
196 * field <code>f</code>. Overflow occurs when a field value exceeds its
\r
197 * range and, as a result, the next larger field is incremented or
\r
198 * decremented and the field value is adjusted back into its range.</p>
\r
200 * <p><strong>Add rule 2</strong>. If a smaller field is expected to be
\r
201 * invariant, but it is impossible for it to be equal to its
\r
202 * prior value because of changes in its minimum or maximum after field
\r
203 * <code>f</code> is changed, then its value is adjusted to be as close
\r
204 * as possible to its expected value. A smaller field represents a
\r
205 * smaller unit of time. <code>HOUR</code> is a smaller field than
\r
206 * <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields
\r
207 * that are not expected to be invariant. The calendar system
\r
208 * determines what fields are expected to be invariant.</p>
\r
211 * <p>In addition, unlike <code>set()</code>, <code>add()</code> forces
\r
212 * an immediate recomputation of the calendar's milliseconds and all
\r
215 * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
\r
216 * originally set to August 31, 1999. Calling <code>add(Calendar.MONTH,
\r
217 * 13)</code> sets the calendar to September 30, 2000. <strong>Add rule
\r
218 * 1</strong> sets the <code>MONTH</code> field to September, since
\r
219 * adding 13 months to August gives September of the next year. Since
\r
220 * <code>DAY_OF_MONTH</code> cannot be 31 in September in a
\r
221 * <code>GregorianCalendar</code>, <strong>add rule 2</strong> sets the
\r
222 * <code>DAY_OF_MONTH</code> to 30, the closest possible value. Although
\r
223 * it is a smaller field, <code>DAY_OF_WEEK</code> is not adjusted by
\r
224 * rule 2, since it is expected to change when the month changes in a
\r
225 * <code>GregorianCalendar</code>.</p>
\r
227 * <p><strong><code>roll(f, delta)</code></strong> adds
\r
228 * <code>delta</code> to field <code>f</code> without changing larger
\r
229 * fields. This is equivalent to calling <code>add(f, delta)</code> with
\r
230 * the following adjustment:</p>
\r
233 * <p><strong>Roll rule</strong>. Larger fields are unchanged after the
\r
234 * call. A larger field represents a larger unit of
\r
235 * time. <code>DAY_OF_MONTH</code> is a larger field than
\r
236 * <code>HOUR</code>.</p>
\r
239 * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
\r
240 * originally set to August 31, 1999. Calling <code>roll(Calendar.MONTH,
\r
241 * 8)</code> sets the calendar to April 30, <strong>1999</strong>. Add
\r
242 * rule 1 sets the <code>MONTH</code> field to April. Using a
\r
243 * <code>GregorianCalendar</code>, the <code>DAY_OF_MONTH</code> cannot
\r
244 * be 31 in the month April. Add rule 2 sets it to the closest possible
\r
245 * value, 30. Finally, the <strong>roll rule</strong> maintains the
\r
246 * <code>YEAR</code> field value of 1999.</p>
\r
248 * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
\r
249 * originally set to Sunday June 6, 1999. Calling
\r
250 * <code>roll(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
\r
251 * Tuesday June 1, 1999, whereas calling
\r
252 * <code>add(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
\r
253 * Sunday May 30, 1999. This is because the roll rule imposes an
\r
254 * additional constraint: The <code>MONTH</code> must not change when the
\r
255 * <code>WEEK_OF_MONTH</code> is rolled. Taken together with add rule 1,
\r
256 * the resultant date must be between Tuesday June 1 and Saturday June
\r
257 * 5. According to add rule 2, the <code>DAY_OF_WEEK</code>, an invariant
\r
258 * when changing the <code>WEEK_OF_MONTH</code>, is set to Tuesday, the
\r
259 * closest possible value to Sunday (where Sunday is the first day of the
\r
262 * <p><strong>Usage model</strong>. To motivate the behavior of
\r
263 * <code>add()</code> and <code>roll()</code>, consider a user interface
\r
264 * component with increment and decrement buttons for the month, day, and
\r
265 * year, and an underlying <code>GregorianCalendar</code>. If the
\r
266 * interface reads January 31, 1999 and the user presses the month
\r
267 * increment button, what should it read? If the underlying
\r
268 * implementation uses <code>set()</code>, it might read March 3, 1999. A
\r
269 * better result would be February 28, 1999. Furthermore, if the user
\r
270 * presses the month increment button again, it should read March 31,
\r
271 * 1999, not March 28, 1999. By saving the original date and using either
\r
272 * <code>add()</code> or <code>roll()</code>, depending on whether larger
\r
273 * fields should be affected, the user interface can behave as most users
\r
274 * will intuitively expect.</p>
\r
276 * <p><b>Note:</b> You should always use {@link #roll roll} and {@link #add add} rather
\r
277 * than attempting to perform arithmetic operations directly on the fields
\r
278 * of a <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses
\r
279 * to have fields with non-linear behavior, for example missing months
\r
280 * or days during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt>
\r
281 * methods will take this into account, while simple arithmetic manipulations
\r
282 * may give invalid results.
\r
284 * <p><big><big><b>Calendar Architecture in ICU4J</b></big></big></p>
\r
286 * <p>Recently the implementation of <code>Calendar</code> has changed
\r
287 * significantly in order to better support subclassing. The original
\r
288 * <code>Calendar</code> class was designed to support subclassing, but
\r
289 * it had only one implemented subclass, <code>GregorianCalendar</code>.
\r
290 * With the implementation of several new calendar subclasses, including
\r
291 * the <code>BuddhistCalendar</code>, <code>ChineseCalendar</code>,
\r
292 * <code>HebrewCalendar</code>, <code>IslamicCalendar</code>, and
\r
293 * <code>JapaneseCalendar</code>, the subclassing API has been reworked
\r
294 * thoroughly. This section details the new subclassing API and other
\r
295 * ways in which <code>com.ibm.icu.util.Calendar</code> differs from
\r
296 * <code>java.util.Calendar</code>.
\r
299 * <p><big><b>Changes</b></big></p>
\r
301 * <p>Overview of changes between the classic <code>Calendar</code>
\r
302 * architecture and the new architecture.
\r
306 * <li>The <code>fields[]</code> array is <code>private</code> now
\r
307 * instead of <code>protected</code>. Subclasses must access it
\r
308 * using the methods {@link #internalSet} and
\r
309 * {@link #internalGet}. <b>Motivation:</b> Subclasses should
\r
310 * not directly access data members.</li>
\r
312 * <li>The <code>time</code> long word is <code>private</code> now
\r
313 * instead of <code>protected</code>. Subclasses may access it using
\r
314 * the method {@link #internalGetTimeInMillis}, which does not
\r
315 * provoke an update. <b>Motivation:</b> Subclasses should not
\r
316 * directly access data members.</li>
\r
318 * <li>The scope of responsibility of subclasses has been drastically
\r
319 * reduced. As much functionality as possible is implemented in the
\r
320 * <code>Calendar</code> base class. As a result, it is much easier
\r
321 * to subclass <code>Calendar</code>. <b>Motivation:</b> Subclasses
\r
322 * should not have to reimplement common code. Certain behaviors are
\r
323 * common across calendar systems: The definition and behavior of
\r
324 * week-related fields and time fields, the arithmetic
\r
325 * ({@link #add(int, int) add} and {@link #roll(int, int) roll}) behavior of many
\r
326 * fields, and the field validation system.</li>
\r
328 * <li>The subclassing API has been completely redesigned.</li>
\r
330 * <li>The <code>Calendar</code> base class contains some Gregorian
\r
331 * calendar algorithmic support that subclasses can use (specifically
\r
332 * in {@link #handleComputeFields}). Subclasses can use the
\r
333 * methods <code>getGregorianXxx()</code> to obtain precomputed
\r
334 * values. <b>Motivation:</b> This is required by all
\r
335 * <code>Calendar</code> subclasses in order to implement consistent
\r
336 * time zone behavior, and Gregorian-derived systems can use the
\r
337 * already computed data.</li>
\r
339 * <li>The <code>FIELD_COUNT</code> constant has been removed. Use
\r
340 * {@link #getFieldCount}. In addition, framework API has been
\r
341 * added to allow subclasses to define additional fields.
\r
342 * <b>Motivation: </b>The number of fields is not constant across
\r
343 * calendar systems.</li>
\r
345 * <li>The range of handled dates has been narrowed from +/-
\r
346 * ~300,000,000 years to +/- ~5,000,000 years. In practical terms
\r
347 * this should not affect clients. However, it does mean that client
\r
348 * code cannot be guaranteed well-behaved results with dates such as
\r
349 * <code>Date(Long.MIN_VALUE)</code> or
\r
350 * <code>Date(Long.MAX_VALUE)</code>. Instead, the
\r
351 * <code>Calendar</code> protected constants should be used.
\r
352 * <b>Motivation:</b> With
\r
353 * the addition of the {@link #JULIAN_DAY} field, Julian day
\r
354 * numbers must be restricted to a 32-bit <code>int</code>. This
\r
355 * restricts the overall supported range. Furthermore, restricting
\r
356 * the supported range simplifies the computations by removing
\r
357 * special case code that was used to accomodate arithmetic overflow
\r
358 * at millis near <code>Long.MIN_VALUE</code> and
\r
359 * <code>Long.MAX_VALUE</code>.</li>
\r
361 * <li>New fields are implemented: {@link #JULIAN_DAY} defines
\r
362 * single-field specification of the
\r
363 * date. {@link #MILLISECONDS_IN_DAY} defines a single-field
\r
364 * specification of the wall time. {@link #DOW_LOCAL} and
\r
365 * {@link #YEAR_WOY} implement localized day-of-week and
\r
366 * week-of-year behavior.</li>
\r
368 * <li>Subclasses can access protected millisecond constants
\r
369 * defined in <code>Calendar</code>.</li>
\r
371 * <li>New API has been added to support calendar-specific subclasses
\r
372 * of <code>DateFormat</code>.</li>
\r
374 * <li>Several subclasses have been implemented, representing
\r
375 * various international calendar systems.</li>
\r
379 * <p><big><b>Subclass API</b></big></p>
\r
381 * <p>The original <code>Calendar</code> API was based on the experience
\r
382 * of implementing a only a single subclass,
\r
383 * <code>GregorianCalendar</code>. As a result, all of the subclassing
\r
384 * kinks had not been worked out. The new subclassing API has been
\r
385 * refined based on several implemented subclasses. This includes methods
\r
386 * that must be overridden and methods for subclasses to call. Subclasses
\r
387 * no longer have direct access to <code>fields</code> and
\r
388 * <code>stamp</code>. Instead, they have new API to access
\r
389 * these. Subclasses are able to allocate the <code>fields</code> array
\r
390 * through a protected framework method; this allows subclasses to
\r
391 * specify additional fields. </p>
\r
393 * <p>More functionality has been moved into the base class. The base
\r
394 * class now contains much of the computational machinery to support the
\r
395 * Gregorian calendar. This is based on two things: (1) Many calendars
\r
396 * are based on the Gregorian calendar (such as the Buddhist and Japanese
\r
397 * imperial calendars). (2) <em>All</em> calendars require basic
\r
398 * Gregorian support in order to handle timezone computations. </p>
\r
400 * <p>Common computations have been moved into
\r
401 * <code>Calendar</code>. Subclasses no longer compute the week related
\r
402 * fields and the time related fields. These are commonly handled for all
\r
403 * calendars by the base class. </p>
\r
405 * <p><b>Subclass computation of time <tt>=></tt> fields</b>
\r
407 * <p>The {@link #ERA}, {@link #YEAR},
\r
408 * {@link #EXTENDED_YEAR}, {@link #MONTH},
\r
409 * {@link #DAY_OF_MONTH}, and {@link #DAY_OF_YEAR} fields are
\r
410 * computed by the subclass, based on the Julian day. All other fields
\r
411 * are computed by <code>Calendar</code>.
\r
415 * <li>Subclasses should implement {@link #handleComputeFields}
\r
416 * to compute the {@link #ERA}, {@link #YEAR},
\r
417 * {@link #EXTENDED_YEAR}, {@link #MONTH},
\r
418 * {@link #DAY_OF_MONTH}, and {@link #DAY_OF_YEAR} fields,
\r
419 * based on the value of the {@link #JULIAN_DAY} field. If there
\r
420 * are calendar-specific fields not defined by <code>Calendar</code>,
\r
421 * they must also be computed. These are the only fields that the
\r
422 * subclass should compute. All other fields are computed by the base
\r
423 * class, so time and week fields behave in a consistent way across
\r
424 * all calendars. The default version of this method in
\r
425 * <code>Calendar</code> implements a proleptic Gregorian
\r
426 * calendar. Within this method, subclasses may call
\r
427 * <code>getGregorianXxx()</code> to obtain the Gregorian calendar
\r
428 * month, day of month, and extended year for the given date.</li>
\r
432 * <p><b>Subclass computation of fields <tt>=></tt> time</b>
\r
434 * <p>The interpretation of most field values is handled entirely by
\r
435 * <code>Calendar</code>. <code>Calendar</code> determines which fields
\r
436 * are set, which are not, which are set more recently, and so on. In
\r
437 * addition, <code>Calendar</code> handles the computation of the time
\r
438 * from the time fields and handles the week-related fields. The only
\r
439 * thing the subclass must do is determine the extended year, based on
\r
440 * the year fields, and then, given an extended year and a month, it must
\r
441 * return a Julian day number.
\r
445 * <li>Subclasses should implement {@link #handleGetExtendedYear}
\r
446 * to return the extended year for this calendar system, based on the
\r
447 * {@link #YEAR}, {@link #EXTENDED_YEAR}, and any fields that
\r
448 * the calendar system uses that are larger than a year, such as
\r
449 * {@link #ERA}.</li>
\r
451 * <li>Subclasses should implement {@link #handleComputeMonthStart}
\r
452 * to return the Julian day number
\r
453 * associated with a month and extended year. This is the Julian day
\r
454 * number of the day before the first day of the month. The month
\r
455 * number is zero-based. This computation should not depend on any
\r
456 * field values.</li>
\r
460 * <p><b>Other methods</b>
\r
464 * <li>Subclasses should implement {@link #handleGetMonthLength}
\r
465 * to return the number of days in a
\r
466 * given month of a given extended year. The month number, as always,
\r
467 * is zero-based.</li>
\r
469 * <li>Subclasses should implement {@link #handleGetYearLength}
\r
470 * to return the number of days in the given
\r
471 * extended year. This method is used by
\r
472 * <tt>computeWeekFields</tt> to compute the
\r
473 * {@link #WEEK_OF_YEAR} and {@link #YEAR_WOY} fields.</li>
\r
475 * <li>Subclasses should implement {@link #handleGetLimit}
\r
476 * to return the protected values of a field, depending on the value of
\r
477 * <code>limitType</code>. This method only needs to handle the
\r
478 * fields {@link #ERA}, {@link #YEAR}, {@link #MONTH},
\r
479 * {@link #WEEK_OF_YEAR}, {@link #WEEK_OF_MONTH},
\r
480 * {@link #DAY_OF_MONTH}, {@link #DAY_OF_YEAR},
\r
481 * {@link #DAY_OF_WEEK_IN_MONTH}, {@link #YEAR_WOY}, and
\r
482 * {@link #EXTENDED_YEAR}. Other fields are invariant (with
\r
483 * respect to calendar system) and are handled by the base
\r
486 * <li>Optionally, subclasses may override {@link #validateField}
\r
487 * to check any subclass-specific fields. If the
\r
488 * field's value is out of range, the method should throw an
\r
489 * <code>IllegalArgumentException</code>. The method may call
\r
490 * <code>super.validateField(field)</code> to handle fields in a
\r
491 * generic way, that is, to compare them to the range
\r
492 * <code>getMinimum(field)</code>..<code>getMaximum(field)</code>.</li>
\r
494 * <li>Optionally, subclasses may override
\r
495 * {@link #handleCreateFields} to create an <code>int[]</code>
\r
496 * array large enough to hold the calendar's fields. This is only
\r
497 * necessary if the calendar defines additional fields beyond those
\r
498 * defined by <code>Calendar</code>. The length of the result must be
\r
499 * be between the base and maximum field counts.</li>
\r
501 * <li>Optionally, subclasses may override
\r
502 * {@link #handleGetDateFormat} to create a
\r
503 * <code>DateFormat</code> appropriate to this calendar. This is only
\r
504 * required if a calendar subclass redefines the use of a field (for
\r
505 * example, changes the {@link #ERA} field from a symbolic field
\r
506 * to a numeric one) or defines an additional field.</li>
\r
508 * <li>Optionally, subclasses may override {@link #roll roll} and
\r
509 * {@link #add add} to handle fields that are discontinuous. For
\r
510 * example, in the Hebrew calendar the month "Adar I" only
\r
511 * occurs in leap years; in other years the calendar jumps from
\r
512 * Shevat (month #4) to Adar (month #6). The {@link
\r
513 * HebrewCalendar#add HebrewCalendar.add} and {@link
\r
514 * HebrewCalendar#roll HebrewCalendar.roll} methods take this into
\r
515 * account, so that adding 1 month to Shevat gives the proper result
\r
516 * (Adar) in a non-leap year. The protected utility method {@link
\r
517 * #pinField pinField} is often useful when implementing these two
\r
522 * <p><big><b>Normalized behavior</b></big>
\r
524 * <p>The behavior of certain fields has been made consistent across all
\r
525 * calendar systems and implemented in <code>Calendar</code>.
\r
529 * <li>Time is normalized. Even though some calendar systems transition
\r
530 * between days at sunset or at other times, all ICU4J calendars
\r
531 * transition between days at <em>local zone midnight</em>. This
\r
532 * allows ICU4J to centralize the time computations in
\r
533 * <code>Calendar</code> and to maintain basic correpsondences
\r
534 * between calendar systems. Affected fields: {@link #AM_PM},
\r
535 * {@link #HOUR}, {@link #HOUR_OF_DAY}, {@link #MINUTE},
\r
536 * {@link #SECOND}, {@link #MILLISECOND},
\r
537 * {@link #ZONE_OFFSET}, and {@link #DST_OFFSET}.</li>
\r
539 * <li>DST behavior is normalized. Daylight savings time behavior is
\r
540 * computed the same for all calendar systems, and depends on the
\r
541 * value of several <code>GregorianCalendar</code> fields: the
\r
542 * {@link #YEAR}, {@link #MONTH}, and
\r
543 * {@link #DAY_OF_MONTH}. As a result, <code>Calendar</code>
\r
544 * always computes these fields, even for non-Gregorian calendar
\r
545 * systems. These fields are available to subclasses.</li>
\r
547 * <li>Weeks are normalized. Although locales define the week
\r
548 * differently, in terms of the day on which it starts, and the
\r
549 * designation of week number one of a month or year, they all use a
\r
550 * common mechanism. Furthermore, the day of the week has a simple
\r
551 * and consistent definition throughout history. For example,
\r
552 * although the Gregorian calendar introduced a discontinuity when
\r
553 * first instituted, the day of week was not disrupted. For this
\r
554 * reason, the fields {@link #DAY_OF_WEEK}, <code>WEEK_OF_YEAR,
\r
555 * WEEK_OF_MONTH</code>, {@link #DAY_OF_WEEK_IN_MONTH},
\r
556 * {@link #DOW_LOCAL}, {@link #YEAR_WOY} are all computed in
\r
557 * a consistent way in the base class, based on the
\r
558 * {@link #EXTENDED_YEAR}, {@link #DAY_OF_YEAR},
\r
559 * {@link #MONTH}, and {@link #DAY_OF_MONTH}, which are
\r
560 * computed by the subclass.</li>
\r
564 * <p><big><b>Supported range</b></big>
\r
566 * <p>The allowable range of <code>Calendar</code> has been
\r
567 * narrowed. <code>GregorianCalendar</code> used to attempt to support
\r
568 * the range of dates with millisecond values from
\r
569 * <code>Long.MIN_VALUE</code> to <code>Long.MAX_VALUE</code>. This
\r
570 * introduced awkward constructions (hacks) which slowed down
\r
571 * performance. It also introduced non-uniform behavior at the
\r
572 * boundaries. The new <code>Calendar</code> protocol specifies the
\r
573 * maximum range of supportable dates as those having Julian day numbers
\r
574 * of <code>-0x7F000000</code> to <code>+0x7F000000</code>. This
\r
575 * corresponds to years from ~5,000,000 BCE to ~5,000,000 CE. Programmers
\r
576 * should use the protected constants in <code>Calendar</code> to
\r
577 * specify an extremely early or extremely late date.</p>
\r
579 * <p><big><b>General notes</b></big>
\r
583 * <li>Calendars implementations are <em>proleptic</em>. For example,
\r
584 * even though the Gregorian calendar was not instituted until the
\r
585 * 16th century, the <code>GregorianCalendar</code> class supports
\r
586 * dates before the historical onset of the calendar by extending the
\r
587 * calendar system backward in time. Similarly, the
\r
588 * <code>HebrewCalendar</code> extends backward before the start of
\r
589 * its epoch into zero and negative years. Subclasses do not throw
\r
590 * exceptions because a date precedes the historical start of a
\r
591 * calendar system. Instead, they implement
\r
592 * {@link #handleGetLimit} to return appropriate limits on
\r
593 * {@link #YEAR}, {@link #ERA}, etc. fields. Then, if the
\r
594 * calendar is set to not be lenient, out-of-range field values will
\r
595 * trigger an exception.</li>
\r
597 * <li>Calendar system subclasses compute a <em>extended
\r
598 * year</em>. This differs from the {@link #YEAR} field in that
\r
599 * it ranges over all integer values, including zero and negative
\r
600 * values, and it encapsulates the information of the
\r
601 * {@link #YEAR} field and all larger fields. Thus, for the
\r
602 * Gregorian calendar, the {@link #EXTENDED_YEAR} is computed as
\r
603 * <code>ERA==AD ? YEAR : 1-YEAR</code>. Another example is the Mayan
\r
604 * long count, which has years (<code>KUN</code>) and nested cycles
\r
605 * of years (<code>KATUN</code> and <code>BAKTUN</code>). The Mayan
\r
606 * {@link #EXTENDED_YEAR} is computed as <code>TUN + 20 * (KATUN
\r
607 * + 20 * BAKTUN)</code>. The <code>Calendar</code> base class uses
\r
608 * the {@link #EXTENDED_YEAR} field to compute the week-related
\r
614 * @see GregorianCalendar
\r
617 * @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu, Laura Werner
\r
620 public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {
\r
622 // Data flow in Calendar
\r
623 // ---------------------
\r
625 // The current time is represented in two ways by Calendar: as UTC
\r
626 // milliseconds from the epoch start (1 January 1970 0:00 UTC), and as local
\r
627 // fields such as MONTH, HOUR, AM_PM, etc. It is possible to compute the
\r
628 // millis from the fields, and vice versa. The data needed to do this
\r
629 // conversion is encapsulated by a TimeZone object owned by the Calendar.
\r
630 // The data provided by the TimeZone object may also be overridden if the
\r
631 // user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class
\r
632 // keeps track of what information was most recently set by the caller, and
\r
633 // uses that to compute any other information as needed.
\r
635 // If the user sets the fields using set(), the data flow is as follows.
\r
636 // This is implemented by the Calendar subclass's computeTime() method.
\r
637 // During this process, certain fields may be ignored. The disambiguation
\r
638 // algorithm for resolving which fields to pay attention to is described
\r
641 // local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
\r
643 // | Using Calendar-specific algorithm
\r
645 // local standard millis
\r
647 // | Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET
\r
649 // UTC millis (in time data member)
\r
651 // If the user sets the UTC millis using setTime(), the data flow is as
\r
652 // follows. This is implemented by the Calendar subclass's computeFields()
\r
655 // UTC millis (in time data member)
\r
657 // | Using TimeZone getOffset()
\r
659 // local standard millis
\r
661 // | Using Calendar-specific algorithm
\r
663 // local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
\r
665 // In general, a round trip from fields, through local and UTC millis, and
\r
666 // back out to fields is made when necessary. This is implemented by the
\r
667 // complete() method. Resolving a partial set of fields into a UTC millis
\r
668 // value allows all remaining fields to be generated from that value. If
\r
669 // the Calendar is lenient, the fields are also renormalized to standard
\r
670 // ranges when they are regenerated.
\r
673 * Field number for <code>get</code> and <code>set</code> indicating the
\r
674 * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific
\r
675 * value; see subclass documentation.
\r
676 * @see GregorianCalendar#AD
\r
677 * @see GregorianCalendar#BC
\r
680 public final static int ERA = 0;
\r
683 * Field number for <code>get</code> and <code>set</code> indicating the
\r
684 * year. This is a calendar-specific value; see subclass documentation.
\r
687 public final static int YEAR = 1;
\r
690 * Field number for <code>get</code> and <code>set</code> indicating the
\r
691 * month. This is a calendar-specific value. The first month of the year is
\r
692 * <code>JANUARY</code>; the last depends on the number of months in a year.
\r
708 public final static int MONTH = 2;
\r
711 * Field number for <code>get</code> and <code>set</code> indicating the
\r
712 * week number within the current year. The first week of the year, as
\r
713 * defined by {@link #getFirstDayOfWeek()} and
\r
714 * {@link #getMinimalDaysInFirstWeek()}, has value 1. Subclasses define
\r
715 * the value of {@link #WEEK_OF_YEAR} for days before the first week of
\r
717 * @see #getFirstDayOfWeek
\r
718 * @see #getMinimalDaysInFirstWeek
\r
721 public final static int WEEK_OF_YEAR = 3;
\r
724 * Field number for <code>get</code> and <code>set</code> indicating the
\r
725 * week number within the current month. The first week of the month, as
\r
726 * defined by {@link #getFirstDayOfWeek()} and
\r
727 * {@link #getMinimalDaysInFirstWeek()}, has value 1. Subclasses define
\r
728 * the value of {@link #WEEK_OF_MONTH} for days before the first week of
\r
730 * @see #getFirstDayOfWeek
\r
731 * @see #getMinimalDaysInFirstWeek
\r
734 public final static int WEEK_OF_MONTH = 4;
\r
737 * Field number for <code>get</code> and <code>set</code> indicating the
\r
738 * day of the month. This is a synonym for {@link #DAY_OF_MONTH}.
\r
739 * The first day of the month has value 1.
\r
740 * @see #DAY_OF_MONTH
\r
743 public final static int DATE = 5;
\r
746 * Field number for <code>get</code> and <code>set</code> indicating the
\r
747 * day of the month. This is a synonym for {@link #DATE}.
\r
748 * The first day of the month has value 1.
\r
752 public final static int DAY_OF_MONTH = 5;
\r
755 * Field number for <code>get</code> and <code>set</code> indicating the day
\r
756 * number within the current year. The first day of the year has value 1.
\r
759 public final static int DAY_OF_YEAR = 6;
\r
762 * Field number for <code>get</code> and <code>set</code> indicating the day
\r
763 * of the week. This field takes values {@link #SUNDAY},
\r
764 * {@link #MONDAY}, {@link #TUESDAY}, {@link #WEDNESDAY},
\r
765 * {@link #THURSDAY}, {@link #FRIDAY}, and {@link #SATURDAY}.
\r
775 public final static int DAY_OF_WEEK = 7;
\r
778 * Field number for <code>get</code> and <code>set</code> indicating the
\r
779 * ordinal number of the day of the week within the current month. Together
\r
780 * with the {@link #DAY_OF_WEEK} field, this uniquely specifies a day
\r
781 * within a month. Unlike {@link #WEEK_OF_MONTH} and
\r
782 * {@link #WEEK_OF_YEAR}, this field's value does <em>not</em> depend on
\r
783 * {@link #getFirstDayOfWeek()} or
\r
784 * {@link #getMinimalDaysInFirstWeek()}. <code>DAY_OF_MONTH 1</code>
\r
785 * through <code>7</code> always correspond to <code>DAY_OF_WEEK_IN_MONTH
\r
786 * 1</code>; <code>8</code> through <code>15</code> correspond to
\r
787 * <code>DAY_OF_WEEK_IN_MONTH 2</code>, and so on.
\r
788 * <code>DAY_OF_WEEK_IN_MONTH 0</code> indicates the week before
\r
789 * <code>DAY_OF_WEEK_IN_MONTH 1</code>. Negative values count back from the
\r
790 * end of the month, so the last Sunday of a month is specified as
\r
791 * <code>DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1</code>. Because
\r
792 * negative values count backward they will usually be aligned differently
\r
793 * within the month than positive values. For example, if a month has 31
\r
794 * days, <code>DAY_OF_WEEK_IN_MONTH -1</code> will overlap
\r
795 * <code>DAY_OF_WEEK_IN_MONTH 5</code> and the end of <code>4</code>.
\r
796 * @see #DAY_OF_WEEK
\r
797 * @see #WEEK_OF_MONTH
\r
800 public final static int DAY_OF_WEEK_IN_MONTH = 8;
\r
803 * Field number for <code>get</code> and <code>set</code> indicating
\r
804 * whether the <code>HOUR</code> is before or after noon.
\r
805 * E.g., at 10:04:15.250 PM the <code>AM_PM</code> is <code>PM</code>.
\r
811 public final static int AM_PM = 9;
\r
814 * Field number for <code>get</code> and <code>set</code> indicating the
\r
815 * hour of the morning or afternoon. <code>HOUR</code> is used for the 12-hour
\r
817 * E.g., at 10:04:15.250 PM the <code>HOUR</code> is 10.
\r
819 * @see #HOUR_OF_DAY
\r
822 public final static int HOUR = 10;
\r
825 * Field number for <code>get</code> and <code>set</code> indicating the
\r
826 * hour of the day. <code>HOUR_OF_DAY</code> is used for the 24-hour clock.
\r
827 * E.g., at 10:04:15.250 PM the <code>HOUR_OF_DAY</code> is 22.
\r
831 public final static int HOUR_OF_DAY = 11;
\r
834 * Field number for <code>get</code> and <code>set</code> indicating the
\r
835 * minute within the hour.
\r
836 * E.g., at 10:04:15.250 PM the <code>MINUTE</code> is 4.
\r
839 public final static int MINUTE = 12;
\r
842 * Field number for <code>get</code> and <code>set</code> indicating the
\r
843 * second within the minute.
\r
844 * E.g., at 10:04:15.250 PM the <code>SECOND</code> is 15.
\r
847 public final static int SECOND = 13;
\r
850 * Field number for <code>get</code> and <code>set</code> indicating the
\r
851 * millisecond within the second.
\r
852 * E.g., at 10:04:15.250 PM the <code>MILLISECOND</code> is 250.
\r
855 public final static int MILLISECOND = 14;
\r
858 * Field number for <code>get</code> and <code>set</code> indicating the
\r
859 * raw offset from GMT in milliseconds.
\r
862 public final static int ZONE_OFFSET = 15;
\r
865 * Field number for <code>get</code> and <code>set</code> indicating the
\r
866 * daylight savings offset in milliseconds.
\r
869 public final static int DST_OFFSET = 16;
\r
872 * {@icu} Field number for <code>get()</code> and <code>set()</code>
\r
873 * indicating the extended year corresponding to the
\r
874 * {@link #WEEK_OF_YEAR} field. This may be one greater or less
\r
875 * than the value of {@link #EXTENDED_YEAR}.
\r
878 public static final int YEAR_WOY = 17;
\r
881 * {@icu} Field number for <code>get()</code> and <code>set()</code>
\r
882 * indicating the localized day of week. This will be a value from 1
\r
883 * to 7 inclusive, with 1 being the localized first day of the week.
\r
886 public static final int DOW_LOCAL = 18;
\r
889 * {@icu} Field number for <code>get()</code> and <code>set()</code>
\r
890 * indicating the extended year. This is a single number designating
\r
891 * the year of this calendar system, encompassing all supra-year
\r
892 * fields. For example, for the Julian calendar system, year numbers
\r
893 * are positive, with an era of BCE or CE. An extended year value for
\r
894 * the Julian calendar system assigns positive values to CE years and
\r
895 * negative values to BCE years, with 1 BCE being year 0.
\r
898 public static final int EXTENDED_YEAR = 19;
\r
901 * {@icu} Field number for <code>get()</code> and <code>set()</code>
\r
902 * indicating the modified Julian day number. This is different from
\r
903 * the conventional Julian day number in two regards. First, it
\r
904 * demarcates days at local zone midnight, rather than noon GMT.
\r
905 * Second, it is a local number; that is, it depends on the local time
\r
906 * zone. It can be thought of as a single number that encompasses all
\r
907 * the date-related fields.
\r
910 public static final int JULIAN_DAY = 20;
\r
913 * {@icu} Field number for <code>get()</code> and <code>set()</code>
\r
914 * indicating the milliseconds in the day. This ranges from 0 to
\r
915 * 23:59:59.999 (regardless of DST). This field behaves
\r
916 * <em>exactly</em> like a composite of all time-related fields, not
\r
917 * including the zone fields. As such, it also reflects
\r
918 * discontinuities of those fields on DST transition days. On a day of
\r
919 * DST onset, it will jump forward. On a day of DST cessation, it will
\r
920 * jump backward. This reflects the fact that is must be combined with
\r
921 * the DST_OFFSET field to obtain a unique local time value.
\r
924 public static final int MILLISECONDS_IN_DAY = 21;
\r
927 * {@icu} Field indicating whether or not the current month is a leap month.
\r
928 * Should have a value of 0 for non-leap months, and 1 for leap months.
\r
930 * @provisional This API might change or be removed in a future release.
\r
932 public static final int IS_LEAP_MONTH = 22;
\r
935 * The number of fields defined by this class. Subclasses may define
\r
936 * addition fields starting with this number.
\r
939 protected static final int BASE_FIELD_COUNT = 23;
\r
942 * The maximum number of fields possible. Subclasses must not define
\r
943 * more total fields than this number.
\r
946 protected static final int MAX_FIELD_COUNT = 32;
\r
949 * Value of the <code>DAY_OF_WEEK</code> field indicating
\r
953 public final static int SUNDAY = 1;
\r
956 * Value of the <code>DAY_OF_WEEK</code> field indicating
\r
960 public final static int MONDAY = 2;
\r
963 * Value of the <code>DAY_OF_WEEK</code> field indicating
\r
967 public final static int TUESDAY = 3;
\r
970 * Value of the <code>DAY_OF_WEEK</code> field indicating
\r
974 public final static int WEDNESDAY = 4;
\r
977 * Value of the <code>DAY_OF_WEEK</code> field indicating
\r
981 public final static int THURSDAY = 5;
\r
984 * Value of the <code>DAY_OF_WEEK</code> field indicating
\r
988 public final static int FRIDAY = 6;
\r
991 * Value of the <code>DAY_OF_WEEK</code> field indicating
\r
995 public final static int SATURDAY = 7;
\r
998 * Value of the <code>MONTH</code> field indicating the
\r
999 * first month of the year.
\r
1002 public final static int JANUARY = 0;
\r
1005 * Value of the <code>MONTH</code> field indicating the
\r
1006 * second month of the year.
\r
1009 public final static int FEBRUARY = 1;
\r
1012 * Value of the <code>MONTH</code> field indicating the
\r
1013 * third month of the year.
\r
1016 public final static int MARCH = 2;
\r
1019 * Value of the <code>MONTH</code> field indicating the
\r
1020 * fourth month of the year.
\r
1023 public final static int APRIL = 3;
\r
1026 * Value of the <code>MONTH</code> field indicating the
\r
1027 * fifth month of the year.
\r
1030 public final static int MAY = 4;
\r
1033 * Value of the <code>MONTH</code> field indicating the
\r
1034 * sixth month of the year.
\r
1037 public final static int JUNE = 5;
\r
1040 * Value of the <code>MONTH</code> field indicating the
\r
1041 * seventh month of the year.
\r
1044 public final static int JULY = 6;
\r
1047 * Value of the <code>MONTH</code> field indicating the
\r
1048 * eighth month of the year.
\r
1051 public final static int AUGUST = 7;
\r
1054 * Value of the <code>MONTH</code> field indicating the
\r
1055 * ninth month of the year.
\r
1058 public final static int SEPTEMBER = 8;
\r
1061 * Value of the <code>MONTH</code> field indicating the
\r
1062 * tenth month of the year.
\r
1065 public final static int OCTOBER = 9;
\r
1068 * Value of the <code>MONTH</code> field indicating the
\r
1069 * eleventh month of the year.
\r
1072 public final static int NOVEMBER = 10;
\r
1075 * Value of the <code>MONTH</code> field indicating the
\r
1076 * twelfth month of the year.
\r
1079 public final static int DECEMBER = 11;
\r
1082 * Value of the <code>MONTH</code> field indicating the
\r
1083 * thirteenth month of the year. Although {@link GregorianCalendar}
\r
1084 * does not use this value, lunar calendars do.
\r
1087 public final static int UNDECIMBER = 12;
\r
1090 * Value of the <code>AM_PM</code> field indicating the
\r
1091 * period of the day from midnight to just before noon.
\r
1094 public final static int AM = 0;
\r
1097 * Value of the <code>AM_PM</code> field indicating the
\r
1098 * period of the day from noon to just before midnight.
\r
1101 public final static int PM = 1;
\r
1104 * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
\r
1107 * @see #WEEKEND_ONSET
\r
1108 * @see #WEEKEND_CEASE
\r
1109 * @see #getDayOfWeekType
\r
1112 public static final int WEEKDAY = 0;
\r
1115 * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
\r
1118 * @see #WEEKEND_ONSET
\r
1119 * @see #WEEKEND_CEASE
\r
1120 * @see #getDayOfWeekType
\r
1123 public static final int WEEKEND = 1;
\r
1126 * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
\r
1127 * day that starts as a weekday and transitions to the weekend.
\r
1128 * Call getWeekendTransition() to get the point of transition.
\r
1131 * @see #WEEKEND_CEASE
\r
1132 * @see #getDayOfWeekType
\r
1135 public static final int WEEKEND_ONSET = 2;
\r
1138 * {@icu} Value returned by getDayOfWeekType(int dayOfWeek) to indicate a
\r
1139 * day that starts as the weekend and transitions to a weekday.
\r
1140 * Call getWeekendTransition() to get the point of transition.
\r
1143 * @see #WEEKEND_ONSET
\r
1144 * @see #getDayOfWeekType
\r
1147 public static final int WEEKEND_CEASE = 3;
\r
1150 * The number of milliseconds in one second.
\r
1153 protected static final int ONE_SECOND = 1000;
\r
1156 * The number of milliseconds in one minute.
\r
1159 protected static final int ONE_MINUTE = 60*ONE_SECOND;
\r
1162 * The number of milliseconds in one hour.
\r
1165 protected static final int ONE_HOUR = 60*ONE_MINUTE;
\r
1168 * The number of milliseconds in one day. Although ONE_DAY and
\r
1169 * ONE_WEEK can fit into ints, they must be longs in order to prevent
\r
1170 * arithmetic overflow when performing (bug 4173516).
\r
1173 protected static final long ONE_DAY = 24*ONE_HOUR;
\r
1176 * The number of milliseconds in one week. Although ONE_DAY and
\r
1177 * ONE_WEEK can fit into ints, they must be longs in order to prevent
\r
1178 * arithmetic overflow when performing (bug 4173516).
\r
1181 protected static final long ONE_WEEK = 7*ONE_DAY;
\r
1184 * The Julian day of the Gregorian epoch, that is, January 1, 1 on the
\r
1185 * Gregorian calendar.
\r
1188 protected static final int JAN_1_1_JULIAN_DAY = 1721426;
\r
1191 * The Julian day of the epoch, that is, January 1, 1970 on the
\r
1192 * Gregorian calendar.
\r
1195 protected static final int EPOCH_JULIAN_DAY = 2440588;
\r
1198 * The minimum supported Julian day. This value is equivalent to
\r
1199 * {@link #MIN_MILLIS} and {@link #MIN_DATE}.
\r
1200 * @see #JULIAN_DAY
\r
1203 protected static final int MIN_JULIAN = -0x7F000000;
\r
1206 * The minimum supported epoch milliseconds. This value is equivalent
\r
1207 * to {@link #MIN_JULIAN} and {@link #MIN_DATE}.
\r
1210 protected static final long MIN_MILLIS = -184303902528000000L;
\r
1212 // Get around bug in jikes 1.12 for now. Later, use:
\r
1213 //protected static final long MIN_MILLIS = (MIN_JULIAN - EPOCH_JULIAN_DAY) * ONE_DAY;
\r
1216 * The minimum supported <code>Date</code>. This value is equivalent
\r
1217 * to {@link #MIN_JULIAN} and {@link #MIN_MILLIS}.
\r
1220 protected static final Date MIN_DATE = new Date(MIN_MILLIS);
\r
1223 * The maximum supported Julian day. This value is equivalent to
\r
1224 * {@link #MAX_MILLIS} and {@link #MAX_DATE}.
\r
1225 * @see #JULIAN_DAY
\r
1228 protected static final int MAX_JULIAN = +0x7F000000;
\r
1231 * The maximum supported epoch milliseconds. This value is equivalent
\r
1232 * to {@link #MAX_JULIAN} and {@link #MAX_DATE}.
\r
1235 protected static final long MAX_MILLIS = (MAX_JULIAN - EPOCH_JULIAN_DAY) * ONE_DAY;
\r
1238 * The maximum supported <code>Date</code>. This value is equivalent
\r
1239 * to {@link #MAX_JULIAN} and {@link #MAX_MILLIS}.
\r
1242 protected static final Date MAX_DATE = new Date(MAX_MILLIS);
\r
1244 // Internal notes:
\r
1245 // Calendar contains two kinds of time representations: current "time" in
\r
1246 // milliseconds, and a set of time "fields" representing the current time.
\r
1247 // The two representations are usually in sync, but can get out of sync
\r
1249 // 1. Initially, no fields are set, and the time is invalid.
\r
1250 // 2. If the time is set, all fields are computed and in sync.
\r
1251 // 3. If a single field is set, the time is invalid.
\r
1252 // Recomputation of the time and fields happens when the object needs
\r
1253 // to return a result to the user, or use a result for a computation.
\r
1256 * The field values for the currently set time for this calendar.
\r
1257 * This is an array of at least {@link #BASE_FIELD_COUNT} integers.
\r
1258 * @see #handleCreateFields
\r
1261 private transient int fields[];
\r
1264 * Pseudo-time-stamps which specify when each field was set. There
\r
1265 * are two special values, UNSET and INTERNALLY_SET. Values from
\r
1266 * MINIMUM_USER_SET to Integer.MAX_VALUE are legal user set values.
\r
1268 private transient int stamp[];
\r
1271 * The currently set time for this calendar, expressed in milliseconds after
\r
1272 * January 1, 1970, 0:00:00 GMT.
\r
1275 private long time;
\r
1278 * True if then the value of <code>time</code> is valid.
\r
1279 * The time is made invalid by a change to an item of <code>field[]</code>.
\r
1283 private transient boolean isTimeSet;
\r
1286 * True if <code>fields[]</code> are in sync with the currently set time.
\r
1287 * If false, then the next attempt to get the value of a field will
\r
1288 * force a recomputation of all fields from the current value of
\r
1289 * <code>time</code>.
\r
1292 private transient boolean areFieldsSet;
\r
1295 * True if all fields have been set. This is only false in a few
\r
1296 * situations: In a newly created, partially constructed object. After
\r
1297 * a call to clear(). In an object just read from a stream using
\r
1298 * readObject(). Once computeFields() has been called this is set to
\r
1299 * true and stays true until one of the above situations recurs.
\r
1302 private transient boolean areAllFieldsSet;
\r
1305 * True if all fields have been virtually set, but have not yet been
\r
1306 * computed. This occurs only in setTimeInMillis(), or after readObject().
\r
1307 * A calendar set to this state will compute all fields from the time if it
\r
1308 * becomes necessary, but otherwise will delay such computation.
\r
1310 private transient boolean areFieldsVirtuallySet;
\r
1313 * True if this calendar allows out-of-range field values during computation
\r
1314 * of <code>time</code> from <code>fields[]</code>.
\r
1315 * @see #setLenient
\r
1318 private boolean lenient = true;
\r
1321 * The {@link TimeZone} used by this calendar. {@link Calendar}
\r
1322 * uses the time zone data to translate between local and GMT time.
\r
1325 private TimeZone zone;
\r
1328 * The first day of the week, with possible values {@link #SUNDAY},
\r
1329 * {@link #MONDAY}, etc. This is a locale-dependent value.
\r
1332 private int firstDayOfWeek;
\r
1335 * The number of days required for the first week in a month or year,
\r
1336 * with possible values from 1 to 7. This is a locale-dependent value.
\r
1339 private int minimalDaysInFirstWeek;
\r
1342 * First day of the weekend in this calendar's locale. Must be in
\r
1343 * the range SUNDAY...SATURDAY (1..7). The weekend starts at
\r
1344 * weekendOnsetMillis milliseconds after midnight on that day of
\r
1345 * the week. This value is taken from locale resource data.
\r
1347 private int weekendOnset;
\r
1350 * Milliseconds after midnight at which the weekend starts on the
\r
1351 * day of the week weekendOnset. Times that are greater than or
\r
1352 * equal to weekendOnsetMillis are considered part of the weekend.
\r
1353 * Must be in the range 0..24*60*60*1000-1. This value is taken
\r
1354 * from locale resource data.
\r
1356 private int weekendOnsetMillis;
\r
1359 * Day of the week when the weekend stops in this calendar's
\r
1360 * locale. Must be in the range SUNDAY...SATURDAY (1..7). The
\r
1361 * weekend stops at weekendCeaseMillis milliseconds after midnight
\r
1362 * on that day of the week. This value is taken from locale
\r
1365 private int weekendCease;
\r
1368 * Milliseconds after midnight at which the weekend stops on the
\r
1369 * day of the week weekendCease. Times that are greater than or
\r
1370 * equal to weekendCeaseMillis are considered not to be the
\r
1371 * weekend. Must be in the range 0..24*60*60*1000-1. This value
\r
1372 * is taken from locale resource data.
\r
1374 private int weekendCeaseMillis;
\r
1377 * Cache to hold the firstDayOfWeek and minimalDaysInFirstWeek
\r
1380 private static Hashtable<ULocale, WeekData> cachedLocaleData = new Hashtable<ULocale, WeekData>(3);
\r
1383 * Value of the time stamp <code>stamp[]</code> indicating that
\r
1384 * a field has not been set since the last call to <code>clear()</code>.
\r
1385 * @see #INTERNALLY_SET
\r
1386 * @see #MINIMUM_USER_STAMP
\r
1389 protected static final int UNSET = 0;
\r
1392 * Value of the time stamp <code>stamp[]</code> indicating that a field
\r
1393 * has been set via computations from the time or from other fields.
\r
1395 * @see #MINIMUM_USER_STAMP
\r
1398 protected static final int INTERNALLY_SET = 1;
\r
1401 * If the time stamp <code>stamp[]</code> has a value greater than or
\r
1402 * equal to <code>MINIMUM_USER_SET</code> then it has been set by the
\r
1403 * user via a call to <code>set()</code>.
\r
1405 * @see #INTERNALLY_SET
\r
1408 protected static final int MINIMUM_USER_STAMP = 2;
\r
1411 * The next available value for <code>stamp[]</code>, an internal array.
\r
1414 private transient int nextStamp = MINIMUM_USER_STAMP;
\r
1416 // the internal serial version which says which version was written
\r
1417 // - 0 (default) for version up to JDK 1.1.5
\r
1418 // - 1 for version from JDK 1.1.6, which writes a correct 'time' value
\r
1419 // as well as compatible values for other fields. This is a
\r
1420 // transitional format.
\r
1421 // - 2 (not implemented yet) a future version, in which fields[],
\r
1422 // areFieldsSet, and isTimeSet become transient, and isSet[] is
\r
1423 // removed. In JDK 1.1.6 we write a format compatible with version 2.
\r
1424 // static final int currentSerialVersion = 1;
\r
1427 * The version of the serialized data on the stream. Possible values:
\r
1429 * <dt><b>0</b> or not present on stream</dt>
\r
1431 * JDK 1.1.5 or earlier.
\r
1433 * <dt><b>1</b></dt>
\r
1435 * JDK 1.1.6 or later. Writes a correct 'time' value
\r
1436 * as well as compatible values for other fields. This is a
\r
1437 * transitional format.
\r
1440 * When streaming out this class, the most recent format
\r
1441 * and the highest allowable <code>serialVersionOnStream</code>
\r
1446 // private int serialVersionOnStream = currentSerialVersion;
\r
1448 // Proclaim serialization compatibility with JDK 1.1
\r
1449 // static final long serialVersionUID = -1807547505821590642L;
\r
1451 // haven't been compatible for awhile, no longer try
\r
1452 // jdk1.4.2 serialver
\r
1453 private static final long serialVersionUID = 6222646104888790989L;
\r
1456 * Bitmask for internalSet() defining which fields may legally be set
\r
1457 * by subclasses. Any attempt to set a field not in this bitmask
\r
1458 * results in an exception, because such fields must be set by the base
\r
1461 private transient int internalSetMask;
\r
1464 * The Gregorian year, as computed by computeGregorianFields() and
\r
1465 * returned by getGregorianYear().
\r
1467 private transient int gregorianYear;
\r
1470 * The Gregorian month, as computed by computeGregorianFields() and
\r
1471 * returned by getGregorianMonth().
\r
1473 private transient int gregorianMonth;
\r
1476 * The Gregorian day of the year, as computed by
\r
1477 * computeGregorianFields() and returned by getGregorianDayOfYear().
\r
1479 private transient int gregorianDayOfYear;
\r
1482 * The Gregorian day of the month, as computed by
\r
1483 * computeGregorianFields() and returned by getGregorianDayOfMonth().
\r
1485 private transient int gregorianDayOfMonth;
\r
1488 * Constructs a Calendar with the default time zone
\r
1490 * @see TimeZone#getDefault
\r
1493 protected Calendar()
\r
1495 this(TimeZone.getDefault(), ULocale.getDefault());
\r
1499 * Constructs a calendar with the specified time zone and locale.
\r
1500 * @param zone the time zone to use
\r
1501 * @param aLocale the locale for the week data
\r
1504 protected Calendar(TimeZone zone, Locale aLocale)
\r
1506 this(zone, ULocale.forLocale(aLocale));
\r
1510 * Constructs a calendar with the specified time zone and locale.
\r
1511 * @param zone the time zone to use
\r
1512 * @param locale the ulocale for the week data
\r
1515 protected Calendar(TimeZone zone, ULocale locale)
\r
1518 setWeekData(locale);
\r
1522 private void initInternal()
\r
1524 // Allocate fields through the framework method. Subclasses
\r
1525 // may override this to define additional fields.
\r
1526 fields = handleCreateFields();
\r
1528 // todo: fix, difficult to test without subclassing
\r
1529 if (fields == null || fields.length < BASE_FIELD_COUNT ||
\r
1530 fields.length > MAX_FIELD_COUNT) {
\r
1531 throw new IllegalStateException("Invalid fields[]");
\r
1534 stamp = new int[fields.length];
\r
1535 int mask = (1 << ERA) |
\r
1538 (1 << DAY_OF_MONTH) |
\r
1539 (1 << DAY_OF_YEAR) |
\r
1540 (1 << EXTENDED_YEAR) |
\r
1541 (1 << IS_LEAP_MONTH);
\r
1542 for (int i=BASE_FIELD_COUNT; i<fields.length; ++i) {
\r
1545 internalSetMask = mask;
\r
1549 * Returns a calendar using the default time zone and locale.
\r
1550 * @return a Calendar.
\r
1553 public static synchronized Calendar getInstance()
\r
1555 return getInstanceInternal(null, null);
\r
1559 * Returns a calendar using the specified time zone and default locale.
\r
1560 * @param zone the time zone to use
\r
1561 * @return a Calendar.
\r
1564 public static synchronized Calendar getInstance(TimeZone zone)
\r
1566 return getInstanceInternal(zone, null);
\r
1570 * Returns a calendar using the default time zone and specified locale.
\r
1571 * @param aLocale the locale for the week data
\r
1572 * @return a Calendar.
\r
1575 public static synchronized Calendar getInstance(Locale aLocale)
\r
1577 return getInstanceInternal(null, ULocale.forLocale(aLocale));
\r
1581 * Returns a calendar using the default time zone and specified locale.
\r
1582 * @param locale the ulocale for the week data
\r
1583 * @return a Calendar.
\r
1586 public static synchronized Calendar getInstance(ULocale locale)
\r
1588 return getInstanceInternal(null, locale);
\r
1592 * Returns a calendar with the specified time zone and locale.
\r
1593 * @param zone the time zone to use
\r
1594 * @param aLocale the locale for the week data
\r
1595 * @return a Calendar.
\r
1598 public static synchronized Calendar getInstance(TimeZone zone,
\r
1600 return getInstanceInternal(zone, ULocale.forLocale(aLocale));
\r
1604 * Returns a calendar with the specified time zone and locale.
\r
1605 * @param zone the time zone to use
\r
1606 * @param locale the ulocale for the week data
\r
1607 * @return a Calendar.
\r
1610 public static synchronized Calendar getInstance(TimeZone zone,
\r
1612 return getInstanceInternal(zone, locale);
\r
1616 * All getInstance implementations call this private method to create a new
\r
1617 * Calendar instance.
\r
1619 private static Calendar getInstanceInternal(TimeZone tz, ULocale locale) {
\r
1620 if (locale == null) {
\r
1621 locale = ULocale.getDefault();
\r
1624 tz = TimeZone.getDefault();
\r
1626 Calendar cal = getShim().createInstance(locale);
\r
1627 cal.setTimeZone(tz);
\r
1628 cal.setTimeInMillis(System.currentTimeMillis());
\r
1632 private static final String[] calTypes = {
\r
1645 "ethiopic-amete-alem",
\r
1648 // must be in the order of calTypes above
\r
1649 private static final int CALTYPE_GREGORIAN = 0;
\r
1650 private static final int CALTYPE_JAPANESE = 1;
\r
1651 private static final int CALTYPE_BUDDHIST = 2;
\r
1652 private static final int CALTYPE_ROC = 3;
\r
1653 private static final int CALTYPE_PERSIAN = 4; // not yet implemented
\r
1654 private static final int CALTYPE_ISLAMIC_CIVIL = 5;
\r
1655 private static final int CALTYPE_ISLAMIC = 6;
\r
1656 private static final int CALTYPE_HEBREW = 7;
\r
1657 private static final int CALTYPE_CHINESE = 8;
\r
1658 private static final int CALTYPE_INDIAN = 9;
\r
1659 private static final int CALTYPE_COPTIC = 10;
\r
1660 private static final int CALTYPE_ETHIOPIC = 11;
\r
1661 private static final int CALTYPE_ETHIOPIC_AMETE_ALEM = 12;
\r
1662 private static final int CALTYPE_UNKNOWN = -1;
\r
1664 private static int getCalendarTypeForLocale(ULocale l) {
\r
1665 String s = CalendarUtil.getCalendarType(l);
\r
1667 s = s.toLowerCase();
\r
1668 for (int i = 0; i < calTypes.length; ++i) {
\r
1669 if (s.equals(calTypes[i])) {
\r
1674 return CALTYPE_UNKNOWN;
\r
1678 * Returns the list of locales for which Calendars are installed.
\r
1679 * @return the list of locales for which Calendars are installed.
\r
1682 public static Locale[] getAvailableLocales()
\r
1684 if (shim == null) {
\r
1685 return ICUResourceBundle.getAvailableLocales();
\r
1687 return getShim().getAvailableLocales();
\r
1691 * {@icu} Returns the list of locales for which Calendars are installed.
\r
1692 * @return the list of locales for which Calendars are installed.
\r
1693 * @draft ICU 3.2 (retain)
\r
1694 * @provisional This API might change or be removed in a future release.
\r
1696 public static ULocale[] getAvailableULocales()
\r
1698 if (shim == null) {
\r
1699 return ICUResourceBundle.getAvailableULocales();
\r
1701 return getShim().getAvailableULocales();
\r
1704 // ==== Factory Stuff ====
\r
1706 * A CalendarFactory is used to register new calendar implementation.
\r
1707 * The factory should be able to create a calendar instance for the
\r
1708 * specified locale.
\r
1712 /* public */ static abstract class CalendarFactory {
\r
1713 public boolean visible() {
\r
1717 public abstract Set<String> getSupportedLocaleNames();
\r
1719 public Calendar createCalendar(ULocale loc) {
\r
1723 protected CalendarFactory() {
\r
1727 // shim so we can build without service code
\r
1728 static abstract class CalendarShim {
\r
1729 abstract Locale[] getAvailableLocales();
\r
1730 abstract ULocale[] getAvailableULocales();
\r
1731 abstract Object registerFactory(CalendarFactory factory);
\r
1732 abstract boolean unregister(Object k);
\r
1733 abstract Calendar createInstance(ULocale l);
\r
1736 private static CalendarShim shim;
\r
1737 private static CalendarShim getShim() {
\r
1738 if (shim == null) {
\r
1740 Class<?> cls = Class.forName("com.ibm.icu.util.CalendarServiceShim");
\r
1741 shim = (CalendarShim)cls.newInstance();
\r
1743 catch (MissingResourceException e) {
\r
1746 catch (Exception e) {
\r
1747 throw new RuntimeException(e.getMessage());
\r
1753 static Calendar createInstance(ULocale locale) {
\r
1754 Calendar cal = null;
\r
1755 TimeZone zone = TimeZone.getDefault();
\r
1756 int calType = getCalendarTypeForLocale(locale);
\r
1757 if (calType == CALTYPE_UNKNOWN) {
\r
1758 // fallback to Gregorian
\r
1759 calType = CALTYPE_GREGORIAN;
\r
1762 switch (calType) {
\r
1763 case CALTYPE_GREGORIAN:
\r
1764 cal = new GregorianCalendar(zone, locale);
\r
1766 case CALTYPE_JAPANESE:
\r
1767 cal = new JapaneseCalendar(zone, locale);
\r
1769 case CALTYPE_BUDDHIST:
\r
1770 cal = new BuddhistCalendar(zone, locale);
\r
1773 cal = new TaiwanCalendar(zone, locale);
\r
1775 case CALTYPE_PERSIAN:
\r
1776 // Not yet implemented in ICU4J
\r
1777 cal = new GregorianCalendar(zone, locale);
\r
1779 case CALTYPE_ISLAMIC_CIVIL:
\r
1780 cal = new IslamicCalendar(zone, locale);
\r
1782 case CALTYPE_ISLAMIC:
\r
1783 cal = new IslamicCalendar(zone, locale);
\r
1784 ((IslamicCalendar)cal).setCivil(false);
\r
1786 case CALTYPE_HEBREW:
\r
1787 cal = new HebrewCalendar(zone, locale);
\r
1789 case CALTYPE_CHINESE:
\r
1790 cal = new ChineseCalendar(zone, locale);
\r
1792 case CALTYPE_INDIAN:
\r
1793 cal = new IndianCalendar(zone, locale);
\r
1795 case CALTYPE_COPTIC:
\r
1796 cal = new CopticCalendar(zone, locale);
\r
1798 case CALTYPE_ETHIOPIC:
\r
1799 cal = new EthiopicCalendar(zone, locale);
\r
1801 case CALTYPE_ETHIOPIC_AMETE_ALEM:
\r
1802 cal = new EthiopicCalendar(zone, locale);
\r
1803 ((EthiopicCalendar)cal).setAmeteAlemEra(true);
\r
1806 // we must not get here, because unknown type is mapped to
\r
1807 // Gregorian at the beginning of this method.
\r
1808 throw new IllegalArgumentException("Unknown calendar type");
\r
1816 * Register a new CalendarFactory. getInstance(TimeZone, ULocale, String) will
\r
1817 * try to locate a registered factories matching the factoryName. Only registered
\r
1818 * factories will be found.
\r
1821 /* public */ static Object registerFactory(CalendarFactory factory) {
\r
1822 if (factory == null) {
\r
1823 throw new IllegalArgumentException("factory must not be null");
\r
1825 return getShim().registerFactory(factory);
\r
1829 * Unregister the CalendarFactory associated with this key
\r
1830 * (obtained from register).
\r
1833 /* public */ static boolean unregister(Object registryKey) {
\r
1834 if (registryKey == null) {
\r
1835 throw new IllegalArgumentException("registryKey must not be null");
\r
1838 if (shim == null) {
\r
1842 return shim.unregister(registryKey);
\r
1846 // ==== End of factory Stuff ====
\r
1848 // //TODO: The table below should be retrieved from ICU resource when CLDR supplementalData
\r
1849 // // is fully updated.
\r
1850 // private static final String[][] CALPREF = {
\r
1851 // {"001", "gregorian"},
\r
1852 // {"AE", "gregorian", "islamic", "islamic-civil"},
\r
1853 // {"AF", "gregorian", "islamic", "islamic-civil", "persian"},
\r
1854 // {"BH", "gregorian", "islamic", "islamic-civil"},
\r
1855 // {"CN", "gregorian", "chinese"},
\r
1856 // {"CX", "gregorian", "chinese"},
\r
1857 // {"DJ", "gregorian", "islamic", "islamic-civil"},
\r
1858 // {"DZ", "gregorian", "islamic", "islamic-civil"},
\r
1859 // {"EG", "gregorian", "islamic", "islamic-civil", "coptic"},
\r
1860 // {"EH", "gregorian", "islamic", "islamic-civil"},
\r
1861 // {"ER", "gregorian", "islamic", "islamic-civil"},
\r
1862 // {"ET", "gregorian", "ethiopic", "ethiopic-amete-alem"},
\r
1863 // {"HK", "gregorian", "chinese"},
\r
1864 // {"IL", "gregorian", "hebrew"},
\r
1865 // {"IL", "gregorian", "islamic", "islamic-civil"},
\r
1866 // {"IN", "gregorian", "indian"},
\r
1867 // {"IQ", "gregorian", "islamic", "islamic-civil"},
\r
1868 // {"IR", "gregorian", "islamic", "islamic-civil", "persian"},
\r
1869 // {"JO", "gregorian", "islamic", "islamic-civil"},
\r
1870 // {"JP", "gregorian", "japanese"},
\r
1871 // {"KM", "gregorian", "islamic", "islamic-civil"},
\r
1872 // {"KW", "gregorian", "islamic", "islamic-civil"},
\r
1873 // {"LB", "gregorian", "islamic", "islamic-civil"},
\r
1874 // {"LY", "gregorian", "islamic", "islamic-civil"},
\r
1875 // {"MA", "gregorian", "islamic", "islamic-civil"},
\r
1876 // {"MO", "gregorian", "chinese"},
\r
1877 // {"MR", "gregorian", "islamic", "islamic-civil"},
\r
1878 // {"OM", "gregorian", "islamic", "islamic-civil"},
\r
1879 // {"PS", "gregorian", "islamic", "islamic-civil"},
\r
1880 // {"QA", "gregorian", "islamic", "islamic-civil"},
\r
1881 // {"SA", "gregorian", "islamic", "islamic-civil"},
\r
1882 // {"SD", "gregorian", "islamic", "islamic-civil"},
\r
1883 // {"SG", "gregorian", "chinese"},
\r
1884 // {"SY", "gregorian", "islamic", "islamic-civil"},
\r
1885 // {"TD", "gregorian", "islamic", "islamic-civil"},
\r
1886 // {"TH", "buddhist", "gregorian"},
\r
1887 // {"TN", "gregorian", "islamic", "islamic-civil"},
\r
1888 // {"TW", "gregorian", "roc", "chinese"},
\r
1889 // {"YE", "gregorian", "islamic", "islamic-civil"},
\r
1893 * {@icu} Given a key and a locale, returns an array of string values in a preferred
\r
1894 * order that would make a difference. These are all and only those values where
\r
1895 * the open (creation) of the service with the locale formed from the input locale
\r
1896 * plus input keyword and that value has different behavior than creation with the
\r
1897 * input locale alone.
\r
1898 * @param key one of the keys supported by this service. For now, only
\r
1899 * "calendar" is supported.
\r
1900 * @param locale the locale
\r
1901 * @param commonlyUsed if set to true it will return only commonly used values
\r
1902 * with the given locale in preferred order. Otherwise,
\r
1903 * it will return all the available values for the locale.
\r
1904 * @return an array of string values for the given key and the locale.
\r
1907 public static final String[] getKeywordValuesForLocale(String key, ULocale locale,
\r
1908 boolean commonlyUsed) {
\r
1910 String prefRegion = locale.getCountry();
\r
1911 if (prefRegion.length() == 0){
\r
1912 ULocale loc = ULocale.addLikelySubtags(locale);
\r
1913 prefRegion = loc.getCountry();
\r
1916 // Read preferred calendar values from supplementalData calendarPreferences
\r
1917 ArrayList<String> values = new ArrayList<String>();
\r
1919 UResourceBundle rb = UResourceBundle.getBundleInstance(
\r
1920 ICUResourceBundle.ICU_BASE_NAME,
\r
1921 "supplementalData",
\r
1922 ICUResourceBundle.ICU_DATA_CLASS_LOADER);
\r
1923 UResourceBundle calPref = rb.get("calendarPreferenceData");
\r
1924 UResourceBundle order = null;
\r
1926 order = calPref.get(prefRegion);
\r
1927 } catch (MissingResourceException mre) {
\r
1928 // use "001" as fallback
\r
1929 order = calPref.get("001");
\r
1932 String[] caltypes = order.getStringArray();
\r
1933 if (commonlyUsed) {
\r
1934 // we have all commonly used calendar for the target region
\r
1938 // if not commonlyUsed, add all preferred calendars in the order
\r
1939 for (int i = 0; i < caltypes.length; i++) {
\r
1940 values.add(caltypes[i]);
\r
1942 // then, add other available clanedars
\r
1943 for (int i = 0; i < calTypes.length; i++) {
\r
1944 if (!values.contains(calTypes[i])) {
\r
1945 values.add(calTypes[i]);
\r
1948 return values.toArray(new String[values.size()]);
\r
1952 * Returns this Calendar's current time.
\r
1953 * @return the current time.
\r
1956 public final Date getTime() {
\r
1957 return new Date( getTimeInMillis() );
\r
1961 * Sets this Calendar's current time with the given Date.
\r
1963 * <p>Note: Calling <code>setTime</code> with
\r
1964 * <code>Date(Long.MAX_VALUE)</code> or <code>Date(Long.MIN_VALUE)</code>
\r
1965 * may yield incorrect field values from {@link #get(int)}.
\r
1966 * @param date the given Date.
\r
1969 public final void setTime(Date date) {
\r
1970 setTimeInMillis( date.getTime() );
\r
1974 * Returns this Calendar's current time as a long.
\r
1975 * @return the current time as UTC milliseconds from the epoch.
\r
1978 public long getTimeInMillis() {
\r
1979 if (!isTimeSet) updateTime();
\r
1984 * Sets this Calendar's current time from the given long value.
\r
1985 * @param millis the new time in UTC milliseconds from the epoch.
\r
1988 public void setTimeInMillis( long millis ) {
\r
1989 if (millis > MAX_MILLIS) {
\r
1990 millis = MAX_MILLIS;
\r
1991 } else if (millis < MIN_MILLIS) {
\r
1992 millis = MIN_MILLIS;
\r
1995 areFieldsSet = areAllFieldsSet = false;
\r
1996 isTimeSet = areFieldsVirtuallySet = true;
\r
1998 for (int i=0; i<fields.length; ++i) {
\r
1999 fields[i] = stamp[i] = 0; // UNSET == 0
\r
2005 * Returns the value for a given time field.
\r
2006 * @param field the given time field.
\r
2007 * @return the value for the given time field.
\r
2010 public final int get(int field)
\r
2013 return fields[field];
\r
2017 * Returns the value for a given time field. This is an internal method
\r
2018 * for subclasses that does <em>not</em> trigger any calculations.
\r
2019 * @param field the given time field.
\r
2020 * @return the value for the given time field.
\r
2023 protected final int internalGet(int field)
\r
2025 return fields[field];
\r
2029 * Returns the value for a given time field, or return the given default
\r
2030 * value if the field is not set. This is an internal method for
\r
2031 * subclasses that does <em>not</em> trigger any calculations.
\r
2032 * @param field the given time field.
\r
2033 * @param defaultValue value to return if field is not set
\r
2034 * @return the value for the given time field of defaultValue if the
\r
2038 protected final int internalGet(int field, int defaultValue) {
\r
2039 return (stamp[field] > UNSET) ? fields[field] : defaultValue;
\r
2043 * Sets the time field with the given value.
\r
2044 * @param field the given time field.
\r
2045 * @param value the value to be set for the given time field.
\r
2048 public final void set(int field, int value)
\r
2050 if (areFieldsVirtuallySet) {
\r
2053 fields[field] = value;
\r
2054 stamp[field] = nextStamp++;
\r
2055 isTimeSet = areFieldsSet = areFieldsVirtuallySet = false;
\r
2059 * Sets the values for the fields year, month, and date.
\r
2060 * Previous values of other fields are retained. If this is not desired,
\r
2061 * call {@link #clear()} first.
\r
2062 * @param year the value used to set the YEAR time field.
\r
2063 * @param month the value used to set the MONTH time field.
\r
2064 * Month value is 0-based. e.g., 0 for January.
\r
2065 * @param date the value used to set the DATE time field.
\r
2068 public final void set(int year, int month, int date)
\r
2071 set(MONTH, month);
\r
2076 * Sets the values for the fields year, month, date, hour, and minute.
\r
2077 * Previous values of other fields are retained. If this is not desired,
\r
2078 * call {@link #clear()} first.
\r
2079 * @param year the value used to set the YEAR time field.
\r
2080 * @param month the value used to set the MONTH time field.
\r
2081 * Month value is 0-based. e.g., 0 for January.
\r
2082 * @param date the value used to set the DATE time field.
\r
2083 * @param hour the value used to set the HOUR_OF_DAY time field.
\r
2084 * @param minute the value used to set the MINUTE time field.
\r
2087 public final void set(int year, int month, int date, int hour, int minute)
\r
2090 set(MONTH, month);
\r
2092 set(HOUR_OF_DAY, hour);
\r
2093 set(MINUTE, minute);
\r
2097 * Sets the values for the fields year, month, date, hour, minute, and second.
\r
2098 * Previous values of other fields are retained. If this is not desired,
\r
2099 * call {@link #clear} first.
\r
2100 * @param year the value used to set the YEAR time field.
\r
2101 * @param month the value used to set the MONTH time field.
\r
2102 * Month value is 0-based. e.g., 0 for January.
\r
2103 * @param date the value used to set the DATE time field.
\r
2104 * @param hour the value used to set the HOUR_OF_DAY time field.
\r
2105 * @param minute the value used to set the MINUTE time field.
\r
2106 * @param second the value used to set the SECOND time field.
\r
2109 public final void set(int year, int month, int date, int hour, int minute,
\r
2113 set(MONTH, month);
\r
2115 set(HOUR_OF_DAY, hour);
\r
2116 set(MINUTE, minute);
\r
2117 set(SECOND, second);
\r
2121 * Clears the values of all the time fields.
\r
2124 public final void clear()
\r
2126 for (int i=0; i<fields.length; ++i) {
\r
2127 fields[i] = stamp[i] = 0; // UNSET == 0
\r
2129 isTimeSet = areFieldsSet = areAllFieldsSet = areFieldsVirtuallySet = false;
\r
2133 * Clears the value in the given time field.
\r
2134 * @param field the time field to be cleared.
\r
2137 public final void clear(int field)
\r
2139 if (areFieldsVirtuallySet) {
\r
2142 fields[field] = 0;
\r
2143 stamp[field] = UNSET;
\r
2144 isTimeSet = areFieldsSet = areAllFieldsSet = areFieldsVirtuallySet = false;
\r
2148 * Determines if the given time field has a value set.
\r
2149 * @return true if the given time field has a value set; false otherwise.
\r
2152 public final boolean isSet(int field)
\r
2154 return areFieldsVirtuallySet || (stamp[field] != UNSET);
\r
2158 * Fills in any unset fields in the time field list.
\r
2161 protected void complete()
\r
2163 if (!isTimeSet) updateTime();
\r
2164 if (!areFieldsSet) {
\r
2165 computeFields(); // fills in unset fields
\r
2166 areFieldsSet = true;
\r
2167 areAllFieldsSet = true;
\r
2172 * Compares this calendar to the specified object.
\r
2173 * The result is <code>true</code> if and only if the argument is
\r
2174 * not <code>null</code> and is a <code>Calendar</code> object that
\r
2175 * represents the same calendar as this object.
\r
2176 * @param obj the object to compare with.
\r
2177 * @return <code>true</code> if the objects are the same;
\r
2178 * <code>false</code> otherwise.
\r
2181 public boolean equals(Object obj) {
\r
2182 if (this == obj) {
\r
2185 if (this.getClass() != obj.getClass()) {
\r
2189 Calendar that = (Calendar) obj;
\r
2191 return isEquivalentTo(that) &&
\r
2192 getTimeInMillis() == that.getTime().getTime();
\r
2196 * {@icu} Returns true if the given Calendar object is equivalent to this
\r
2197 * one. An equivalent Calendar will behave exactly as this one
\r
2198 * does, but it may be set to a different time. By contrast, for
\r
2199 * the equals() method to return true, the other Calendar must
\r
2200 * be set to the same time.
\r
2202 * @param other the Calendar to be compared with this Calendar
\r
2205 public boolean isEquivalentTo(Calendar other) {
\r
2206 return this.getClass() == other.getClass() &&
\r
2207 isLenient() == other.isLenient() &&
\r
2208 getFirstDayOfWeek() == other.getFirstDayOfWeek() &&
\r
2209 getMinimalDaysInFirstWeek() == other.getMinimalDaysInFirstWeek() &&
\r
2210 getTimeZone().equals(other.getTimeZone());
\r
2214 * Returns a hash code for this calendar.
\r
2215 * @return a hash code value for this object.
\r
2218 public int hashCode() {
\r
2219 /* Don't include the time because (a) we don't want the hash value to
\r
2220 * move around just because a calendar is set to different times, and
\r
2221 * (b) we don't want to trigger a time computation just to get a hash.
\r
2222 * Note that it is not necessary for unequal objects to always have
\r
2223 * unequal hashes, but equal objects must have equal hashes. */
\r
2224 return (lenient ? 1 : 0)
\r
2225 | (firstDayOfWeek << 1)
\r
2226 | (minimalDaysInFirstWeek << 4)
\r
2227 | (zone.hashCode() << 7);
\r
2231 * Returns the difference in milliseconds between the moment this
\r
2232 * calendar is set to and the moment the given calendar or Date object
\r
2235 private long compare(Object that) {
\r
2237 if (that instanceof Calendar) {
\r
2238 thatMs = ((Calendar)that).getTimeInMillis();
\r
2239 } else if (that instanceof Date) {
\r
2240 thatMs = ((Date)that).getTime();
\r
2242 throw new IllegalArgumentException(that + "is not a Calendar or Date");
\r
2244 return getTimeInMillis() - thatMs;
\r
2248 * Compares the time field records.
\r
2249 * Equivalent to comparing result of conversion to UTC.
\r
2250 * @param when the Calendar to be compared with this Calendar.
\r
2251 * @return true if the current time of this Calendar is before
\r
2252 * the time of Calendar when; false otherwise.
\r
2255 public boolean before(Object when) {
\r
2256 return compare(when) < 0;
\r
2260 * Compares the time field records.
\r
2261 * Equivalent to comparing result of conversion to UTC.
\r
2262 * @param when the Calendar to be compared with this Calendar.
\r
2263 * @return true if the current time of this Calendar is after
\r
2264 * the time of Calendar when; false otherwise.
\r
2267 public boolean after(Object when) {
\r
2268 return compare(when) > 0;
\r
2272 * Returns the maximum value that this field could have, given the
\r
2273 * current date. For example, with the Gregorian date February 3, 1997
\r
2274 * and the {@link #DAY_OF_MONTH DAY_OF_MONTH} field, the actual maximum
\r
2275 * is 28; for February 3, 1996 it is 29.
\r
2277 * <p>The actual maximum computation ignores smaller fields and the
\r
2278 * current value of like-sized fields. For example, the actual maximum
\r
2279 * of the DAY_OF_YEAR or MONTH depends only on the year and supra-year
\r
2280 * fields. The actual maximum of the DAY_OF_MONTH depends, in
\r
2281 * addition, on the MONTH field and any other fields at that
\r
2282 * granularity (such as IS_LEAP_MONTH). The
\r
2283 * DAY_OF_WEEK_IN_MONTH field does not depend on the current
\r
2284 * DAY_OF_WEEK; it returns the maximum for any day of week in the
\r
2285 * current month. Likewise for the WEEK_OF_MONTH and WEEK_OF_YEAR
\r
2288 * @param field the field whose maximum is desired
\r
2289 * @return the maximum of the given field for the current date of this calendar
\r
2290 * @see #getMaximum
\r
2291 * @see #getLeastMaximum
\r
2294 public int getActualMaximum(int field) {
\r
2298 case DAY_OF_MONTH:
\r
2300 Calendar cal = (Calendar) clone();
\r
2301 cal.prepareGetActual(field, false);
\r
2302 result = handleGetMonthLength(cal.get(EXTENDED_YEAR), cal.get(MONTH));
\r
2308 Calendar cal = (Calendar) clone();
\r
2309 cal.prepareGetActual(field, false);
\r
2310 result = handleGetYearLength(cal.get(EXTENDED_YEAR));
\r
2326 case MILLISECONDS_IN_DAY:
\r
2327 // These fields all have fixed minima/maxima
\r
2328 result = getMaximum(field);
\r
2332 // For all other fields, do it the hard way....
\r
2333 result = getActualHelper(field, getLeastMaximum(field), getMaximum(field));
\r
2340 * Returns the minimum value that this field could have, given the current date.
\r
2341 * For most fields, this is the same as {@link #getMinimum getMinimum}
\r
2342 * and {@link #getGreatestMinimum getGreatestMinimum}. However, some fields,
\r
2343 * especially those related to week number, are more complicated.
\r
2345 * For example, assume {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek}
\r
2346 * returns 4 and {@link #getFirstDayOfWeek getFirstDayOfWeek} returns SUNDAY.
\r
2347 * If the first day of the month is Sunday, Monday, Tuesday, or Wednesday
\r
2348 * there will be four or more days in the first week, so it will be week number 1,
\r
2349 * and <code>getActualMinimum(WEEK_OF_MONTH)</code> will return 1. However,
\r
2350 * if the first of the month is a Thursday, Friday, or Saturday, there are
\r
2351 * <em>not</em> four days in that week, so it is week number 0, and
\r
2352 * <code>getActualMinimum(WEEK_OF_MONTH)</code> will return 0.
\r
2354 * @param field the field whose actual minimum value is desired.
\r
2355 * @return the minimum of the given field for the current date of this calendar
\r
2357 * @see #getMinimum
\r
2358 * @see #getGreatestMinimum
\r
2361 public int getActualMinimum(int field) {
\r
2376 case MILLISECONDS_IN_DAY:
\r
2377 // These fields all have fixed minima/maxima
\r
2378 result = getMinimum(field);
\r
2382 // For all other fields, do it the hard way....
\r
2383 result = getActualHelper(field, getGreatestMinimum(field), getMinimum(field));
\r
2390 * Prepare this calendar for computing the actual minimum or maximum.
\r
2391 * This method modifies this calendar's fields; it is called on a
\r
2392 * temporary calendar.
\r
2394 * <p>Rationale: The semantics of getActualXxx() is to return the
\r
2395 * maximum or minimum value that the given field can take, taking into
\r
2396 * account other relevant fields. In general these other fields are
\r
2397 * larger fields. For example, when computing the actual maximum
\r
2398 * DAY_OF_MONTH, the current value of DAY_OF_MONTH itself is ignored,
\r
2399 * as is the value of any field smaller.
\r
2401 * <p>The time fields all have fixed minima and maxima, so we don't
\r
2402 * need to worry about them. This also lets us set the
\r
2403 * MILLISECONDS_IN_DAY to zero to erase any effects the time fields
\r
2404 * might have when computing date fields.
\r
2406 * <p>DAY_OF_WEEK is adjusted specially for the WEEK_OF_MONTH and
\r
2407 * WEEK_OF_YEAR fields to ensure that they are computed correctly.
\r
2410 protected void prepareGetActual(int field, boolean isMinimum) {
\r
2411 set(MILLISECONDS_IN_DAY, 0);
\r
2415 case EXTENDED_YEAR:
\r
2416 set(DAY_OF_YEAR, getGreatestMinimum(DAY_OF_YEAR));
\r
2420 set(WEEK_OF_YEAR, getGreatestMinimum(WEEK_OF_YEAR));
\r
2424 set(DAY_OF_MONTH, getGreatestMinimum(DAY_OF_MONTH));
\r
2427 case DAY_OF_WEEK_IN_MONTH:
\r
2428 // For dowim, the maximum occurs for the DOW of the first of the
\r
2430 set(DAY_OF_MONTH, 1);
\r
2431 set(DAY_OF_WEEK, get(DAY_OF_WEEK)); // Make this user set
\r
2434 case WEEK_OF_MONTH:
\r
2435 case WEEK_OF_YEAR:
\r
2436 // If we're counting weeks, set the day of the week to either the
\r
2437 // first or last localized DOW. We know the last week of a month
\r
2438 // or year will contain the first day of the week, and that the
\r
2439 // first week will contain the last DOW.
\r
2441 int dow = firstDayOfWeek;
\r
2443 dow = (dow + 6) % 7; // set to last DOW
\r
2444 if (dow < SUNDAY) {
\r
2448 set(DAY_OF_WEEK, dow);
\r
2453 // Do this last to give it the newest time stamp
\r
2454 set(field, getGreatestMinimum(field));
\r
2457 private int getActualHelper(int field, int startValue, int endValue) {
\r
2459 if (startValue == endValue) {
\r
2460 // if we know that the maximum value is always the same, just return it
\r
2461 return startValue;
\r
2464 final int delta = (endValue > startValue) ? 1 : -1;
\r
2466 // clone the calendar so we don't mess with the real one, and set it to
\r
2467 // accept anything for the field values
\r
2468 Calendar work = (Calendar) clone();
\r
2469 work.setLenient(true);
\r
2470 work.prepareGetActual(field, delta < 0);
\r
2472 // now try each value from the start to the end one by one until
\r
2473 // we get a value that normalizes to another value. The last value that
\r
2474 // normalizes to itself is the actual maximum for the current date
\r
2476 work.set(field, startValue);
\r
2477 // prepareGetActual sets the first day of week in the same week with
\r
2478 // the first day of a month. Unlike WEEK_OF_YEAR, week number for the
\r
2479 // which week contains days from both previous and current month is
\r
2480 // not unique. For example, last several days in the previous month
\r
2481 // is week 5, and the rest of week is week 1.
\r
2482 if (work.get(field) != startValue
\r
2483 && field != WEEK_OF_MONTH && delta > 0) {
\r
2484 return startValue;
\r
2486 int result = startValue;
\r
2488 startValue += delta;
\r
2489 work.add(field, delta);
\r
2490 if (work.get(field) != startValue) {
\r
2493 result = startValue;
\r
2494 } while (startValue != endValue);
\r
2501 * Rolls (up/down) a single unit of time on the given field. If the
\r
2502 * field is rolled past its maximum allowable value, it will "wrap" back
\r
2503 * to its minimum and continue rolling. For
\r
2504 * example, to roll the current date up by one day, you can call:
\r
2506 * <code>roll({@link #DATE}, true)</code>
\r
2508 * When rolling on the {@link #YEAR} field, it will roll the year
\r
2509 * value in the range between 1 and the value returned by calling
\r
2510 * {@link #getMaximum getMaximum}({@link #YEAR}).
\r
2512 * When rolling on certain fields, the values of other fields may conflict and
\r
2513 * need to be changed. For example, when rolling the <code>MONTH</code> field
\r
2514 * for the Gregorian date 1/31/96 upward, the <code>DAY_OF_MONTH</code> field
\r
2515 * must be adjusted so that the result is 2/29/96 rather than the invalid
\r
2518 * <b>Note:</b> Calling <tt>roll(field, true)</tt> N times is <em>not</em>
\r
2519 * necessarily equivalent to calling <tt>roll(field, N)</tt>. For example,
\r
2520 * imagine that you start with the date Gregorian date January 31, 1995. If you call
\r
2521 * <tt>roll(Calendar.MONTH, 2)</tt>, the result will be March 31, 1995.
\r
2522 * But if you call <tt>roll(Calendar.MONTH, true)</tt>, the result will be
\r
2523 * February 28, 1995. Calling it one more time will give March 28, 1995, which
\r
2524 * is usually not the desired result.
\r
2526 * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather
\r
2527 * than attempting to perform arithmetic operations directly on the fields
\r
2528 * of a <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses
\r
2529 * to have fields with non-linear behavior, for example missing months
\r
2530 * or days during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt>
\r
2531 * methods will take this into account, while simple arithmetic manipulations
\r
2532 * may give invalid results.
\r
2534 * @param field the calendar field to roll.
\r
2536 * @param up indicates if the value of the specified time field is to be
\r
2537 * rolled up or rolled down. Use <code>true</code> if rolling up,
\r
2538 * <code>false</code> otherwise.
\r
2540 * @exception IllegalArgumentException if the field is invalid or refers
\r
2541 * to a field that cannot be handled by this method.
\r
2542 * @see #roll(int, int)
\r
2546 public final void roll(int field, boolean up)
\r
2548 roll(field, up ? +1 : -1);
\r
2552 * Rolls (up/down) a specified amount time on the given field. For
\r
2553 * example, to roll the current date up by three days, you can call
\r
2554 * <code>roll(Calendar.DATE, 3)</code>. If the
\r
2555 * field is rolled past its maximum allowable value, it will "wrap" back
\r
2556 * to its minimum and continue rolling.
\r
2557 * For example, calling <code>roll(Calendar.DATE, 10)</code>
\r
2558 * on a Gregorian calendar set to 4/25/96 will result in the date 4/5/96.
\r
2560 * When rolling on certain fields, the values of other fields may conflict and
\r
2561 * need to be changed. For example, when rolling the {@link #MONTH MONTH} field
\r
2562 * for the Gregorian date 1/31/96 by +1, the {@link #DAY_OF_MONTH DAY_OF_MONTH} field
\r
2563 * must be adjusted so that the result is 2/29/96 rather than the invalid
\r
2566 * {@icunote} the ICU implementation of this method is able to roll
\r
2567 * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET},
\r
2568 * and {@link #ZONE_OFFSET ZONE_OFFSET}. Subclasses may, of course, add support for
\r
2569 * additional fields in their overrides of <code>roll</code>.
\r
2571 * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather
\r
2572 * than attempting to perform arithmetic operations directly on the fields
\r
2573 * of a <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses
\r
2574 * to have fields with non-linear behavior, for example missing months
\r
2575 * or days during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt>
\r
2576 * methods will take this into account, while simple arithmetic manipulations
\r
2577 * may give invalid results.
\r
2579 * <b>Subclassing:</b><br>
\r
2580 * This implementation of <code>roll</code> assumes that the behavior of the
\r
2581 * field is continuous between its minimum and maximum, which are found by
\r
2582 * calling {@link #getActualMinimum getActualMinimum} and {@link #getActualMaximum getActualMaximum}.
\r
2583 * For most such fields, simple addition, subtraction, and modulus operations
\r
2584 * are sufficient to perform the roll. For week-related fields,
\r
2585 * the results of {@link #getFirstDayOfWeek getFirstDayOfWeek} and
\r
2586 * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} are also necessary.
\r
2587 * Subclasses can override these two methods if their values differ from the defaults.
\r
2589 * Subclasses that have fields for which the assumption of continuity breaks
\r
2590 * down must overide <code>roll</code> to handle those fields specially.
\r
2591 * For example, in the Hebrew calendar the month "Adar I"
\r
2592 * only occurs in leap years; in other years the calendar jumps from
\r
2593 * Shevat (month #4) to Adar (month #6). The
\r
2594 * {@link HebrewCalendar#roll HebrewCalendar.roll} method takes this into account,
\r
2595 * so that rolling the month of Shevat by one gives the proper result (Adar) in a
\r
2598 * @param field the calendar field to roll.
\r
2599 * @param amount the amount by which the field should be rolled.
\r
2601 * @exception IllegalArgumentException if the field is invalid or refers
\r
2602 * to a field that cannot be handled by this method.
\r
2603 * @see #roll(int, boolean)
\r
2607 public void roll(int field, int amount) {
\r
2609 if (amount == 0) {
\r
2610 return; // Nothing to do
\r
2616 case DAY_OF_MONTH:
\r
2621 case MILLISECONDS_IN_DAY:
\r
2623 // These are the standard roll instructions. These work for all
\r
2624 // simple cases, that is, cases in which the limits are fixed, such
\r
2625 // as the hour, the day of the month, and the era.
\r
2627 int min = getActualMinimum(field);
\r
2628 int max = getActualMaximum(field);
\r
2629 int gap = max - min + 1;
\r
2631 int value = internalGet(field) + amount;
\r
2632 value = (value - min) % gap;
\r
2638 set(field, value);
\r
2644 // Rolling the hour is difficult on the ONSET and CEASE days of
\r
2645 // daylight savings. For example, if the change occurs at
\r
2646 // 2 AM, we have the following progression:
\r
2647 // ONSET: 12 Std -> 1 Std -> 3 Dst -> 4 Dst
\r
2648 // CEASE: 12 Dst -> 1 Dst -> 1 Std -> 2 Std
\r
2649 // To get around this problem we don't use fields; we manipulate
\r
2650 // the time in millis directly.
\r
2652 // Assume min == 0 in calculations below
\r
2653 long start = getTimeInMillis();
\r
2654 int oldHour = internalGet(field);
\r
2655 int max = getMaximum(field);
\r
2656 int newHour = (oldHour + amount) % (max + 1);
\r
2657 if (newHour < 0) {
\r
2658 newHour += max + 1;
\r
2660 setTimeInMillis(start + ONE_HOUR * (newHour - oldHour));
\r
2665 // Rolling the month involves both pinning the final value
\r
2666 // and adjusting the DAY_OF_MONTH if necessary. We only adjust the
\r
2667 // DAY_OF_MONTH if, after updating the MONTH field, it is illegal.
\r
2668 // E.g., <jan31>.roll(MONTH, 1) -> <feb28> or <feb29>.
\r
2670 int max = getActualMaximum(MONTH);
\r
2671 int mon = (internalGet(MONTH) + amount) % (max+1);
\r
2678 // Keep the day of month in range. We don't want to spill over
\r
2679 // into the next month; e.g., we don't want jan31 + 1 mo -> feb31 ->
\r
2681 pinField(DAY_OF_MONTH);
\r
2687 case EXTENDED_YEAR:
\r
2688 // Rolling the year can involve pinning the DAY_OF_MONTH.
\r
2689 set(field, internalGet(field) + amount);
\r
2691 pinField(DAY_OF_MONTH);
\r
2694 case WEEK_OF_MONTH:
\r
2696 // This is tricky, because during the roll we may have to shift
\r
2697 // to a different day of the week. For example:
\r
2701 // 6 7 8 9 10 11 12
\r
2703 // When rolling from the 6th or 7th back one week, we go to the
\r
2704 // 1st (assuming that the first partial week counts). The same
\r
2705 // thing happens at the end of the month.
\r
2707 // The other tricky thing is that we have to figure out whether
\r
2708 // the first partial week actually counts or not, based on the
\r
2709 // minimal first days in the week. And we have to use the
\r
2710 // correct first day of the week to delineate the week
\r
2713 // Here's our algorithm. First, we find the real boundaries of
\r
2714 // the month. Then we discard the first partial week if it
\r
2715 // doesn't count in this locale. Then we fill in the ends with
\r
2716 // phantom days, so that the first partial week and the last
\r
2717 // partial week are full weeks. We then have a nice square
\r
2718 // block of weeks. We do the usual rolling within this block,
\r
2719 // as is done elsewhere in this method. If we wind up on one of
\r
2720 // the phantom days that we added, we recognize this and pin to
\r
2721 // the first or the last day of the month. Easy, eh?
\r
2723 // Normalize the DAY_OF_WEEK so that 0 is the first day of the week
\r
2724 // in this locale. We have dow in 0..6.
\r
2725 int dow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek();
\r
2726 if (dow < 0) dow += 7;
\r
2728 // Find the day of the week (normalized for locale) for the first
\r
2730 int fdm = (dow - internalGet(DAY_OF_MONTH) + 1) % 7;
\r
2731 if (fdm < 0) fdm += 7;
\r
2733 // Get the first day of the first full week of the month,
\r
2734 // including phantom days, if any. Figure out if the first week
\r
2735 // counts or not; if it counts, then fill in phantom days. If
\r
2736 // not, advance to the first real full week (skip the partial week).
\r
2738 if ((7 - fdm) < getMinimalDaysInFirstWeek())
\r
2739 start = 8 - fdm; // Skip the first partial week
\r
2741 start = 1 - fdm; // This may be zero or negative
\r
2743 // Get the day of the week (normalized for locale) for the last
\r
2744 // day of the month.
\r
2745 int monthLen = getActualMaximum(DAY_OF_MONTH);
\r
2746 int ldm = (monthLen - internalGet(DAY_OF_MONTH) + dow) % 7;
\r
2747 // We know monthLen >= DAY_OF_MONTH so we skip the += 7 step here.
\r
2749 // Get the limit day for the blocked-off rectangular month; that
\r
2750 // is, the day which is one past the last day of the month,
\r
2751 // after the month has already been filled in with phantom days
\r
2752 // to fill out the last week. This day has a normalized DOW of 0.
\r
2753 int limit = monthLen + 7 - ldm;
\r
2755 // Now roll between start and (limit - 1).
\r
2756 int gap = limit - start;
\r
2757 int day_of_month = (internalGet(DAY_OF_MONTH) + amount*7 -
\r
2759 if (day_of_month < 0) day_of_month += gap;
\r
2760 day_of_month += start;
\r
2762 // Finally, pin to the real start and end of the month.
\r
2763 if (day_of_month < 1) day_of_month = 1;
\r
2764 if (day_of_month > monthLen) day_of_month = monthLen;
\r
2766 // Set the DAY_OF_MONTH. We rely on the fact that this field
\r
2767 // takes precedence over everything else (since all other fields
\r
2768 // are also set at this point). If this fact changes (if the
\r
2769 // disambiguation algorithm changes) then we will have to unset
\r
2770 // the appropriate fields here so that DAY_OF_MONTH is attended
\r
2772 set(DAY_OF_MONTH, day_of_month);
\r
2775 case WEEK_OF_YEAR:
\r
2777 // This follows the outline of WEEK_OF_MONTH, except it applies
\r
2778 // to the whole year. Please see the comment for WEEK_OF_MONTH
\r
2779 // for general notes.
\r
2781 // Normalize the DAY_OF_WEEK so that 0 is the first day of the week
\r
2782 // in this locale. We have dow in 0..6.
\r
2783 int dow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek();
\r
2784 if (dow < 0) dow += 7;
\r
2786 // Find the day of the week (normalized for locale) for the first
\r
2788 int fdy = (dow - internalGet(DAY_OF_YEAR) + 1) % 7;
\r
2789 if (fdy < 0) fdy += 7;
\r
2791 // Get the first day of the first full week of the year,
\r
2792 // including phantom days, if any. Figure out if the first week
\r
2793 // counts or not; if it counts, then fill in phantom days. If
\r
2794 // not, advance to the first real full week (skip the partial week).
\r
2796 if ((7 - fdy) < getMinimalDaysInFirstWeek())
\r
2797 start = 8 - fdy; // Skip the first partial week
\r
2799 start = 1 - fdy; // This may be zero or negative
\r
2801 // Get the day of the week (normalized for locale) for the last
\r
2802 // day of the year.
\r
2803 int yearLen = getActualMaximum(DAY_OF_YEAR);
\r
2804 int ldy = (yearLen - internalGet(DAY_OF_YEAR) + dow) % 7;
\r
2805 // We know yearLen >= DAY_OF_YEAR so we skip the += 7 step here.
\r
2807 // Get the limit day for the blocked-off rectangular year; that
\r
2808 // is, the day which is one past the last day of the year,
\r
2809 // after the year has already been filled in with phantom days
\r
2810 // to fill out the last week. This day has a normalized DOW of 0.
\r
2811 int limit = yearLen + 7 - ldy;
\r
2813 // Now roll between start and (limit - 1).
\r
2814 int gap = limit - start;
\r
2815 int day_of_year = (internalGet(DAY_OF_YEAR) + amount*7 -
\r
2817 if (day_of_year < 0) day_of_year += gap;
\r
2818 day_of_year += start;
\r
2820 // Finally, pin to the real start and end of the month.
\r
2821 if (day_of_year < 1) day_of_year = 1;
\r
2822 if (day_of_year > yearLen) day_of_year = yearLen;
\r
2824 // Make sure that the year and day of year are attended to by
\r
2825 // clearing other fields which would normally take precedence.
\r
2826 // If the disambiguation algorithm is changed, this section will
\r
2827 // have to be updated as well.
\r
2828 set(DAY_OF_YEAR, day_of_year);
\r
2834 // Roll the day of year using millis. Compute the millis for
\r
2835 // the start of the year, and get the length of the year.
\r
2836 long delta = amount * ONE_DAY; // Scale up from days to millis
\r
2837 long min2 = time - (internalGet(DAY_OF_YEAR) - 1) * ONE_DAY;
\r
2838 int yearLength = getActualMaximum(DAY_OF_YEAR);
\r
2839 time = (time + delta - min2) % (yearLength*ONE_DAY);
\r
2840 if (time < 0) time += yearLength*ONE_DAY;
\r
2841 setTimeInMillis(time + min2);
\r
2847 // Roll the day of week using millis. Compute the millis for
\r
2848 // the start of the week, using the first day of week setting.
\r
2849 // Restrict the millis to [start, start+7days).
\r
2850 long delta = amount * ONE_DAY; // Scale up from days to millis
\r
2851 // Compute the number of days before the current day in this
\r
2852 // week. This will be a value 0..6.
\r
2853 int leadDays = internalGet(field);
\r
2854 leadDays -= (field == DAY_OF_WEEK) ? getFirstDayOfWeek() : 1;
\r
2855 if (leadDays < 0) leadDays += 7;
\r
2856 long min2 = time - leadDays * ONE_DAY;
\r
2857 time = (time + delta - min2) % ONE_WEEK;
\r
2858 if (time < 0) time += ONE_WEEK;
\r
2859 setTimeInMillis(time + min2);
\r
2862 case DAY_OF_WEEK_IN_MONTH:
\r
2864 // Roll the day of week in the month using millis. Determine
\r
2865 // the first day of the week in the month, and then the last,
\r
2866 // and then roll within that range.
\r
2867 long delta = amount * ONE_WEEK; // Scale up from weeks to millis
\r
2868 // Find the number of same days of the week before this one
\r
2870 int preWeeks = (internalGet(DAY_OF_MONTH) - 1) / 7;
\r
2871 // Find the number of same days of the week after this one
\r
2873 int postWeeks = (getActualMaximum(DAY_OF_MONTH) -
\r
2874 internalGet(DAY_OF_MONTH)) / 7;
\r
2875 // From these compute the min and gap millis for rolling.
\r
2876 long min2 = time - preWeeks * ONE_WEEK;
\r
2877 long gap2 = ONE_WEEK * (preWeeks + postWeeks + 1); // Must add 1!
\r
2878 // Roll within this range
\r
2879 time = (time + delta - min2) % gap2;
\r
2880 if (time < 0) time += gap2;
\r
2881 setTimeInMillis(time + min2);
\r
2885 set(field, internalGet(field) + amount);
\r
2888 // Other fields cannot be rolled by this method
\r
2889 throw new IllegalArgumentException("Calendar.roll(" + fieldName(field) +
\r
2890 ") not supported");
\r
2895 * Add a signed amount to a specified field, using this calendar's rules.
\r
2896 * For example, to add three days to the current date, you can call
\r
2897 * <code>add(Calendar.DATE, 3)</code>.
\r
2899 * When adding to certain fields, the values of other fields may conflict and
\r
2900 * need to be changed. For example, when adding one to the {@link #MONTH MONTH} field
\r
2901 * for the Gregorian date 1/31/96, the {@link #DAY_OF_MONTH DAY_OF_MONTH} field
\r
2902 * must be adjusted so that the result is 2/29/96 rather than the invalid
\r
2905 * {@icunote} The ICU implementation of this method is able to add to
\r
2906 * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET},
\r
2907 * and {@link #ZONE_OFFSET ZONE_OFFSET}. Subclasses may, of course, add support for
\r
2908 * additional fields in their overrides of <code>add</code>.
\r
2910 * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather
\r
2911 * than attempting to perform arithmetic operations directly on the fields
\r
2912 * of a <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses
\r
2913 * to have fields with non-linear behavior, for example missing months
\r
2914 * or days during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt>
\r
2915 * methods will take this into account, while simple arithmetic manipulations
\r
2916 * may give invalid results.
\r
2918 * <b>Subclassing:</b><br>
\r
2919 * This implementation of <code>add</code> assumes that the behavior of the
\r
2920 * field is continuous between its minimum and maximum, which are found by
\r
2921 * calling {@link #getActualMinimum getActualMinimum} and
\r
2922 * {@link #getActualMaximum getActualMaximum}.
\r
2923 * For such fields, simple arithmetic operations are sufficient to
\r
2924 * perform the add.
\r
2926 * Subclasses that have fields for which this assumption of continuity breaks
\r
2927 * down must overide <code>add</code> to handle those fields specially.
\r
2928 * For example, in the Hebrew calendar the month "Adar I"
\r
2929 * only occurs in leap years; in other years the calendar jumps from
\r
2930 * Shevat (month #4) to Adar (month #6). The
\r
2931 * {@link HebrewCalendar#add HebrewCalendar.add} method takes this into account,
\r
2932 * so that adding one month
\r
2933 * to a date in Shevat gives the proper result (Adar) in a non-leap year.
\r
2935 * @param field the time field.
\r
2936 * @param amount the amount to add to the field.
\r
2938 * @exception IllegalArgumentException if the field is invalid or refers
\r
2939 * to a field that cannot be handled by this method.
\r
2940 * @see #roll(int, int)
\r
2943 public void add(int field, int amount) {
\r
2945 if (amount == 0) {
\r
2946 return; // Do nothing!
\r
2949 // We handle most fields in the same way. The algorithm is to add
\r
2950 // a computed amount of millis to the current millis. The only
\r
2951 // wrinkle is with DST -- for some fields, like the DAY_OF_MONTH,
\r
2952 // we don't want the HOUR to shift due to changes in DST. If the
\r
2953 // result of the add operation is to move from DST to Standard, or
\r
2954 // vice versa, we need to adjust by an hour forward or back,
\r
2955 // respectively. For such fields we set keepHourInvariant to true.
\r
2957 // We only adjust the DST for fields larger than an hour. For
\r
2958 // fields smaller than an hour, we cannot adjust for DST without
\r
2959 // causing problems. for instance, if you add one hour to April 5,
\r
2960 // 1998, 1:00 AM, in PST, the time becomes "2:00 AM PDT" (an
\r
2961 // illegal value), but then the adjustment sees the change and
\r
2962 // compensates by subtracting an hour. As a result the time
\r
2963 // doesn't advance at all.
\r
2965 // For some fields larger than a day, such as a MONTH, we pin the
\r
2966 // DAY_OF_MONTH. This allows <March 31>.add(MONTH, 1) to be
\r
2967 // <April 30>, rather than <April 31> => <May 1>.
\r
2969 long delta = amount; // delta in ms
\r
2970 boolean keepHourInvariant = true;
\r
2974 set(field, get(field) + amount);
\r
2979 case EXTENDED_YEAR:
\r
2982 set(field, get(field) + amount);
\r
2983 pinField(DAY_OF_MONTH);
\r
2986 case WEEK_OF_YEAR:
\r
2987 case WEEK_OF_MONTH:
\r
2988 case DAY_OF_WEEK_IN_MONTH:
\r
2989 delta *= ONE_WEEK;
\r
2993 delta *= 12 * ONE_HOUR;
\r
2996 case DAY_OF_MONTH:
\r
3006 delta *= ONE_HOUR;
\r
3007 keepHourInvariant = false;
\r
3011 delta *= ONE_MINUTE;
\r
3012 keepHourInvariant = false;
\r
3016 delta *= ONE_SECOND;
\r
3017 keepHourInvariant = false;
\r
3021 case MILLISECONDS_IN_DAY:
\r
3022 keepHourInvariant = false;
\r
3026 throw new IllegalArgumentException("Calendar.add(" + fieldName(field) +
\r
3027 ") not supported");
\r
3030 // In order to keep the hour invariant (for fields where this is
\r
3031 // appropriate), record the DST_OFFSET before and after the add()
\r
3032 // operation. If it has changed, then adjust the millis to
\r
3036 if (keepHourInvariant) {
\r
3037 dst = get(DST_OFFSET);
\r
3038 hour = internalGet(HOUR_OF_DAY);
\r
3041 setTimeInMillis(getTimeInMillis() + delta);
\r
3043 if (keepHourInvariant) {
\r
3044 dst -= get(DST_OFFSET);
\r
3046 // We have done an hour-invariant adjustment but the
\r
3047 // DST offset has altered. We adjust millis to keep
\r
3048 // the hour constant. In cases such as midnight after
\r
3049 // a DST change which occurs at midnight, there is the
\r
3050 // danger of adjusting into a different day. To avoid
\r
3051 // this we make the adjustment only if it actually
\r
3052 // maintains the hour.
\r
3054 setTimeInMillis(time + dst);
\r
3055 if (get(HOUR_OF_DAY) != hour) {
\r
3056 setTimeInMillis(t);
\r
3063 * Returns the name of this calendar in the language of the given locale.
\r
3066 public String getDisplayName(Locale loc) {
\r
3067 return this.getClass().getName();
\r
3071 * Returns the name of this calendar in the language of the given locale.
\r
3074 public String getDisplayName(ULocale loc) {
\r
3075 return this.getClass().getName();
\r
3079 * Compares the times (in millis) represented by two
\r
3080 * <code>Calendar</code> objects.
\r
3082 * @param that the <code>Calendar</code> to compare to this.
\r
3083 * @return <code>0</code> if the time represented by
\r
3084 * this <code>Calendar</code> is equal to the time represented
\r
3085 * by that <code>Calendar</code>, a value less than
\r
3086 * <code>0</code> if the time represented by this is before
\r
3087 * the time represented by that, and a value greater than
\r
3088 * <code>0</code> if the time represented by this
\r
3089 * is after the time represented by that.
\r
3090 * @throws NullPointerException if that
\r
3091 * <code>Calendar</code> is null.
\r
3092 * @throws IllegalArgumentException if the time of that
\r
3093 * <code>Calendar</code> can't be obtained because of invalid
\r
3094 * calendar values.
\r
3097 public int compareTo(Calendar that) {
\r
3098 long v = getTimeInMillis() - that.getTimeInMillis();
\r
3099 return v < 0 ? -1 : (v > 0 ? 1 : 0);
\r
3102 //-------------------------------------------------------------------------
\r
3103 // Interface for creating custon DateFormats for different types of Calendars
\r
3104 //-------------------------------------------------------------------------
\r
3107 * {@icu} Returns a <code>DateFormat</code> appropriate to this calendar.
\r
3108 * Subclasses wishing to specialize this behavior should override
\r
3109 * {@link #handleGetDateFormat}.
\r
3112 public DateFormat getDateTimeFormat(int dateStyle, int timeStyle, Locale loc) {
\r
3113 return formatHelper(this, ULocale.forLocale(loc), dateStyle, timeStyle);
\r
3117 * {@icu} Returns a <code>DateFormat</code> appropriate to this calendar.
\r
3118 * Subclasses wishing to specialize this behavior should override
\r
3119 * {@link #handleGetDateFormat}.
\r
3122 public DateFormat getDateTimeFormat(int dateStyle, int timeStyle, ULocale loc) {
\r
3123 return formatHelper(this, loc, dateStyle, timeStyle);
\r
3127 * Creates a <code>DateFormat</code> appropriate to this calendar.
\r
3128 * This is a framework method for subclasses to override. This method
\r
3129 * is responsible for creating the calendar-specific DateFormat and
\r
3130 * DateFormatSymbols objects as needed.
\r
3131 * @param pattern the pattern, specific to the <code>DateFormat</code>
\r
3133 * @param locale the locale for which the symbols should be drawn
\r
3134 * @return a <code>DateFormat</code> appropriate to this calendar
\r
3137 protected DateFormat handleGetDateFormat(String pattern, Locale locale) {
\r
3138 return handleGetDateFormat(pattern, null, ULocale.forLocale(locale));
\r
3142 * Creates a <code>DateFormat</code> appropriate to this calendar.
\r
3143 * This is a framework method for subclasses to override. This method
\r
3144 * is responsible for creating the calendar-specific DateFormat and
\r
3145 * DateFormatSymbols objects as needed.
\r
3146 * @param pattern the pattern, specific to the <code>DateFormat</code>
\r
3148 * @param override The override string. A numbering system override string can take one of the following forms:
\r
3149 * 1). If just a numbering system name is specified, it applies to all numeric fields in the date format pattern.
\r
3150 * 2). To specify an alternate numbering system on a field by field basis, use the field letters from the pattern
\r
3151 * followed by an = sign, followed by the numbering system name. For example, to specify that just the year
\r
3152 * be formatted using Hebrew digits, use the override "y=hebr". Multiple overrides can be specified in a single
\r
3153 * string by separating them with a semi-colon. For example, the override string "m=thai;y=deva" would format using
\r
3154 * Thai digits for the month and Devanagari digits for the year.
\r
3155 * @param locale the locale for which the symbols should be drawn
\r
3156 * @return a <code>DateFormat</code> appropriate to this calendar
\r
3159 protected DateFormat handleGetDateFormat(String pattern, String override, Locale locale) {
\r
3160 return handleGetDateFormat(pattern, override, ULocale.forLocale(locale));
\r
3164 * Creates a <code>DateFormat</code> appropriate to this calendar.
\r
3165 * This is a framework method for subclasses to override. This method
\r
3166 * is responsible for creating the calendar-specific DateFormat and
\r
3167 * DateFormatSymbols objects as needed.
\r
3168 * @param pattern the pattern, specific to the <code>DateFormat</code>
\r
3170 * @param locale the locale for which the symbols should be drawn
\r
3171 * @return a <code>DateFormat</code> appropriate to this calendar
\r
3174 protected DateFormat handleGetDateFormat(String pattern, ULocale locale) {
\r
3175 return handleGetDateFormat(pattern, null, locale);
\r
3179 * Creates a <code>DateFormat</code> appropriate to this calendar.
\r
3180 * This is a framework method for subclasses to override. This method
\r
3181 * is responsible for creating the calendar-specific DateFormat and
\r
3182 * DateFormatSymbols objects as needed.
\r
3183 * @param pattern the pattern, specific to the <code>DateFormat</code>
\r
3185 * @param locale the locale for which the symbols should be drawn
\r
3186 * @return a <code>DateFormat</code> appropriate to this calendar
\r
3187 * @draft ICU 3.2 (retain)
\r
3188 * @provisional This API might change or be removed in a future release.
\r
3190 protected DateFormat handleGetDateFormat(String pattern, String override, ULocale locale) {
\r
3191 FormatConfiguration fmtConfig = new FormatConfiguration();
\r
3192 fmtConfig.pattern = pattern;
\r
3193 fmtConfig.override = override;
\r
3194 fmtConfig.formatData = new DateFormatSymbols(this, locale);
\r
3195 fmtConfig.loc = locale;
\r
3196 fmtConfig.cal = this;
\r
3198 return SimpleDateFormat.getInstance(fmtConfig);
\r
3201 // date format pattern cache
\r
3202 private static final ICUCache<String, PatternData> PATTERN_CACHE =
\r
3203 new SimpleCache<String, PatternData>();
\r
3204 // final fallback patterns
\r
3205 private static final String[] DEFAULT_PATTERNS = {
\r
3210 "EEEE, yyyy MMMM dd",
\r
3221 static private DateFormat formatHelper(Calendar cal, ULocale loc, int dateStyle,
\r
3223 PatternData patternData = PatternData.make(cal, loc);
\r
3224 String override = null;
\r
3226 // Resolve a pattern for the date/time style
\r
3227 String pattern = null;
\r
3228 if ((timeStyle >= 0) && (dateStyle >= 0)) {
\r
3229 pattern = MessageFormat.format(patternData.getDateTimePattern(dateStyle),
\r
3230 new Object[] {patternData.patterns[timeStyle],
\r
3231 patternData.patterns[dateStyle + 4]});
\r
3232 // Might need to merge the overrides from the date and time into a single
\r
3233 // override string TODO: Right now we are forcing the date's override into the
\r
3235 if ( patternData.overrides != null ) {
\r
3236 String dateOverride = patternData.overrides[dateStyle + 4];
\r
3237 String timeOverride = patternData.overrides[timeStyle];
\r
3238 override = mergeOverrideStrings(
\r
3239 patternData.patterns[dateStyle+4],
\r
3240 patternData.patterns[timeStyle],
\r
3241 dateOverride, timeOverride);
\r
3243 } else if (timeStyle >= 0) {
\r
3244 pattern = patternData.patterns[timeStyle];
\r
3245 if ( patternData.overrides != null ) {
\r
3246 override = patternData.overrides[timeStyle];
\r
3248 } else if (dateStyle >= 0) {
\r
3249 pattern = patternData.patterns[dateStyle + 4];
\r
3250 if ( patternData.overrides != null ) {
\r
3251 override = patternData.overrides[dateStyle + 4];
\r
3254 throw new IllegalArgumentException("No date or time style specified");
\r
3256 DateFormat result = cal.handleGetDateFormat(pattern, override, loc);
\r
3257 result.setCalendar(cal);
\r
3261 static class PatternData {
\r
3262 // TODO make this even more object oriented
\r
3263 private String[] patterns;
\r
3264 private String[] overrides;
\r
3265 public PatternData(String[] patterns, String[] overrides) {
\r
3266 this.patterns = patterns;
\r
3267 this.overrides = overrides;
\r
3269 private String getDateTimePattern(int dateStyle) {
\r
3270 int glueIndex = 8;
\r
3271 if (patterns.length >= 13) {
\r
3272 glueIndex += (dateStyle + 1);
\r
3274 final String dateTimePattern = patterns[glueIndex];
\r
3275 return dateTimePattern;
\r
3277 private static PatternData make(Calendar cal, ULocale loc) {
\r
3278 // First, try to get a pattern from PATTERN_CACHE
\r
3279 String key = loc.toString() + cal.getType();
\r
3280 PatternData patternData = PATTERN_CACHE.get(key);
\r
3281 if (patternData == null) {
\r
3282 // Cache missed. Get one from bundle
\r
3284 CalendarData calData = new CalendarData(loc, cal.getType());
\r
3285 patternData = new PatternData(calData.getDateTimePatterns(),
\r
3286 calData.getOverrides());
\r
3287 } catch (MissingResourceException e) {
\r
3288 patternData = new PatternData(DEFAULT_PATTERNS, null);
\r
3290 PATTERN_CACHE.put(key, patternData);
\r
3292 return patternData;
\r
3298 * @deprecated This API is ICU internal only.
\r
3300 public static String getDateTimePattern(Calendar cal, ULocale uLocale, int dateStyle) {
\r
3301 PatternData patternData = PatternData.make(cal, uLocale);
\r
3302 return patternData.getDateTimePattern(dateStyle);
\r
3305 private static String mergeOverrideStrings( String datePattern, String timePattern,
\r
3306 String dateOverride, String timeOverride ) {
\r
3308 if ( dateOverride == null && timeOverride == null ) {
\r
3312 if ( dateOverride == null ) {
\r
3313 return expandOverride(timePattern,timeOverride);
\r
3316 if ( timeOverride == null ) {
\r
3317 return expandOverride(datePattern,dateOverride);
\r
3320 if ( dateOverride.equals(timeOverride) ) {
\r
3321 return dateOverride;
\r
3324 return (expandOverride(datePattern,dateOverride)+";"+
\r
3325 expandOverride(timePattern,timeOverride));
\r
3329 private static final char QUOTE = '\'';
\r
3330 private static String expandOverride(String pattern, String override) {
\r
3332 if (override.indexOf('=') >= 0) {
\r
3335 boolean inQuotes = false;
\r
3336 char prevChar = ' ';
\r
3337 StringBuilder result = new StringBuilder();
\r
3339 StringCharacterIterator it = new StringCharacterIterator(pattern);
\r
3341 for (char c = it.first(); c!= StringCharacterIterator.DONE; c = it.next()) {
\r
3342 if ( c == QUOTE ) {
\r
3343 inQuotes = !inQuotes;
\r
3347 if ( !inQuotes && c != prevChar ) {
\r
3348 if (result.length() > 0) {
\r
3349 result.append(";");
\r
3352 result.append("=");
\r
3353 result.append(override);
\r
3357 return result.toString();
\r
3360 * An instance of FormatConfiguration represents calendar specific
\r
3361 * date format configuration and used for calling the ICU private
\r
3362 * SimpleDateFormat factory method.
\r
3365 * @deprecated This API is ICU internal only.
\r
3367 public static class FormatConfiguration {
\r
3368 private String pattern;
\r
3369 private String override;
\r
3370 private DateFormatSymbols formatData;
\r
3371 private Calendar cal;
\r
3372 private ULocale loc;
\r
3374 // Only Calendar can instantiate
\r
3375 private FormatConfiguration() {
\r
3379 * Returns the pattern string
\r
3380 * @return the format pattern string
\r
3382 * @deprecated This API is ICU internal only.
\r
3384 public String getPatternString() {
\r
3390 * @deprecated This API is ICU internal only.
\r
3392 public String getOverrideString() {
\r
3397 * Returns the calendar
\r
3398 * @return the calendar
\r
3400 * @deprecated This API is ICU internal only.
\r
3402 public Calendar getCalendar() {
\r
3407 * Returns the locale
\r
3408 * @return the locale
\r
3410 * @deprecated This API is ICU internal only.
\r
3412 public ULocale getLocale() {
\r
3417 * Returns the format symbols
\r
3418 * @return the format symbols
\r
3420 * @deprecated This API is ICU internal only.
\r
3422 public DateFormatSymbols getDateFormatSymbols() {
\r
3423 return formatData;
\r
3427 //-------------------------------------------------------------------------
\r
3428 // Protected utility methods for use by subclasses. These are very handy
\r
3429 // for implementing add, roll, and computeFields.
\r
3430 //-------------------------------------------------------------------------
\r
3433 * Adjust the specified field so that it is within
\r
3434 * the allowable range for the date to which this calendar is set.
\r
3435 * For example, in a Gregorian calendar pinning the {@link #DAY_OF_MONTH DAY_OF_MONTH}
\r
3436 * field for a calendar set to April 31 would cause it to be set
\r
3439 * <b>Subclassing:</b>
\r
3441 * This utility method is intended for use by subclasses that need to implement
\r
3442 * their own overrides of {@link #roll roll} and {@link #add add}.
\r
3445 * <code>pinField</code> is implemented in terms of
\r
3446 * {@link #getActualMinimum getActualMinimum}
\r
3447 * and {@link #getActualMaximum getActualMaximum}. If either of those methods uses
\r
3448 * a slow, iterative algorithm for a particular field, it would be
\r
3449 * unwise to attempt to call <code>pinField</code> for that field. If you
\r
3450 * really do need to do so, you should override this method to do
\r
3451 * something more efficient for that field.
\r
3453 * @param field The calendar field whose value should be pinned.
\r
3455 * @see #getActualMinimum
\r
3456 * @see #getActualMaximum
\r
3459 protected void pinField(int field) {
\r
3460 int max = getActualMaximum(field);
\r
3461 int min = getActualMinimum(field);
\r
3463 if (fields[field] > max) {
\r
3465 } else if (fields[field] < min) {
\r
3471 * Returns the week number of a day, within a period. This may be the week number in
\r
3472 * a year or the week number in a month. Usually this will be a value >= 1, but if
\r
3473 * some initial days of the period are excluded from week 1, because
\r
3474 * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} is > 1, then
\r
3475 * the week number will be zero for those
\r
3476 * initial days. This method requires the day number and day of week for some
\r
3477 * known date in the period in order to determine the day of week
\r
3478 * on the desired day.
\r
3480 * <b>Subclassing:</b>
\r
3482 * This method is intended for use by subclasses in implementing their
\r
3483 * {@link #computeTime computeTime} and/or {@link #computeFields computeFields} methods.
\r
3484 * It is often useful in {@link #getActualMinimum getActualMinimum} and
\r
3485 * {@link #getActualMaximum getActualMaximum} as well.
\r
3487 * This variant is handy for computing the week number of some other
\r
3488 * day of a period (often the first or last day of the period) when its day
\r
3489 * of the week is not known but the day number and day of week for some other
\r
3490 * day in the period (e.g. the current date) <em>is</em> known.
\r
3492 * @param desiredDay The {@link #DAY_OF_YEAR DAY_OF_YEAR} or
\r
3493 * {@link #DAY_OF_MONTH DAY_OF_MONTH} whose week number is desired.
\r
3494 * Should be 1 for the first day of the period.
\r
3496 * @param dayOfPeriod The {@link #DAY_OF_YEAR DAY_OF_YEAR}
\r
3497 * or {@link #DAY_OF_MONTH DAY_OF_MONTH} for a day in the period whose
\r
3498 * {@link #DAY_OF_WEEK DAY_OF_WEEK} is specified by the
\r
3499 * <code>dayOfWeek</code> parameter.
\r
3500 * Should be 1 for first day of period.
\r
3502 * @param dayOfWeek The {@link #DAY_OF_WEEK DAY_OF_WEEK} for the day
\r
3503 * corresponding to the <code>dayOfPeriod</code> parameter.
\r
3504 * 1-based with 1=Sunday.
\r
3506 * @return The week number (one-based), or zero if the day falls before
\r
3507 * the first week because
\r
3508 * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek}
\r
3509 * is more than one.
\r
3512 protected int weekNumber(int desiredDay, int dayOfPeriod, int dayOfWeek)
\r
3514 // Determine the day of the week of the first day of the period
\r
3515 // in question (either a year or a month). Zero represents the
\r
3516 // first day of the week on this calendar.
\r
3517 int periodStartDayOfWeek = (dayOfWeek - getFirstDayOfWeek() - dayOfPeriod + 1) % 7;
\r
3518 if (periodStartDayOfWeek < 0) periodStartDayOfWeek += 7;
\r
3520 // Compute the week number. Initially, ignore the first week, which
\r
3521 // may be fractional (or may not be). We add periodStartDayOfWeek in
\r
3522 // order to fill out the first week, if it is fractional.
\r
3523 int weekNo = (desiredDay + periodStartDayOfWeek - 1)/7;
\r
3525 // If the first week is long enough, then count it. If
\r
3526 // the minimal days in the first week is one, or if the period start
\r
3527 // is zero, we always increment weekNo.
\r
3528 if ((7 - periodStartDayOfWeek) >= getMinimalDaysInFirstWeek()) ++weekNo;
\r
3534 * Returns the week number of a day, within a period. This may be the week number in
\r
3535 * a year, or the week number in a month. Usually this will be a value >= 1, but if
\r
3536 * some initial days of the period are excluded from week 1, because
\r
3537 * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} is > 1,
\r
3538 * then the week number will be zero for those
\r
3539 * initial days. This method requires the day of week for the given date in order to
\r
3540 * determine the result.
\r
3542 * <b>Subclassing:</b>
\r
3544 * This method is intended for use by subclasses in implementing their
\r
3545 * {@link #computeTime computeTime} and/or {@link #computeFields computeFields} methods.
\r
3546 * It is often useful in {@link #getActualMinimum getActualMinimum} and
\r
3547 * {@link #getActualMaximum getActualMaximum} as well.
\r
3549 * @param dayOfPeriod The {@link #DAY_OF_YEAR DAY_OF_YEAR} or
\r
3550 * {@link #DAY_OF_MONTH DAY_OF_MONTH} whose week number is desired.
\r
3551 * Should be 1 for the first day of the period.
\r
3553 * @param dayOfWeek The {@link #DAY_OF_WEEK DAY_OF_WEEK} for the day
\r
3554 * corresponding to the <code>dayOfPeriod</code> parameter.
\r
3555 * 1-based with 1=Sunday.
\r
3557 * @return The week number (one-based), or zero if the day falls before
\r
3558 * the first week because
\r
3559 * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek}
\r
3560 * is more than one.
\r
3563 protected final int weekNumber(int dayOfPeriod, int dayOfWeek)
\r
3565 return weekNumber(dayOfPeriod, dayOfPeriod, dayOfWeek);
\r
3568 //-------------------------------------------------------------------------
\r
3570 //-------------------------------------------------------------------------
\r
3573 * {@icu} Returns the difference between the given time and the time this
\r
3574 * calendar object is set to. If this calendar is set
\r
3575 * <em>before</em> the given time, the returned value will be
\r
3576 * positive. If this calendar is set <em>after</em> the given
\r
3577 * time, the returned value will be negative. The
\r
3578 * <code>field</code> parameter specifies the units of the return
\r
3579 * value. For example, if <code>fieldDifference(when,
\r
3580 * Calendar.MONTH)</code> returns 3, then this calendar is set to
\r
3581 * 3 months before <code>when</code>, and possibly some additional
\r
3582 * time less than one month.
\r
3584 * <p>As a side effect of this call, this calendar is advanced
\r
3585 * toward <code>when</code> by the given amount. That is, calling
\r
3586 * this method has the side effect of calling <code>add(field,
\r
3587 * n)</code>, where <code>n</code> is the return value.
\r
3589 * <p>Usage: To use this method, call it first with the largest
\r
3590 * field of interest, then with progressively smaller fields. For
\r
3594 * int y = cal.fieldDifference(when, Calendar.YEAR);
\r
3595 * int m = cal.fieldDifference(when, Calendar.MONTH);
\r
3596 * int d = cal.fieldDifference(when, Calendar.DATE);</pre>
\r
3598 * computes the difference between <code>cal</code> and
\r
3599 * <code>when</code> in years, months, and days.
\r
3601 * <p>Note: <code>fieldDifference()</code> is
\r
3602 * <em>asymmetrical</em>. That is, in the following code:
\r
3605 * cal.setTime(date1);
\r
3606 * int m1 = cal.fieldDifference(date2, Calendar.MONTH);
\r
3607 * int d1 = cal.fieldDifference(date2, Calendar.DATE);
\r
3608 * cal.setTime(date2);
\r
3609 * int m2 = cal.fieldDifference(date1, Calendar.MONTH);
\r
3610 * int d2 = cal.fieldDifference(date1, Calendar.DATE);</pre>
\r
3612 * one might expect that <code>m1 == -m2 && d1 == -d2</code>.
\r
3613 * However, this is not generally the case, because of
\r
3614 * irregularities in the underlying calendar system (e.g., the
\r
3615 * Gregorian calendar has a varying number of days per month).
\r
3617 * @param when the date to compare this calendar's time to
\r
3618 * @param field the field in which to compute the result
\r
3619 * @return the difference, either positive or negative, between
\r
3620 * this calendar's time and <code>when</code>, in terms of
\r
3621 * <code>field</code>.
\r
3624 public int fieldDifference(Date when, int field) {
\r
3626 long startMs = getTimeInMillis();
\r
3627 long targetMs = when.getTime();
\r
3628 // Always add from the start millis. This accomodates
\r
3629 // operations like adding years from February 29, 2000 up to
\r
3630 // February 29, 2004. If 1, 1, 1, 1 is added to the year
\r
3631 // field, the DOM gets pinned to 28 and stays there, giving an
\r
3632 // incorrect DOM difference of 1. We have to add 1, reset, 2,
\r
3633 // reset, 3, reset, 4.
\r
3634 if (startMs < targetMs) {
\r
3636 // Find a value that is too large
\r
3638 setTimeInMillis(startMs);
\r
3640 long ms = getTimeInMillis();
\r
3641 if (ms == targetMs) {
\r
3643 } else if (ms > targetMs) {
\r
3648 // Field difference too large to fit into int
\r
3649 throw new RuntimeException();
\r
3653 // Do a binary search
\r
3654 while ((max - min) > 1) {
\r
3655 int t = (min + max) / 2;
\r
3656 setTimeInMillis(startMs);
\r
3658 long ms = getTimeInMillis();
\r
3659 if (ms == targetMs) {
\r
3661 } else if (ms > targetMs) {
\r
3667 } else if (startMs > targetMs) {
\r
3668 //Eclipse stated the following is "dead code"
\r
3670 // This works, and makes the code smaller, but costs
\r
3671 // an extra object creation and an extra couple cycles
\r
3672 // of calendar computation.
\r
3673 setTimeInMillis(targetMs);
\r
3674 min = -fieldDifference(new Date(startMs), field);
\r
3677 // Find a value that is too small
\r
3679 setTimeInMillis(startMs);
\r
3681 long ms = getTimeInMillis();
\r
3682 if (ms == targetMs) {
\r
3684 } else if (ms < targetMs) {
\r
3689 // Field difference too large to fit into int
\r
3690 throw new RuntimeException();
\r
3694 // Do a binary search
\r
3695 while ((min - max) > 1) {
\r
3696 int t = (min + max) / 2;
\r
3697 setTimeInMillis(startMs);
\r
3699 long ms = getTimeInMillis();
\r
3700 if (ms == targetMs) {
\r
3702 } else if (ms < targetMs) {
\r
3709 // Set calendar to end point
\r
3710 setTimeInMillis(startMs);
\r
3716 * Sets the time zone with the given time zone value.
\r
3717 * @param value the given time zone.
\r
3720 public void setTimeZone(TimeZone value)
\r
3723 /* Recompute the fields from the time using the new zone. This also
\r
3724 * works if isTimeSet is false (after a call to set()). In that case
\r
3725 * the time will be computed from the fields using the new zone, then
\r
3726 * the fields will get recomputed from that. Consider the sequence of
\r
3727 * calls: cal.setTimeZone(EST); cal.set(HOUR, 1); cal.setTimeZone(PST).
\r
3728 * Is cal set to 1 o'clock EST or 1 o'clock PST? Answer: PST. More
\r
3729 * generally, a call to setTimeZone() affects calls to set() BEFORE AND
\r
3730 * AFTER it up to the next call to complete().
\r
3732 areFieldsSet = false;
\r
3736 * Returns the time zone.
\r
3737 * @return the time zone object associated with this calendar.
\r
3740 public TimeZone getTimeZone()
\r
3746 * Specify whether or not date/time interpretation is to be lenient. With
\r
3747 * lenient interpretation, a date such as "February 942, 1996" will be
\r
3748 * treated as being equivalent to the 941st day after February 1, 1996.
\r
3749 * With strict interpretation, such dates will cause an exception to be
\r
3752 * @see DateFormat#setLenient
\r
3755 public void setLenient(boolean lenient)
\r
3757 this.lenient = lenient;
\r
3761 * Tell whether date/time interpretation is to be lenient.
\r
3764 public boolean isLenient()
\r
3770 * Sets what the first day of the week is; e.g., Sunday in US,
\r
3771 * Monday in France.
\r
3772 * @param value the given first day of the week.
\r
3775 public void setFirstDayOfWeek(int value)
\r
3777 if (firstDayOfWeek != value) {
\r
3778 if (value < SUNDAY || value > SATURDAY) {
\r
3779 throw new IllegalArgumentException("Invalid day of week");
\r
3781 firstDayOfWeek = value;
\r
3782 areFieldsSet = false;
\r
3787 * Returns what the first day of the week is; e.g., Sunday in US,
\r
3788 * Monday in France.
\r
3789 * @return the first day of the week.
\r
3792 public int getFirstDayOfWeek()
\r
3794 return firstDayOfWeek;
\r
3798 * Sets what the minimal days required in the first week of the year are.
\r
3799 * For example, if the first week is defined as one that contains the first
\r
3800 * day of the first month of a year, call the method with value 1. If it
\r
3801 * must be a full week, use value 7.
\r
3802 * @param value the given minimal days required in the first week
\r
3806 public void setMinimalDaysInFirstWeek(int value)
\r
3808 // Values less than 1 have the same effect as 1; values greater
\r
3809 // than 7 have the same effect as 7. However, we normalize values
\r
3810 // so operator== and so forth work.
\r
3813 } else if (value > 7) {
\r
3816 if (minimalDaysInFirstWeek != value) {
\r
3817 minimalDaysInFirstWeek = value;
\r
3818 areFieldsSet = false;
\r
3823 * Returns what the minimal days required in the first week of the year are;
\r
3824 * e.g., if the first week is defined as one that contains the first day
\r
3825 * of the first month of a year, getMinimalDaysInFirstWeek returns 1. If
\r
3826 * the minimal days required must be a full week, getMinimalDaysInFirstWeek
\r
3828 * @return the minimal days required in the first week of the year.
\r
3831 public int getMinimalDaysInFirstWeek()
\r
3833 return minimalDaysInFirstWeek;
\r
3836 private static final int LIMITS[][] = {
\r
3837 // Minimum Greatest min Least max Greatest max
\r
3841 {/* */}, // WEEK_OF_YEAR
\r
3842 {/* */}, // WEEK_OF_MONTH
\r
3843 {/* */}, // DAY_OF_MONTH
\r
3844 {/* */}, // DAY_OF_YEAR
\r
3845 { 1, 1, 7, 7 }, // DAY_OF_WEEK
\r
3846 {/* */}, // DAY_OF_WEEK_IN_MONTH
\r
3847 { 0, 0, 1, 1 }, // AM_PM
\r
3848 { 0, 0, 11, 11 }, // HOUR
\r
3849 { 0, 0, 23, 23 }, // HOUR_OF_DAY
\r
3850 { 0, 0, 59, 59 }, // MINUTE
\r
3851 { 0, 0, 59, 59 }, // SECOND
\r
3852 { 0, 0, 999, 999 }, // MILLISECOND
\r
3853 {-12*ONE_HOUR, -12*ONE_HOUR, 12*ONE_HOUR, 12*ONE_HOUR }, // ZONE_OFFSET
\r
3854 { 0, 0, 1*ONE_HOUR, 1*ONE_HOUR }, // DST_OFFSET
\r
3855 {/* */}, // YEAR_WOY
\r
3856 { 1, 1, 7, 7 }, // DOW_LOCAL
\r
3857 {/* */}, // EXTENDED_YEAR
\r
3858 { -0x7F000000, -0x7F000000, 0x7F000000, 0x7F000000 }, // JULIAN_DAY
\r
3859 { 0, 0, 24*ONE_HOUR-1, 24*ONE_HOUR-1 }, // MILLISECONDS_IN_DAY
\r
3860 { 0, 0, 1, 1 }, // IS_LEAP_MONTH
\r
3865 * Subclass API for defining limits of different types.
\r
3866 * Subclasses must implement this method to return limits for the
\r
3867 * following fields:
\r
3876 * DAY_OF_WEEK_IN_MONTH
\r
3878 * EXTENDED_YEAR</pre>
\r
3880 * @param field one of the above field numbers
\r
3881 * @param limitType one of <code>MINIMUM</code>, <code>GREATEST_MINIMUM</code>,
\r
3882 * <code>LEAST_MAXIMUM</code>, or <code>MAXIMUM</code>
\r
3885 abstract protected int handleGetLimit(int field, int limitType);
\r
3888 * Returns a limit for a field.
\r
3889 * @param field the field, from 0..</code>getFieldCount()-1</code>
\r
3890 * @param limitType the type specifier for the limit
\r
3892 * @see #GREATEST_MINIMUM
\r
3893 * @see #LEAST_MAXIMUM
\r
3897 protected int getLimit(int field, int limitType) {
\r
3910 case MILLISECONDS_IN_DAY:
\r
3911 case IS_LEAP_MONTH:
\r
3912 return LIMITS[field][limitType];
\r
3914 case WEEK_OF_MONTH:
\r
3917 if (limitType == MINIMUM) {
\r
3918 limit = getMinimalDaysInFirstWeek() == 1 ? 1 : 0;
\r
3919 } else if (limitType == GREATEST_MINIMUM){
\r
3922 int minDaysInFirst = getMinimalDaysInFirstWeek();
\r
3923 int daysInMonth = handleGetLimit(DAY_OF_MONTH, limitType);
\r
3924 if (limitType == LEAST_MAXIMUM) {
\r
3925 limit = (daysInMonth + (7 - minDaysInFirst)) / 7;
\r
3926 } else { // limitType == MAXIMUM
\r
3927 limit = (daysInMonth + 6 + (7 - minDaysInFirst)) / 7;
\r
3934 return handleGetLimit(field, limitType);
\r
3938 * Limit type for <code>getLimit()</code> and <code>handleGetLimit()</code>
\r
3939 * indicating the minimum value that a field can take (least minimum).
\r
3941 * @see #handleGetLimit
\r
3944 protected static final int MINIMUM = 0;
\r
3947 * Limit type for <code>getLimit()</code> and <code>handleGetLimit()</code>
\r
3948 * indicating the greatest minimum value that a field can take.
\r
3950 * @see #handleGetLimit
\r
3953 protected static final int GREATEST_MINIMUM = 1;
\r
3956 * Limit type for <code>getLimit()</code> and <code>handleGetLimit()</code>
\r
3957 * indicating the least maximum value that a field can take.
\r
3959 * @see #handleGetLimit
\r
3962 protected static final int LEAST_MAXIMUM = 2;
\r
3965 * Limit type for <code>getLimit()</code> and <code>handleGetLimit()</code>
\r
3966 * indicating the maximum value that a field can take (greatest maximum).
\r
3968 * @see #handleGetLimit
\r
3971 protected static final int MAXIMUM = 3;
\r
3974 * Returns the minimum value for the given time field.
\r
3975 * e.g., for Gregorian DAY_OF_MONTH, 1.
\r
3976 * @param field the given time field.
\r
3977 * @return the minimum value for the given time field.
\r
3980 public final int getMinimum(int field) {
\r
3981 return getLimit(field, MINIMUM);
\r
3985 * Returns the maximum value for the given time field.
\r
3986 * e.g. for Gregorian DAY_OF_MONTH, 31.
\r
3987 * @param field the given time field.
\r
3988 * @return the maximum value for the given time field.
\r
3991 public final int getMaximum(int field) {
\r
3992 return getLimit(field, MAXIMUM);
\r
3996 * Returns the highest minimum value for the given field if varies.
\r
3997 * Otherwise same as getMinimum(). For Gregorian, no difference.
\r
3998 * @param field the given time field.
\r
3999 * @return the highest minimum value for the given time field.
\r
4002 public final int getGreatestMinimum(int field) {
\r
4003 return getLimit(field, GREATEST_MINIMUM);
\r
4007 * Returns the lowest maximum value for the given field if varies.
\r
4008 * Otherwise same as getMaximum(). e.g., for Gregorian DAY_OF_MONTH, 28.
\r
4009 * @param field the given time field.
\r
4010 * @return the lowest maximum value for the given time field.
\r
4013 public final int getLeastMaximum(int field) {
\r
4014 return getLimit(field, LEAST_MAXIMUM);
\r
4017 //-------------------------------------------------------------------------
\r
4018 // Weekend support -- determining which days of the week are the weekend
\r
4019 // in a given locale
\r
4020 //-------------------------------------------------------------------------
\r
4023 * {@icu} Returns whether the given day of the week is a weekday, a
\r
4024 * weekend day, or a day that transitions from one to the other,
\r
4025 * in this calendar system. If a transition occurs at midnight,
\r
4026 * then the days before and after the transition will have the
\r
4027 * type WEEKDAY or WEEKEND. If a transition occurs at a time
\r
4028 * other than midnight, then the day of the transition will have
\r
4029 * the type WEEKEND_ONSET or WEEKEND_CEASE. In this case, the
\r
4030 * method getWeekendTransition() will return the point of
\r
4032 * @param dayOfWeek either SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
\r
4033 * THURSDAY, FRIDAY, or SATURDAY
\r
4034 * @return either WEEKDAY, WEEKEND, WEEKEND_ONSET, or
\r
4036 * @exception IllegalArgumentException if dayOfWeek is not
\r
4037 * between SUNDAY and SATURDAY, inclusive
\r
4040 * @see #WEEKEND_ONSET
\r
4041 * @see #WEEKEND_CEASE
\r
4042 * @see #getWeekendTransition
\r
4043 * @see #isWeekend(Date)
\r
4044 * @see #isWeekend()
\r
4047 public int getDayOfWeekType(int dayOfWeek) {
\r
4048 if (dayOfWeek < SUNDAY || dayOfWeek > SATURDAY) {
\r
4049 throw new IllegalArgumentException("Invalid day of week");
\r
4051 if (weekendOnset < weekendCease) {
\r
4052 if (dayOfWeek < weekendOnset || dayOfWeek > weekendCease) {
\r
4056 if (dayOfWeek > weekendCease && dayOfWeek < weekendOnset) {
\r
4060 if (dayOfWeek == weekendOnset) {
\r
4061 return (weekendOnsetMillis == 0) ? WEEKEND : WEEKEND_ONSET;
\r
4063 if (dayOfWeek == weekendCease) {
\r
4064 return (weekendCeaseMillis == 0) ? WEEKDAY : WEEKEND_CEASE;
\r
4070 * {@icu} Returns the time during the day at which the weekend begins or end in this
\r
4071 * calendar system. If getDayOfWeekType(dayOfWeek) == WEEKEND_ONSET return the time
\r
4072 * at which the weekend begins. If getDayOfWeekType(dayOfWeek) == WEEKEND_CEASE
\r
4073 * return the time at which the weekend ends. If getDayOfWeekType(dayOfWeek) has some
\r
4074 * other value, then throw an exception.
\r
4075 * @param dayOfWeek either SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
\r
4076 * THURSDAY, FRIDAY, or SATURDAY
\r
4077 * @return the milliseconds after midnight at which the
\r
4078 * weekend begins or ends
\r
4079 * @exception IllegalArgumentException if dayOfWeek is not
\r
4080 * WEEKEND_ONSET or WEEKEND_CEASE
\r
4081 * @see #getDayOfWeekType
\r
4082 * @see #isWeekend(Date)
\r
4083 * @see #isWeekend()
\r
4086 public int getWeekendTransition(int dayOfWeek) {
\r
4087 if (dayOfWeek == weekendOnset) {
\r
4088 return weekendOnsetMillis;
\r
4089 } else if (dayOfWeek == weekendCease) {
\r
4090 return weekendCeaseMillis;
\r
4092 throw new IllegalArgumentException("Not weekend transition day");
\r
4096 * {@icu} Returns true if the given date and time is in the weekend in this calendar
\r
4097 * system. Equivalent to calling setTime() followed by isWeekend(). Note: This
\r
4098 * method changes the time this calendar is set to.
\r
4099 * @param date the date and time
\r
4100 * @return true if the given date and time is part of the
\r
4102 * @see #getDayOfWeekType
\r
4103 * @see #getWeekendTransition
\r
4104 * @see #isWeekend()
\r
4107 public boolean isWeekend(Date date) {
\r
4109 return isWeekend();
\r
4113 * {@icu} Returns true if this Calendar's current date and time is in the weekend in
\r
4114 * this calendar system.
\r
4115 * @return true if the given date and time is part of the
\r
4117 * @see #getDayOfWeekType
\r
4118 * @see #getWeekendTransition
\r
4119 * @see #isWeekend(Date)
\r
4122 public boolean isWeekend() {
\r
4123 int dow = get(DAY_OF_WEEK);
\r
4124 int dowt = getDayOfWeekType(dow);
\r
4130 default: // That is, WEEKEND_ONSET or WEEKEND_CEASE
\r
4131 // Use internalGet() because the above call to get() populated
\r
4133 // [Note: There should be a better way to get millis in day.
\r
4134 // For ICU4J, submit request for a MILLIS_IN_DAY field
\r
4135 // and a DAY_NUMBER field (could be Julian day #). - aliu]
\r
4136 int millisInDay = internalGet(MILLISECOND) + 1000 * (internalGet(SECOND) +
\r
4137 60 * (internalGet(MINUTE) + 60 * internalGet(HOUR_OF_DAY)));
\r
4138 int transition = getWeekendTransition(dow);
\r
4139 return (dowt == WEEKEND_ONSET)
\r
4140 ? (millisInDay >= transition)
\r
4141 : (millisInDay < transition);
\r
4143 // (We can never reach this point.)
\r
4146 //-------------------------------------------------------------------------
\r
4147 // End of weekend support
\r
4148 //-------------------------------------------------------------------------
\r
4151 * Overrides Cloneable
\r
4154 public Object clone()
\r
4157 Calendar other = (Calendar) super.clone();
\r
4159 other.fields = new int[fields.length];
\r
4160 other.stamp = new int[fields.length];
\r
4161 System.arraycopy(this.fields, 0, other.fields, 0, fields.length);
\r
4162 System.arraycopy(this.stamp, 0, other.stamp, 0, fields.length);
\r
4164 other.zone = (TimeZone) zone.clone();
\r
4167 catch (CloneNotSupportedException e) {
\r
4168 // this shouldn't happen, since we are Cloneable
\r
4169 throw new IllegalStateException();
\r
4174 * Returns a string representation of this calendar. This method
\r
4175 * is intended to be used only for debugging purposes, and the
\r
4176 * format of the returned string may vary between implementations.
\r
4177 * The returned string may be empty but may not be <code>null</code>.
\r
4179 * @return a string representation of this calendar.
\r
4182 public String toString() {
\r
4183 StringBuilder buffer = new StringBuilder();
\r
4184 buffer.append(getClass().getName());
\r
4185 buffer.append("[time=");
\r
4186 buffer.append(isTimeSet ? String.valueOf(time) : "?");
\r
4187 buffer.append(",areFieldsSet=");
\r
4188 buffer.append(areFieldsSet);
\r
4189 buffer.append(",areAllFieldsSet=");
\r
4190 buffer.append(areAllFieldsSet);
\r
4191 buffer.append(",lenient=");
\r
4192 buffer.append(lenient);
\r
4193 buffer.append(",zone=");
\r
4194 buffer.append(zone);
\r
4195 buffer.append(",firstDayOfWeek=");
\r
4196 buffer.append(firstDayOfWeek);
\r
4197 buffer.append(",minimalDaysInFirstWeek=");
\r
4198 buffer.append(minimalDaysInFirstWeek);
\r
4199 for (int i=0; i<fields.length; ++i) {
\r
4200 buffer.append(',').append(fieldName(i)).append('=');
\r
4201 buffer.append(isSet(i) ? String.valueOf(fields[i]) : "?");
\r
4203 buffer.append(']');
\r
4204 return buffer.toString();
\r
4207 // =======================privates===============================
\r
4210 * Internal class that holds cached locale data.
\r
4212 private static class WeekData {
\r
4213 public int firstDayOfWeek;
\r
4214 public int minimalDaysInFirstWeek;
\r
4215 public int weekendOnset;
\r
4216 public int weekendOnsetMillis;
\r
4217 public int weekendCease;
\r
4218 public int weekendCeaseMillis;
\r
4219 public ULocale actualLocale;
\r
4220 public WeekData(int fdow, int mdifw,
\r
4221 int weekendOnset, int weekendOnsetMillis,
\r
4222 int weekendCease, int weekendCeaseMillis,
\r
4223 ULocale actualLoc) {
\r
4224 this.firstDayOfWeek = fdow;
\r
4225 this.minimalDaysInFirstWeek = mdifw;
\r
4226 this.actualLocale = actualLoc;
\r
4227 this.weekendOnset = weekendOnset;
\r
4228 this.weekendOnsetMillis = weekendOnsetMillis;
\r
4229 this.weekendCease = weekendCease;
\r
4230 this.weekendCeaseMillis = weekendCeaseMillis;
\r
4235 * Set this calendar to contain week and weekend data for the given
\r
4237 * @param locale the locale
\r
4239 private void setWeekData(ULocale locale)
\r
4241 /* try to get the Locale data from the cache */
\r
4242 WeekData data = cachedLocaleData.get(locale);
\r
4244 if (data == null) { /* cache miss */
\r
4246 CalendarData calData = new CalendarData(locale, getType());
\r
4247 int[] dateTimeElements = calData.get("DateTimeElements").getIntVector();
\r
4248 int[] weekend = calData.get("weekend").getIntVector();
\r
4249 data = new WeekData(dateTimeElements[0],dateTimeElements[1],
\r
4254 calData.getULocale());
\r
4255 /* cache update */
\r
4256 cachedLocaleData.put(locale, data);
\r
4258 setFirstDayOfWeek(data.firstDayOfWeek);
\r
4259 setMinimalDaysInFirstWeek(data.minimalDaysInFirstWeek);
\r
4260 weekendOnset = data.weekendOnset;
\r
4261 weekendOnsetMillis = data.weekendOnsetMillis;
\r
4262 weekendCease = data.weekendCease;
\r
4263 weekendCeaseMillis = data.weekendCeaseMillis;
\r
4265 // TODO: determine the actual/valid locale
\r
4266 ULocale uloc = data.actualLocale;
\r
4267 setLocale(uloc, uloc);
\r
4271 * Recompute the time and update the status fields isTimeSet
\r
4272 * and areFieldsSet. Callers should check isTimeSet and only
\r
4273 * call this method if isTimeSet is false.
\r
4275 private void updateTime() {
\r
4277 // If we are lenient, we need to recompute the fields to normalize
\r
4278 // the values. Also, if we haven't set all the fields yet (i.e.,
\r
4279 // in a newly-created object), we need to fill in the fields. [LIU]
\r
4280 if (isLenient() || !areAllFieldsSet) areFieldsSet = false;
\r
4282 areFieldsVirtuallySet = false;
\r
4286 * Save the state of this object to a stream (i.e., serialize it).
\r
4288 private void writeObject(ObjectOutputStream stream)
\r
4289 throws IOException
\r
4291 // Try to compute the time correctly, for the future (stream
\r
4292 // version 2) in which we don't write out fields[] or isSet[].
\r
4297 catch (IllegalArgumentException e) {}
\r
4300 // Write out the 1.1 FCS object.
\r
4301 stream.defaultWriteObject();
\r
4305 * Reconstitute this object from a stream (i.e., deserialize it).
\r
4307 private void readObject(ObjectInputStream stream)
\r
4308 throws IOException, ClassNotFoundException {
\r
4310 stream.defaultReadObject();
\r
4315 areFieldsSet = areAllFieldsSet = false;
\r
4316 areFieldsVirtuallySet = true; // cause fields to be recalculated if requested.
\r
4317 nextStamp = MINIMUM_USER_STAMP;
\r
4321 //----------------------------------------------------------------------
\r
4323 //----------------------------------------------------------------------
\r
4326 * Converts the current millisecond time value <code>time</code> to
\r
4327 * field values in <code>fields[]</code>. This synchronizes the time
\r
4328 * field values with a new time that is set for the calendar. The time
\r
4329 * is <em>not</em> recomputed first; to recompute the time, then the
\r
4330 * fields, call the <code>complete</code> method.
\r
4334 protected void computeFields() {
\r
4335 int offsets[] = new int[2];
\r
4336 getTimeZone().getOffset(time, false, offsets);
\r
4337 long localMillis = time + offsets[0] + offsets[1];
\r
4339 // Mark fields as set. Do this before calling handleComputeFields().
\r
4340 int mask = internalSetMask;
\r
4341 for (int i=0; i<fields.length; ++i) {
\r
4342 if ((mask & 1) == 0) {
\r
4343 stamp[i] = INTERNALLY_SET;
\r
4350 // We used to check for and correct extreme millis values (near
\r
4351 // Long.MIN_VALUE or Long.MAX_VALUE) here. Such values would cause
\r
4352 // overflows from positive to negative (or vice versa) and had to
\r
4353 // be manually tweaked. We no longer need to do this because we
\r
4354 // have limited the range of supported dates to those that have a
\r
4355 // Julian day that fits into an int. This allows us to implement a
\r
4356 // JULIAN_DAY field and also removes some inelegant code. - Liu
\r
4359 long days = floorDivide(localMillis, ONE_DAY);
\r
4361 fields[JULIAN_DAY] = (int) days + EPOCH_JULIAN_DAY;
\r
4363 computeGregorianAndDOWFields(fields[JULIAN_DAY]);
\r
4365 // Call framework method to have subclass compute its fields.
\r
4366 // These must include, at a minimum, MONTH, DAY_OF_MONTH,
\r
4367 // EXTENDED_YEAR, YEAR, DAY_OF_YEAR. This method will call internalSet(),
\r
4368 // which will update stamp[].
\r
4369 handleComputeFields(fields[JULIAN_DAY]);
\r
4371 // Compute week-related fields, based on the subclass-computed
\r
4372 // fields computed by handleComputeFields().
\r
4373 computeWeekFields();
\r
4375 // Compute time-related fields. These are indepent of the date and
\r
4376 // of the subclass algorithm. They depend only on the local zone
\r
4377 // wall milliseconds in day.
\r
4378 int millisInDay = (int) (localMillis - (days * ONE_DAY));
\r
4379 fields[MILLISECONDS_IN_DAY] = millisInDay;
\r
4380 fields[MILLISECOND] = millisInDay % 1000;
\r
4381 millisInDay /= 1000;
\r
4382 fields[SECOND] = millisInDay % 60;
\r
4383 millisInDay /= 60;
\r
4384 fields[MINUTE] = millisInDay % 60;
\r
4385 millisInDay /= 60;
\r
4386 fields[HOUR_OF_DAY] = millisInDay;
\r
4387 fields[AM_PM] = millisInDay / 12; // Assume AM == 0
\r
4388 fields[HOUR] = millisInDay % 12;
\r
4389 fields[ZONE_OFFSET] = offsets[0];
\r
4390 fields[DST_OFFSET] = offsets[1];
\r
4394 * Compute the Gregorian calendar year, month, and day of month from
\r
4395 * the given Julian day. These values are not stored in fields, but in
\r
4396 * member variables gregorianXxx. Also compute the DAY_OF_WEEK and
\r
4397 * DOW_LOCAL fields.
\r
4399 private final void computeGregorianAndDOWFields(int julianDay) {
\r
4400 computeGregorianFields(julianDay);
\r
4402 // Compute day of week: JD 0 = Monday
\r
4403 int dow = fields[DAY_OF_WEEK] = julianDayToDayOfWeek(julianDay);
\r
4405 // Calculate 1-based localized day of week
\r
4406 int dowLocal = dow - getFirstDayOfWeek() + 1;
\r
4407 if (dowLocal < 1) {
\r
4410 fields[DOW_LOCAL] = dowLocal;
\r
4414 * Compute the Gregorian calendar year, month, and day of month from the
\r
4415 * Julian day. These values are not stored in fields, but in member
\r
4416 * variables gregorianXxx. They are used for time zone computations and by
\r
4417 * subclasses that are Gregorian derivatives. Subclasses may call this
\r
4418 * method to perform a Gregorian calendar millis->fields computation.
\r
4419 * To perform a Gregorian calendar fields->millis computation, call
\r
4420 * computeGregorianMonthStart().
\r
4421 * @see #computeGregorianMonthStart
\r
4424 protected final void computeGregorianFields(int julianDay) {
\r
4425 int year, month, dayOfMonth, dayOfYear;
\r
4427 // The Gregorian epoch day is zero for Monday January 1, year 1.
\r
4428 long gregorianEpochDay = julianDay - JAN_1_1_JULIAN_DAY;
\r
4430 // Here we convert from the day number to the multiple radix
\r
4431 // representation. We use 400-year, 100-year, and 4-year cycles.
\r
4432 // For example, the 4-year cycle has 4 years + 1 leap day; giving
\r
4433 // 1461 == 365*4 + 1 days.
\r
4434 int[] rem = new int[1];
\r
4435 int n400 = floorDivide(gregorianEpochDay, 146097, rem); // 400-year cycle length
\r
4436 int n100 = floorDivide(rem[0], 36524, rem); // 100-year cycle length
\r
4437 int n4 = floorDivide(rem[0], 1461, rem); // 4-year cycle length
\r
4438 int n1 = floorDivide(rem[0], 365, rem);
\r
4439 year = 400*n400 + 100*n100 + 4*n4 + n1;
\r
4440 dayOfYear = rem[0]; // zero-based day of year
\r
4441 if (n100 == 4 || n1 == 4) {
\r
4442 dayOfYear = 365; // Dec 31 at end of 4- or 400-yr cycle
\r
4447 boolean isLeap = ((year&0x3) == 0) && // equiv. to (year%4 == 0)
\r
4448 (year%100 != 0 || year%400 == 0);
\r
4450 int correction = 0;
\r
4451 int march1 = isLeap ? 60 : 59; // zero-based DOY for March 1
\r
4452 if (dayOfYear >= march1) correction = isLeap ? 1 : 2;
\r
4453 month = (12 * (dayOfYear + correction) + 6) / 367; // zero-based month
\r
4454 dayOfMonth = dayOfYear -
\r
4455 GREGORIAN_MONTH_COUNT[month][isLeap?3:2] + 1; // one-based DOM
\r
4457 gregorianYear = year;
\r
4458 gregorianMonth = month; // 0-based already
\r
4459 gregorianDayOfMonth = dayOfMonth; // 1-based already
\r
4460 gregorianDayOfYear = dayOfYear + 1; // Convert from 0-based to 1-based
\r
4464 * Compute the fields WEEK_OF_YEAR, YEAR_WOY, WEEK_OF_MONTH,
\r
4465 * DAY_OF_WEEK_IN_MONTH, and DOW_LOCAL from EXTENDED_YEAR, YEAR,
\r
4466 * DAY_OF_WEEK, and DAY_OF_YEAR. The latter fields are computed by the
\r
4467 * subclass based on the calendar system.
\r
4469 * <p>The YEAR_WOY field is computed simplistically. It is equal to YEAR
\r
4470 * most of the time, but at the year boundary it may be adjusted to YEAR-1
\r
4471 * or YEAR+1 to reflect the overlap of a week into an adjacent year. In
\r
4472 * this case, a simple increment or decrement is performed on YEAR, even
\r
4473 * though this may yield an invalid YEAR value. For instance, if the YEAR
\r
4474 * is part of a calendar system with an N-year cycle field CYCLE, then
\r
4475 * incrementing the YEAR may involve incrementing CYCLE and setting YEAR
\r
4476 * back to 0 or 1. This is not handled by this code, and in fact cannot be
\r
4477 * simply handled without having subclasses define an entire parallel set of
\r
4478 * fields for fields larger than or equal to a year. This additional
\r
4479 * complexity is not warranted, since the intention of the YEAR_WOY field is
\r
4480 * to support ISO 8601 notation, so it will typically be used with a
\r
4481 * proleptic Gregorian calendar, which has no field larger than a year.
\r
4483 private final void computeWeekFields() {
\r
4484 int eyear = fields[EXTENDED_YEAR];
\r
4485 int dayOfWeek = fields[DAY_OF_WEEK];
\r
4486 int dayOfYear = fields[DAY_OF_YEAR];
\r
4488 // WEEK_OF_YEAR start
\r
4489 // Compute the week of the year. For the Gregorian calendar, valid week
\r
4490 // numbers run from 1 to 52 or 53, depending on the year, the first day
\r
4491 // of the week, and the minimal days in the first week. For other
\r
4492 // calendars, the valid range may be different -- it depends on the year
\r
4493 // length. Days at the start of the year may fall into the last week of
\r
4494 // the previous year; days at the end of the year may fall into the
\r
4495 // first week of the next year. ASSUME that the year length is less than
\r
4497 int yearOfWeekOfYear = eyear;
\r
4498 int relDow = (dayOfWeek + 7 - getFirstDayOfWeek()) % 7; // 0..6
\r
4499 int relDowJan1 = (dayOfWeek - dayOfYear + 7001 - getFirstDayOfWeek()) % 7; // 0..6
\r
4500 int woy = (dayOfYear - 1 + relDowJan1) / 7; // 0..53
\r
4501 if ((7 - relDowJan1) >= getMinimalDaysInFirstWeek()) {
\r
4505 // Adjust for weeks at the year end that overlap into the previous or
\r
4506 // next calendar year.
\r
4508 // We are the last week of the previous year.
\r
4509 // Check to see if we are in the last week; if so, we need
\r
4510 // to handle the case in which we are the first week of the
\r
4513 int prevDoy = dayOfYear + handleGetYearLength(eyear - 1);
\r
4514 woy = weekNumber(prevDoy, dayOfWeek);
\r
4515 yearOfWeekOfYear--;
\r
4517 int lastDoy = handleGetYearLength(eyear);
\r
4518 // Fast check: For it to be week 1 of the next year, the DOY
\r
4519 // must be on or after L-5, where L is yearLength(), then it
\r
4520 // cannot possibly be week 1 of the next year:
\r
4522 // doy: 359 360 361 362 363 364 365 001
\r
4523 // dow: 1 2 3 4 5 6 7
\r
4524 if (dayOfYear >= (lastDoy - 5)) {
\r
4525 int lastRelDow = (relDow + lastDoy - dayOfYear) % 7;
\r
4526 if (lastRelDow < 0) {
\r
4529 if (((6 - lastRelDow) >= getMinimalDaysInFirstWeek()) &&
\r
4530 ((dayOfYear + 7 - relDow) > lastDoy)) {
\r
4532 yearOfWeekOfYear++;
\r
4536 fields[WEEK_OF_YEAR] = woy;
\r
4537 fields[YEAR_WOY] = yearOfWeekOfYear;
\r
4538 // WEEK_OF_YEAR end
\r
4540 int dayOfMonth = fields[DAY_OF_MONTH];
\r
4541 fields[WEEK_OF_MONTH] = weekNumber(dayOfMonth, dayOfWeek);
\r
4542 fields[DAY_OF_WEEK_IN_MONTH] = (dayOfMonth-1) / 7 + 1;
\r
4545 //----------------------------------------------------------------------
\r
4547 //----------------------------------------------------------------------
\r
4550 * Value to OR against resolve table field values for remapping.
\r
4551 * @see #resolveFields
\r
4554 protected static final int RESOLVE_REMAP = 32;
\r
4555 // A power of 2 greater than or equal to MAX_FIELD_COUNT
\r
4557 // Default table for day in year
\r
4558 static final int[][][] DATE_PRECEDENCE = {
\r
4561 { WEEK_OF_YEAR, DAY_OF_WEEK },
\r
4562 { WEEK_OF_MONTH, DAY_OF_WEEK },
\r
4563 { DAY_OF_WEEK_IN_MONTH, DAY_OF_WEEK },
\r
4564 { WEEK_OF_YEAR, DOW_LOCAL },
\r
4565 { WEEK_OF_MONTH, DOW_LOCAL },
\r
4566 { DAY_OF_WEEK_IN_MONTH, DOW_LOCAL },
\r
4571 { WEEK_OF_MONTH },
\r
4572 { DAY_OF_WEEK_IN_MONTH },
\r
4573 { RESOLVE_REMAP | DAY_OF_WEEK_IN_MONTH, DAY_OF_WEEK },
\r
4574 { RESOLVE_REMAP | DAY_OF_WEEK_IN_MONTH, DOW_LOCAL },
\r
4578 static final int[][][] DOW_PRECEDENCE = {
\r
4586 * Given a precedence table, return the newest field combination in
\r
4587 * the table, or -1 if none is found.
\r
4589 * <p>The precedence table is a 3-dimensional array of integers. It
\r
4590 * may be thought of as an array of groups. Each group is an array of
\r
4591 * lines. Each line is an array of field numbers. Within a line, if
\r
4592 * all fields are set, then the time stamp of the line is taken to be
\r
4593 * the stamp of the most recently set field. If any field of a line is
\r
4594 * unset, then the line fails to match. Within a group, the line with
\r
4595 * the newest time stamp is selected. The first field of the line is
\r
4596 * returned to indicate which line matched.
\r
4598 * <p>In some cases, it may be desirable to map a line to field that
\r
4599 * whose stamp is NOT examined. For example, if the best field is
\r
4600 * DAY_OF_WEEK then the DAY_OF_WEEK_IN_MONTH algorithm may be used. In
\r
4601 * order to do this, insert the value <code>REMAP_RESOLVE | F</code> at
\r
4602 * the start of the line, where <code>F</code> is the desired return
\r
4603 * field value. This field will NOT be examined; it only determines
\r
4604 * the return value if the other fields in the line are the newest.
\r
4606 * <p>If all lines of a group contain at least one unset field, then no
\r
4607 * line will match, and the group as a whole will fail to match. In
\r
4608 * that case, the next group will be processed. If all groups fail to
\r
4609 * match, then -1 is returned.
\r
4612 protected int resolveFields(int[][][] precedenceTable) {
\r
4613 int bestField = -1;
\r
4614 for (int g=0; g<precedenceTable.length && bestField < 0; ++g) {
\r
4615 int[][] group = precedenceTable[g];
\r
4616 int bestStamp = UNSET;
\r
4618 for (int l=0; l<group.length; ++l) {
\r
4619 int[] line= group[l];
\r
4620 int lineStamp = UNSET;
\r
4621 // Skip over first entry if it is negative
\r
4622 for (int i=(line[0]>=RESOLVE_REMAP)?1:0; i<line.length; ++i) {
\r
4623 int s = stamp[line[i]];
\r
4624 // If any field is unset then don't use this line
\r
4626 continue linesInGroup;
\r
4628 lineStamp = Math.max(lineStamp, s);
\r
4631 // Record new maximum stamp & field no.
\r
4632 if (lineStamp > bestStamp) {
\r
4633 bestStamp = lineStamp;
\r
4634 bestField = line[0]; // First field refers to entire line
\r
4638 return (bestField>=RESOLVE_REMAP)?(bestField&(RESOLVE_REMAP-1)):bestField;
\r
4642 * Returns the newest stamp of a given range of fields.
\r
4645 protected int newestStamp(int first, int last, int bestStampSoFar) {
\r
4646 int bestStamp = bestStampSoFar;
\r
4647 for (int i=first; i<=last; ++i) {
\r
4648 if (stamp[i] > bestStamp) {
\r
4649 bestStamp = stamp[i];
\r
4656 * Returns the timestamp of a field.
\r
4659 protected final int getStamp(int field) {
\r
4660 return stamp[field];
\r
4664 * Returns the field that is newer, either defaultField, or
\r
4665 * alternateField. If neither is newer or neither is set, return defaultField.
\r
4668 protected int newerField(int defaultField, int alternateField) {
\r
4669 if (stamp[alternateField] > stamp[defaultField]) {
\r
4670 return alternateField;
\r
4672 return defaultField;
\r
4676 * Ensure that each field is within its valid range by calling {@link
\r
4677 * #validateField(int)} on each field that has been set. This method
\r
4678 * should only be called if this calendar is not lenient.
\r
4680 * @see #validateField(int)
\r
4683 protected void validateFields() {
\r
4684 for (int field = 0; field < fields.length; field++) {
\r
4685 if (isSet(field)) {
\r
4686 validateField(field);
\r
4692 * Validate a single field of this calendar. Subclasses should
\r
4693 * override this method to validate any calendar-specific fields.
\r
4694 * Generic fields can be handled by
\r
4695 * <code>Calendar.validateField()</code>.
\r
4696 * @see #validateField(int, int, int)
\r
4699 protected void validateField(int field) {
\r
4702 case DAY_OF_MONTH:
\r
4703 y = handleGetExtendedYear();
\r
4704 validateField(field, 1, handleGetMonthLength(y, internalGet(MONTH)));
\r
4707 y = handleGetExtendedYear();
\r
4708 validateField(field, 1, handleGetYearLength(y));
\r
4710 case DAY_OF_WEEK_IN_MONTH:
\r
4711 if (internalGet(field) == 0) {
\r
4712 throw new IllegalArgumentException("DAY_OF_WEEK_IN_MONTH cannot be zero");
\r
4714 validateField(field, getMinimum(field), getMaximum(field));
\r
4717 validateField(field, getMinimum(field), getMaximum(field));
\r
4723 * Validate a single field of this calendar given its minimum and
\r
4724 * maximum allowed value. If the field is out of range, throw a
\r
4725 * descriptive <code>IllegalArgumentException</code>. Subclasses may
\r
4726 * use this method in their implementation of {@link
\r
4727 * #validateField(int)}.
\r
4730 protected final void validateField(int field, int min, int max) {
\r
4731 int value = fields[field];
\r
4732 if (value < min || value > max) {
\r
4733 throw new IllegalArgumentException(fieldName(field) +
\r
4734 '=' + value + ", valid range=" +
\r
4735 min + ".." + max);
\r
4740 * Converts the current field values in <code>fields[]</code> to the
\r
4741 * millisecond time value <code>time</code>.
\r
4744 protected void computeTime() {
\r
4745 if (!isLenient()) {
\r
4749 // Compute the Julian day
\r
4750 int julianDay = computeJulianDay();
\r
4752 long millis = julianDayToMillis(julianDay);
\r
4756 // We only use MILLISECONDS_IN_DAY if it has been set by the user.
\r
4757 // This makes it possible for the caller to set the calendar to a
\r
4758 // time and call clear(MONTH) to reset the MONTH to January. This
\r
4759 // is legacy behavior. Without this, clear(MONTH) has no effect,
\r
4760 // since the internally set JULIAN_DAY is used.
\r
4761 if (stamp[MILLISECONDS_IN_DAY] >= MINIMUM_USER_STAMP &&
\r
4762 newestStamp(AM_PM, MILLISECOND, UNSET) <= stamp[MILLISECONDS_IN_DAY]) {
\r
4763 millisInDay = internalGet(MILLISECONDS_IN_DAY);
\r
4765 millisInDay = computeMillisInDay();
\r
4768 // Compute the time zone offset and DST offset. There are two potential
\r
4769 // ambiguities here. We'll assume a 2:00 am (wall time) switchover time
\r
4770 // for discussion purposes here.
\r
4771 // 1. The transition into DST. Here, a designated time of 2:00 am - 2:59 am
\r
4772 // can be in standard or in DST depending. However, 2:00 am is an invalid
\r
4773 // representation (the representation jumps from 1:59:59 am Std to 3:00:00 am DST).
\r
4774 // We assume standard time, that is, 2:30 am is interpreted as 3:30 am DST.
\r
4775 // 2. The transition out of DST. Here, a designated time of 1:00 am - 1:59 am
\r
4776 // can be in standard or DST. Both are valid representations (the rep
\r
4777 // jumps from 1:59:59 DST to 1:00:00 Std).
\r
4778 // Again, we assume standard time, that is, 1:30 am is interpreted as 1:30 am Std.
\r
4779 // We use the TimeZone object, unless the user has explicitly set the ZONE_OFFSET
\r
4780 // or DST_OFFSET fields; then we use those fields.
\r
4781 if (stamp[ZONE_OFFSET] >= MINIMUM_USER_STAMP ||
\r
4782 stamp[DST_OFFSET] >= MINIMUM_USER_STAMP) {
\r
4783 millisInDay -= internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET);
\r
4785 millisInDay -= computeZoneOffset(millis, millisInDay);
\r
4788 time = millis + millisInDay;
\r
4792 * Compute the milliseconds in the day from the fields. This is a
\r
4793 * value from 0 to 23:59:59.999 inclusive, unless fields are out of
\r
4794 * range, in which case it can be an arbitrary value. This value
\r
4795 * reflects local zone wall time.
\r
4798 protected int computeMillisInDay() {
\r
4799 // Do the time portion of the conversion.
\r
4801 int millisInDay = 0;
\r
4803 // Find the best set of fields specifying the time of day. There
\r
4804 // are only two possibilities here; the HOUR_OF_DAY or the
\r
4805 // AM_PM and the HOUR.
\r
4806 int hourOfDayStamp = stamp[HOUR_OF_DAY];
\r
4807 int hourStamp = Math.max(stamp[HOUR], stamp[AM_PM]);
\r
4808 int bestStamp = (hourStamp > hourOfDayStamp) ? hourStamp : hourOfDayStamp;
\r
4811 if (bestStamp != UNSET) {
\r
4812 if (bestStamp == hourOfDayStamp) {
\r
4813 // Don't normalize here; let overflow bump into the next period.
\r
4814 // This is consistent with how we handle other fields.
\r
4815 millisInDay += internalGet(HOUR_OF_DAY);
\r
4817 // Don't normalize here; let overflow bump into the next period.
\r
4818 // This is consistent with how we handle other fields.
\r
4819 millisInDay += internalGet(HOUR);
\r
4820 millisInDay += 12 * internalGet(AM_PM); // Default works for unset AM_PM
\r
4824 // We use the fact that unset == 0; we start with millisInDay
\r
4825 // == HOUR_OF_DAY.
\r
4826 millisInDay *= 60;
\r
4827 millisInDay += internalGet(MINUTE); // now have minutes
\r
4828 millisInDay *= 60;
\r
4829 millisInDay += internalGet(SECOND); // now have seconds
\r
4830 millisInDay *= 1000;
\r
4831 millisInDay += internalGet(MILLISECOND); // now have millis
\r
4833 return millisInDay;
\r
4837 * This method can assume EXTENDED_YEAR has been set.
\r
4838 * @param millis milliseconds of the date fields (local midnight millis)
\r
4839 * @param millisInDay milliseconds of the time fields; may be out
\r
4841 * @return total zone offset (raw + DST) for the given moment
\r
4844 protected int computeZoneOffset(long millis, int millisInDay) {
\r
4845 int offsets[] = new int[2];
\r
4846 zone.getOffset(millis + millisInDay, true, offsets);
\r
4847 return offsets[0] + offsets[1];
\r
4849 // Note: Because we pass in wall millisInDay, rather than
\r
4850 // standard millisInDay, we interpret "1:00 am" on the day
\r
4851 // of cessation of DST as "1:00 am Std" (assuming the time
\r
4852 // of cessation is 2:00 am).
\r
4856 * Compute the Julian day number as specified by this calendar's fields.
\r
4859 protected int computeJulianDay() {
\r
4861 // We want to see if any of the date fields is newer than the
\r
4862 // JULIAN_DAY. If not, then we use JULIAN_DAY. If so, then we do
\r
4863 // the normal resolution. We only use JULIAN_DAY if it has been
\r
4864 // set by the user. This makes it possible for the caller to set
\r
4865 // the calendar to a time and call clear(MONTH) to reset the MONTH
\r
4866 // to January. This is legacy behavior. Without this,
\r
4867 // clear(MONTH) has no effect, since the internally set JULIAN_DAY
\r
4869 if (stamp[JULIAN_DAY] >= MINIMUM_USER_STAMP) {
\r
4870 int bestStamp = newestStamp(ERA, DAY_OF_WEEK_IN_MONTH, UNSET);
\r
4871 bestStamp = newestStamp(YEAR_WOY, EXTENDED_YEAR, bestStamp);
\r
4872 if (bestStamp <= stamp[JULIAN_DAY]) {
\r
4873 return internalGet(JULIAN_DAY);
\r
4877 int bestField = resolveFields(getFieldResolutionTable());
\r
4878 if (bestField < 0) {
\r
4879 bestField = DAY_OF_MONTH;
\r
4882 return handleComputeJulianDay(bestField);
\r
4886 * Returns the field resolution array for this calendar. Calendars that
\r
4887 * define additional fields or change the semantics of existing fields
\r
4888 * should override this method to adjust the field resolution semantics
\r
4889 * accordingly. Other subclasses should not override this method.
\r
4890 * @see #resolveFields
\r
4893 protected int[][][] getFieldResolutionTable() {
\r
4894 return DATE_PRECEDENCE;
\r
4898 * Returns the Julian day number of day before the first day of the
\r
4899 * given month in the given extended year. Subclasses should override
\r
4900 * this method to implement their calendar system.
\r
4901 * @param eyear the extended year
\r
4902 * @param month the zero-based month, or 0 if useMonth is false
\r
4903 * @param useMonth if false, compute the day before the first day of
\r
4904 * the given year, otherwise, compute the day before the first day of
\r
4906 * @return the Julian day number of the day before the first
\r
4907 * day of the given month and year
\r
4910 abstract protected int handleComputeMonthStart(int eyear, int month,
\r
4911 boolean useMonth);
\r
4914 * Returns the extended year defined by the current fields. This will
\r
4915 * use the EXTENDED_YEAR field or the YEAR and supra-year fields (such
\r
4916 * as ERA) specific to the calendar system, depending on which set of
\r
4917 * fields is newer.
\r
4918 * @return the extended year
\r
4921 abstract protected int handleGetExtendedYear();
\r
4923 // (The following method is not called because all existing subclasses
\r
4924 // override it. 2003-06-11 ICU 2.6 Alan)
\r
4927 * Returns the number of days in the given month of the given extended
\r
4928 * year of this calendar system. Subclasses should override this
\r
4929 * method if they can provide a more correct or more efficient
\r
4930 * implementation than the default implementation in Calendar.
\r
4933 protected int handleGetMonthLength(int extendedYear, int month) {
\r
4934 return handleComputeMonthStart(extendedYear, month+1, true) -
\r
4935 handleComputeMonthStart(extendedYear, month, true);
\r
4940 * Returns the number of days in the given extended year of this
\r
4941 * calendar system. Subclasses should override this method if they can
\r
4942 * provide a more correct or more efficient implementation than the
\r
4943 * default implementation in Calendar.
\r
4946 protected int handleGetYearLength(int eyear) {
\r
4947 return handleComputeMonthStart(eyear+1, 0, false) -
\r
4948 handleComputeMonthStart(eyear, 0, false);
\r
4952 * Subclasses that use additional fields beyond those defined in
\r
4953 * <code>Calendar</code> should override this method to return an
\r
4954 * <code>int[]</code> array of the appropriate length. The length
\r
4955 * must be at least <code>BASE_FIELD_COUNT</code> and no more than
\r
4956 * <code>MAX_FIELD_COUNT</code>.
\r
4959 protected int[] handleCreateFields() {
\r
4960 return new int[BASE_FIELD_COUNT];
\r
4964 * Subclasses may override this.
\r
4965 * Called by handleComputeJulianDay. Returns the default month (0-based) for the year,
\r
4966 * taking year and era into account. Defaults to 0 (JANUARY) for Gregorian.
\r
4967 * @param extendedYear the extendedYear, as returned by handleGetExtendedYear
\r
4968 * @return the default month
\r
4969 * @draft ICU 3.6 (retain)
\r
4970 * @provisional This API might change or be removed in a future release.
\r
4973 protected int getDefaultMonthInYear(int extendedYear) {
\r
4974 return Calendar.JANUARY;
\r
4978 * Subclasses may override this.
\r
4979 * Called by handleComputeJulianDay. Returns the default day (1-based) for the month,
\r
4980 * taking currently-set year and era into account. Defaults to 1 for Gregorian.
\r
4981 * @param extendedYear the extendedYear, as returned by handleGetExtendedYear
\r
4982 * @param month the month, as returned by getDefaultMonthInYear
\r
4983 * @return the default day of the month
\r
4984 * @draft ICU 3.6 (retain)
\r
4985 * @provisional This API might change or be removed in a future release.
\r
4986 * @see #DAY_OF_MONTH
\r
4988 protected int getDefaultDayInMonth(int extendedYear, int month) {
\r
4994 * Subclasses may override this. This method calls
\r
4995 * handleGetMonthLength() to obtain the calendar-specific month
\r
4999 protected int handleComputeJulianDay(int bestField) {
\r
5001 boolean useMonth = (bestField == DAY_OF_MONTH ||
\r
5002 bestField == WEEK_OF_MONTH ||
\r
5003 bestField == DAY_OF_WEEK_IN_MONTH);
\r
5007 if (bestField == WEEK_OF_YEAR) {
\r
5008 // Nota Bene! It is critical that YEAR_WOY be used as the year here, if it is
\r
5009 // set. Otherwise, when WOY is the best field, the year may be wrong at the
\r
5010 // extreme limits of the year. If YEAR_WOY is not set then it will fall back.
\r
5011 // TODO: Should resolveField(YEAR_PRECEDENCE) be brought to bear?
\r
5012 year = internalGet(YEAR_WOY, handleGetExtendedYear());
\r
5014 year = handleGetExtendedYear();
\r
5017 internalSet(EXTENDED_YEAR, year);
\r
5019 int month = useMonth ? internalGet(MONTH, getDefaultMonthInYear(year)) : 0;
\r
5021 // Get the Julian day of the day BEFORE the start of this year.
\r
5022 // If useMonth is true, get the day before the start of the month.
\r
5023 int julianDay = handleComputeMonthStart(year, month, useMonth);
\r
5025 if (bestField == DAY_OF_MONTH) {
\r
5026 if(isSet(DAY_OF_MONTH)) {
\r
5027 return julianDay + internalGet(DAY_OF_MONTH, getDefaultDayInMonth(year, month));
\r
5029 return julianDay + getDefaultDayInMonth(year, month);
\r
5033 if (bestField == DAY_OF_YEAR) {
\r
5034 return julianDay + internalGet(DAY_OF_YEAR);
\r
5037 int firstDOW = getFirstDayOfWeek(); // Localized fdw
\r
5039 // At this point julianDay is the 0-based day BEFORE the first day of
\r
5040 // January 1, year 1 of the given calendar. If julianDay == 0, it
\r
5041 // specifies (Jan. 1, 1) - 1, in whatever calendar we are using (Julian
\r
5044 // At this point we need to process the WEEK_OF_MONTH or
\r
5045 // WEEK_OF_YEAR, which are similar, or the DAY_OF_WEEK_IN_MONTH.
\r
5046 // First, perform initial shared computations. These locate the
\r
5047 // first week of the period.
\r
5049 // Get the 0-based localized DOW of day one of the month or year.
\r
5050 // Valid range 0..6.
\r
5051 int first = julianDayToDayOfWeek(julianDay + 1) - firstDOW;
\r
5056 // Get zero-based localized DOW, valid range 0..6. This is the DOW
\r
5057 // we are looking for.
\r
5059 switch (resolveFields(DOW_PRECEDENCE)) {
\r
5061 dowLocal = internalGet(DAY_OF_WEEK) - firstDOW;
\r
5064 dowLocal = internalGet(DOW_LOCAL) - 1;
\r
5067 dowLocal = dowLocal % 7;
\r
5068 if (dowLocal < 0) {
\r
5072 // Find the first target DOW (dowLocal) in the month or year.
\r
5073 // Actually, it may be just before the first of the month or year.
\r
5074 // It will be an integer from -5..7.
\r
5075 int date = 1 - first + dowLocal;
\r
5077 if (bestField == DAY_OF_WEEK_IN_MONTH) {
\r
5079 // Adjust the target DOW to be in the month or year.
\r
5084 // The only trickiness occurs if the day-of-week-in-month is
\r
5086 int dim = internalGet(DAY_OF_WEEK_IN_MONTH, 1);
\r
5088 date += 7*(dim - 1);
\r
5091 // Move date to the last of this day-of-week in this month,
\r
5092 // then back up as needed. If dim==-1, we don't back up at
\r
5093 // all. If dim==-2, we back up once, etc. Don't back up
\r
5094 // past the first of the given day-of-week in this month.
\r
5095 // Note that we handle -2, -3, etc. correctly, even though
\r
5096 // values < -1 are technically disallowed.
\r
5097 int m = internalGet(MONTH, JANUARY);
\r
5098 int monthLength = handleGetMonthLength(year, m);
\r
5099 date += ((monthLength - date) / 7 + dim + 1) * 7;
\r
5102 // assert(bestField == WEEK_OF_MONTH || bestField == WEEK_OF_YEAR)
\r
5104 // Adjust for minimal days in first week
\r
5105 if ((7 - first) < getMinimalDaysInFirstWeek()) {
\r
5109 // Now adjust for the week number.
\r
5110 date += 7 * (internalGet(bestField) - 1);
\r
5113 return julianDay + date;
\r
5117 * Compute the Julian day of a month of the Gregorian calendar.
\r
5118 * Subclasses may call this method to perform a Gregorian calendar
\r
5119 * fields->millis computation. To perform a Gregorian calendar
\r
5120 * millis->fields computation, call computeGregorianFields().
\r
5121 * @param year extended Gregorian year
\r
5122 * @param month zero-based Gregorian month
\r
5123 * @return the Julian day number of the day before the first
\r
5124 * day of the given month in the given extended year
\r
5125 * @see #computeGregorianFields
\r
5128 protected int computeGregorianMonthStart(int year, int month) {
\r
5130 // If the month is out of range, adjust it into range, and
\r
5131 // modify the extended year value accordingly.
\r
5132 if (month < 0 || month > 11) {
\r
5133 int[] rem = new int[1];
\r
5134 year += floorDivide(month, 12, rem);
\r
5138 boolean isLeap = (year%4 == 0) && ((year%100 != 0) || (year%400 == 0));
\r
5140 // This computation is actually ... + (JAN_1_1_JULIAN_DAY - 3) + 2.
\r
5141 // Add 2 because Gregorian calendar starts 2 days after Julian
\r
5143 int julianDay = 365*y + floorDivide(y, 4) - floorDivide(y, 100) +
\r
5144 floorDivide(y, 400) + JAN_1_1_JULIAN_DAY - 1;
\r
5146 // At this point julianDay indicates the day BEFORE the first day
\r
5147 // of January 1, <eyear> of the Gregorian calendar.
\r
5149 julianDay += GREGORIAN_MONTH_COUNT[month][isLeap?3:2];
\r
5155 //----------------------------------------------------------------------
\r
5157 // For subclasses to override
\r
5158 //----------------------------------------------------------------------
\r
5160 // (The following method is not called because all existing subclasses
\r
5161 // override it. 2003-06-11 ICU 2.6 Alan)
\r
5164 * Subclasses may override this method to compute several fields
\r
5165 * specific to each calendar system. These are:
\r
5170 * <li>DAY_OF_MONTH
\r
5172 * <li>EXTENDED_YEAR</ul>
\r
5174 * Subclasses can refer to the DAY_OF_WEEK and DOW_LOCAL fields, which
\r
5175 * will be set when this method is called. Subclasses can also call
\r
5176 * the getGregorianXxx() methods to obtain Gregorian calendar
\r
5177 * equivalents for the given Julian day.
\r
5179 * <p>In addition, subclasses should compute any subclass-specific
\r
5180 * fields, that is, fields from BASE_FIELD_COUNT to
\r
5181 * getFieldCount() - 1.
\r
5183 * <p>The default implementation in <code>Calendar</code> implements
\r
5184 * a pure proleptic Gregorian calendar.
\r
5187 protected void handleComputeFields(int julianDay) {
\r
5188 internalSet(MONTH, getGregorianMonth());
\r
5189 internalSet(DAY_OF_MONTH, getGregorianDayOfMonth());
\r
5190 internalSet(DAY_OF_YEAR, getGregorianDayOfYear());
\r
5191 int eyear = getGregorianYear();
\r
5192 internalSet(EXTENDED_YEAR, eyear);
\r
5193 int era = GregorianCalendar.AD;
\r
5195 era = GregorianCalendar.BC;
\r
5196 eyear = 1 - eyear;
\r
5198 internalSet(ERA, era);
\r
5199 internalSet(YEAR, eyear);
\r
5203 //----------------------------------------------------------------------
\r
5205 // For subclasses to call
\r
5206 //----------------------------------------------------------------------
\r
5209 * Returns the extended year on the Gregorian calendar as computed by
\r
5210 * <code>computeGregorianFields()</code>.
\r
5211 * @see #computeGregorianFields
\r
5214 protected final int getGregorianYear() {
\r
5215 return gregorianYear;
\r
5219 * Returns the month (0-based) on the Gregorian calendar as computed by
\r
5220 * <code>computeGregorianFields()</code>.
\r
5221 * @see #computeGregorianFields
\r
5224 protected final int getGregorianMonth() {
\r
5225 return gregorianMonth;
\r
5229 * Returns the day of year (1-based) on the Gregorian calendar as
\r
5230 * computed by <code>computeGregorianFields()</code>.
\r
5231 * @see #computeGregorianFields
\r
5234 protected final int getGregorianDayOfYear() {
\r
5235 return gregorianDayOfYear;
\r
5239 * Returns the day of month (1-based) on the Gregorian calendar as
\r
5240 * computed by <code>computeGregorianFields()</code>.
\r
5241 * @see #computeGregorianFields
\r
5244 protected final int getGregorianDayOfMonth() {
\r
5245 return gregorianDayOfMonth;
\r
5249 * {@icu} Returns the number of fields defined by this calendar. Valid field
\r
5250 * arguments to <code>set()</code> and <code>get()</code> are
\r
5251 * <code>0..getFieldCount()-1</code>.
\r
5254 public final int getFieldCount() {
\r
5255 return fields.length;
\r
5259 * Set a field to a value. Subclasses should use this method when
\r
5260 * computing fields. It sets the time stamp in the
\r
5261 * <code>stamp[]</code> array to <code>INTERNALLY_SET</code>. If a
\r
5262 * field that may not be set by subclasses is passed in, an
\r
5263 * <code>IllegalArgumentException</code> is thrown. This prevents
\r
5264 * subclasses from modifying fields that are intended to be
\r
5265 * calendar-system invariant.
\r
5268 protected final void internalSet(int field, int value) {
\r
5269 if (((1 << field) & internalSetMask) == 0) {
\r
5270 throw new IllegalStateException("Subclass cannot set " +
\r
5271 fieldName(field));
\r
5273 fields[field] = value;
\r
5274 stamp[field] = INTERNALLY_SET;
\r
5277 private static final int[][] GREGORIAN_MONTH_COUNT = {
\r
5279 { 31, 31, 0, 0 }, // Jan
\r
5280 { 28, 29, 31, 31 }, // Feb
\r
5281 { 31, 31, 59, 60 }, // Mar
\r
5282 { 30, 30, 90, 91 }, // Apr
\r
5283 { 31, 31, 120, 121 }, // May
\r
5284 { 30, 30, 151, 152 }, // Jun
\r
5285 { 31, 31, 181, 182 }, // Jul
\r
5286 { 31, 31, 212, 213 }, // Aug
\r
5287 { 30, 30, 243, 244 }, // Sep
\r
5288 { 31, 31, 273, 274 }, // Oct
\r
5289 { 30, 30, 304, 305 }, // Nov
\r
5290 { 31, 31, 334, 335 } // Dec
\r
5291 // len length of month
\r
5292 // len2 length of month in a leap year
\r
5293 // st days in year before start of month
\r
5294 // st2 days in year before month in leap year
\r
5298 * Determines if the given year is a leap year. Returns true if the
\r
5299 * given year is a leap year.
\r
5300 * @param year the given year.
\r
5301 * @return true if the given year is a leap year; false otherwise.
\r
5304 protected static final boolean isGregorianLeapYear(int year) {
\r
5305 return (year%4 == 0) && ((year%100 != 0) || (year%400 == 0));
\r
5309 * Returns the length of a month of the Gregorian calendar.
\r
5310 * @param y the extended year
\r
5311 * @param m the 0-based month number
\r
5312 * @return the number of days in the given month
\r
5315 protected static final int gregorianMonthLength(int y, int m) {
\r
5316 return GREGORIAN_MONTH_COUNT[m][isGregorianLeapYear(y)?1:0];
\r
5320 * Returns the length of a previous month of the Gregorian calendar.
\r
5321 * @param y the extended year
\r
5322 * @param m the 0-based month number
\r
5323 * @return the number of days in the month previous to the given month
\r
5326 protected static final int gregorianPreviousMonthLength(int y, int m) {
\r
5327 return (m > 0) ? gregorianMonthLength(y, m-1) : 31;
\r
5331 * Divide two long integers, returning the floor of the quotient.
\r
5333 * Unlike the built-in division, this is mathematically well-behaved.
\r
5334 * E.g., <code>-1/4</code> => 0
\r
5335 * but <code>floorDivide(-1,4)</code> => -1.
\r
5336 * @param numerator the numerator
\r
5337 * @param denominator a divisor which must be > 0
\r
5338 * @return the floor of the quotient.
\r
5341 protected static final long floorDivide(long numerator, long denominator) {
\r
5342 // We do this computation in order to handle
\r
5343 // a numerator of Long.MIN_VALUE correctly
\r
5344 return (numerator >= 0) ?
\r
5345 numerator / denominator :
\r
5346 ((numerator + 1) / denominator) - 1;
\r
5350 * Divide two integers, returning the floor of the quotient.
\r
5352 * Unlike the built-in division, this is mathematically well-behaved.
\r
5353 * E.g., <code>-1/4</code> => 0
\r
5354 * but <code>floorDivide(-1,4)</code> => -1.
\r
5355 * @param numerator the numerator
\r
5356 * @param denominator a divisor which must be > 0
\r
5357 * @return the floor of the quotient.
\r
5360 protected static final int floorDivide(int numerator, int denominator) {
\r
5361 // We do this computation in order to handle
\r
5362 // a numerator of Integer.MIN_VALUE correctly
\r
5363 return (numerator >= 0) ?
\r
5364 numerator / denominator :
\r
5365 ((numerator + 1) / denominator) - 1;
\r
5369 * Divide two integers, returning the floor of the quotient, and
\r
5370 * the modulus remainder.
\r
5372 * Unlike the built-in division, this is mathematically well-behaved.
\r
5373 * E.g., <code>-1/4</code> => 0 and <code>-1%4</code> => -1,
\r
5374 * but <code>floorDivide(-1,4)</code> => -1 with <code>remainder[0]</code> => 3.
\r
5375 * @param numerator the numerator
\r
5376 * @param denominator a divisor which must be > 0
\r
5377 * @param remainder an array of at least one element in which the value
\r
5378 * <code>numerator mod denominator</code> is returned. Unlike <code>numerator
\r
5379 * % denominator</code>, this will always be non-negative.
\r
5380 * @return the floor of the quotient.
\r
5383 protected static final int floorDivide(int numerator, int denominator, int[] remainder) {
\r
5384 if (numerator >= 0) {
\r
5385 remainder[0] = numerator % denominator;
\r
5386 return numerator / denominator;
\r
5388 int quotient = ((numerator + 1) / denominator) - 1;
\r
5389 remainder[0] = numerator - (quotient * denominator);
\r
5394 * Divide two integers, returning the floor of the quotient, and
\r
5395 * the modulus remainder.
\r
5397 * Unlike the built-in division, this is mathematically well-behaved.
\r
5398 * E.g., <code>-1/4</code> => 0 and <code>-1%4</code> => -1,
\r
5399 * but <code>floorDivide(-1,4)</code> => -1 with <code>remainder[0]</code> => 3.
\r
5400 * @param numerator the numerator
\r
5401 * @param denominator a divisor which must be > 0
\r
5402 * @param remainder an array of at least one element in which the value
\r
5403 * <code>numerator mod denominator</code> is returned. Unlike <code>numerator
\r
5404 * % denominator</code>, this will always be non-negative.
\r
5405 * @return the floor of the quotient.
\r
5408 protected static final int floorDivide(long numerator, int denominator, int[] remainder) {
\r
5409 if (numerator >= 0) {
\r
5410 remainder[0] = (int)(numerator % denominator);
\r
5411 return (int)(numerator / denominator);
\r
5413 int quotient = (int)(((numerator + 1) / denominator) - 1);
\r
5414 remainder[0] = (int)(numerator - (quotient * denominator));
\r
5418 private static final String[] FIELD_NAME = {
\r
5419 "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH",
\r
5420 "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK",
\r
5421 "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR", "HOUR_OF_DAY",
\r
5422 "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",
\r
5423 "DST_OFFSET", "YEAR_WOY", "DOW_LOCAL", "EXTENDED_YEAR",
\r
5424 "JULIAN_DAY", "MILLISECONDS_IN_DAY",
\r
5428 * Returns a string name for a field, for debugging and exceptions.
\r
5431 protected String fieldName(int field) {
\r
5433 return FIELD_NAME[field];
\r
5434 } catch (ArrayIndexOutOfBoundsException e) {
\r
5435 return "Field " + field;
\r
5440 * Converts time as milliseconds to Julian day.
\r
5441 * @param millis the given milliseconds.
\r
5442 * @return the Julian day number.
\r
5445 protected static final int millisToJulianDay(long millis) {
\r
5446 return (int) (EPOCH_JULIAN_DAY + floorDivide(millis, ONE_DAY));
\r
5450 * Converts Julian day to time as milliseconds.
\r
5451 * @param julian the given Julian day number.
\r
5452 * @return time as milliseconds.
\r
5455 protected static final long julianDayToMillis(int julian) {
\r
5456 return (julian - EPOCH_JULIAN_DAY) * ONE_DAY;
\r
5460 * Returns the day of week, from SUNDAY to SATURDAY, given a Julian day.
\r
5463 protected static final int julianDayToDayOfWeek(int julian) {
\r
5464 // If julian is negative, then julian%7 will be negative, so we adjust
\r
5465 // accordingly. Julian day 0 is Monday.
\r
5466 int dayOfWeek = (julian + MONDAY) % 7;
\r
5467 if (dayOfWeek < SUNDAY) {
\r
5474 * Returns the current milliseconds without recomputing.
\r
5477 protected final long internalGetTimeInMillis() {
\r
5482 * {@icu} Returns the current Calendar type. Note, in 3.0 this function will return
\r
5483 * 'gregorian' in Calendar to emulate legacy behavior
\r
5484 * @return type of calendar (gregorian, etc)
\r
5487 public String getType() {
\r
5488 return "gregorian";
\r
5491 // -------- BEGIN ULocale boilerplate --------
\r
5494 * {@icu} Returns the locale that was used to create this object, or null.
\r
5495 * This may may differ from the locale requested at the time of
\r
5496 * this object's creation. For example, if an object is created
\r
5497 * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
\r
5498 * drawn from <tt>en</tt> (the <i>actual</i> locale), and
\r
5499 * <tt>en_US</tt> may be the most specific locale that exists (the
\r
5500 * <i>valid</i> locale).
\r
5502 * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8
\r
5503 * contains a partial preview implementation. The * <i>actual</i>
\r
5504 * locale is returned correctly, but the <i>valid</i> locale is
\r
5505 * not, in most cases.
\r
5506 * @param type type of information requested, either {@link
\r
5507 * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
\r
5508 * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
\r
5509 * @return the information specified by <i>type</i>, or null if
\r
5510 * this object was not constructed from locale data.
\r
5511 * @see com.ibm.icu.util.ULocale
\r
5512 * @see com.ibm.icu.util.ULocale#VALID_LOCALE
\r
5513 * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
\r
5514 * @draft ICU 2.8 (retain)
\r
5515 * @provisional This API might change or be removed in a future release.
\r
5517 public final ULocale getLocale(ULocale.Type type) {
\r
5518 return type == ULocale.ACTUAL_LOCALE ?
\r
5519 this.actualLocale : this.validLocale;
\r
5523 * Set information about the locales that were used to create this
\r
5524 * object. If the object was not constructed from locale data,
\r
5525 * both arguments should be set to null. Otherwise, neither
\r
5526 * should be null. The actual locale must be at the same level or
\r
5527 * less specific than the valid locale. This method is intended
\r
5528 * for use by factories or other entities that create objects of
\r
5530 * @param valid the most specific locale containing any resource
\r
5532 * @param actual the locale containing data used to construct this
\r
5534 * @see com.ibm.icu.util.ULocale
\r
5535 * @see com.ibm.icu.util.ULocale#VALID_LOCALE
\r
5536 * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
\r
5538 final void setLocale(ULocale valid, ULocale actual) {
\r
5539 // Change the following to an assertion later
\r
5540 if ((valid == null) != (actual == null)) {
\r
5542 throw new IllegalArgumentException();
\r
5545 // Another check we could do is that the actual locale is at
\r
5546 // the same level or less specific than the valid locale.
\r
5547 this.validLocale = valid;
\r
5548 this.actualLocale = actual;
\r
5552 * The most specific locale containing any resource data, or null.
\r
5553 * @see com.ibm.icu.util.ULocale
\r
5555 private ULocale validLocale;
\r
5558 * The locale containing data used to construct this object, or
\r
5560 * @see com.ibm.icu.util.ULocale
\r
5562 private ULocale actualLocale;
\r
5564 // -------- END ULocale boilerplate --------
\r