1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 * Copyright (C) 1996-2016, International Business Machines 6 * Corporation and others. All Rights Reserved. 7 */ 8 9 package android.icu.util; 10 11 import java.io.IOException; 12 import java.io.ObjectInputStream; 13 import java.io.ObjectOutputStream; 14 import java.io.Serializable; 15 import java.text.StringCharacterIterator; 16 import java.util.ArrayList; 17 import java.util.Date; 18 import java.util.Locale; 19 import java.util.MissingResourceException; 20 21 import android.icu.impl.CalendarUtil; 22 import android.icu.impl.ICUCache; 23 import android.icu.impl.ICUData; 24 import android.icu.impl.ICUResourceBundle; 25 import android.icu.impl.SimpleCache; 26 import android.icu.impl.SimpleFormatterImpl; 27 import android.icu.impl.SoftCache; 28 import android.icu.text.DateFormat; 29 import android.icu.text.DateFormatSymbols; 30 import android.icu.text.SimpleDateFormat; 31 import android.icu.util.ULocale.Category; 32 33 /** 34 * <strong>[icu enhancement]</strong> ICU's replacement for {@link java.util.Calendar}. Methods, fields, and other functionality specific to ICU are labeled '<strong>[icu]</strong>'. 35 * 36 * <p><code>Calendar</code> is an abstract base class for converting between 37 * a <code>Date</code> object and a set of integer fields such as 38 * <code>YEAR</code>, <code>MONTH</code>, <code>DAY</code>, <code>HOUR</code>, 39 * and so on. (A <code>Date</code> object represents a specific instant in 40 * time with millisecond precision. See 41 * {@link Date} 42 * for information about the <code>Date</code> class.) 43 * 44 * <p>Subclasses of <code>Calendar</code> interpret a <code>Date</code> 45 * according to the rules of a specific calendar system. ICU4J contains 46 * several subclasses implementing different international calendar systems. 47 * 48 * <p> 49 * Like other locale-sensitive classes, <code>Calendar</code> provides a 50 * class method, <code>getInstance</code>, for getting a generally useful 51 * object of this type. <code>Calendar</code>'s <code>getInstance</code> method 52 * returns a calendar of a type appropriate to the locale, whose 53 * time fields have been initialized with the current date and time: 54 * <blockquote> 55 * <pre>Calendar rightNow = Calendar.getInstance()</pre> 56 * </blockquote> 57 * 58 * <p>When a <code>ULocale</code> is used by <code>getInstance</code>, its 59 * '<code>calendar</code>' tag and value are retrieved if present. If a recognized 60 * value is supplied, a calendar is provided and configured as appropriate. 61 * Currently recognized tags are "buddhist", "chinese", "coptic", "ethiopic", 62 * "gregorian", "hebrew", "islamic", "islamic-civil", "japanese", and "roc". For 63 * example: <blockquote> 64 * <pre>Calendar cal = Calendar.getInstance(new ULocale("en_US@calendar=japanese"));</pre> 65 * </blockquote> will return an instance of JapaneseCalendar (using en_US conventions for 66 * minimum days in first week, start day of week, et cetera). 67 * 68 * <p>A <code>Calendar</code> object can produce all the time field values 69 * needed to implement the date-time formatting for a particular language and 70 * calendar style (for example, Japanese-Gregorian, Japanese-Traditional). 71 * <code>Calendar</code> defines the range of values returned by certain fields, 72 * as well as their meaning. For example, the first month of the year has value 73 * <code>MONTH</code> == <code>JANUARY</code> for all calendars. Other values 74 * are defined by the concrete subclass, such as <code>ERA</code> and 75 * <code>YEAR</code>. See individual field documentation and subclass 76 * documentation for details. 77 * 78 * <p>When a <code>Calendar</code> is <em>lenient</em>, it accepts a wider range 79 * of field values than it produces. For example, a lenient 80 * <code>GregorianCalendar</code> interprets <code>MONTH</code> == 81 * <code>JANUARY</code>, <code>DAY_OF_MONTH</code> == 32 as February 1. A 82 * non-lenient <code>GregorianCalendar</code> throws an exception when given 83 * out-of-range field settings. When calendars recompute field values for 84 * return by <code>get()</code>, they normalize them. For example, a 85 * <code>GregorianCalendar</code> always produces <code>DAY_OF_MONTH</code> 86 * values between 1 and the length of the month. 87 * 88 * <p><code>Calendar</code> defines a locale-specific seven day week using two 89 * parameters: the first day of the week and the minimal days in first week 90 * (from 1 to 7). These numbers are taken from the locale resource data when a 91 * <code>Calendar</code> is constructed. They may also be specified explicitly 92 * through the API. 93 * 94 * <p>When setting or getting the <code>WEEK_OF_MONTH</code> or 95 * <code>WEEK_OF_YEAR</code> fields, <code>Calendar</code> must determine the 96 * first week of the month or year as a reference point. The first week of a 97 * month or year is defined as the earliest seven day period beginning on 98 * <code>getFirstDayOfWeek()</code> and containing at least 99 * <code>getMinimalDaysInFirstWeek()</code> days of that month or year. Weeks 100 * numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow 101 * it. Note that the normalized numbering returned by <code>get()</code> may be 102 * different. For example, a specific <code>Calendar</code> subclass may 103 * designate the week before week 1 of a year as week <em>n</em> of the previous 104 * year. 105 * 106 * <p> When computing a <code>Date</code> from time fields, some special 107 * circumstances may arise: there may be insufficient information to compute the 108 * <code>Date</code> (such as only year and month but no day in the month), 109 * there may be inconsistent information (such as "Tuesday, July 15, 1996" -- 110 * July 15, 1996 is actually a Monday), or the input time might be ambiguous 111 * because of time zone transition. 112 * 113 * <p><strong>Insufficient information.</strong> The calendar will use default 114 * information to specify the missing fields. This may vary by calendar; for 115 * the Gregorian calendar, the default for a field is the same as that of the 116 * start of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc. 117 * 118 * <p><strong>Inconsistent information.</strong> If fields conflict, the calendar 119 * will give preference to fields set more recently. For example, when 120 * determining the day, the calendar will look for one of the following 121 * combinations of fields. The most recent combination, as determined by the 122 * most recently set single field, will be used. 123 * 124 * <blockquote> 125 * <pre> 126 * MONTH + DAY_OF_MONTH 127 * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK 128 * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK 129 * DAY_OF_YEAR 130 * DAY_OF_WEEK + WEEK_OF_YEAR</pre> 131 * </blockquote> 132 * 133 * For the time of day: 134 * 135 * <blockquote> 136 * <pre> 137 * HOUR_OF_DAY 138 * AM_PM + HOUR</pre> 139 * </blockquote> 140 * 141 * <p><strong>Ambiguous Wall Clock Time.</strong> When time offset from UTC has 142 * changed, it produces an ambiguous time slot around the transition. For example, 143 * many US locations observe daylight saving time. On the date switching to daylight 144 * saving time in US, wall clock time jumps from 12:59 AM (standard) to 2:00 AM 145 * (daylight). Therefore, wall clock time from 1:00 AM to 1:59 AM do not exist on 146 * the date. When the input wall time fall into this missing time slot, the ICU 147 * Calendar resolves the time using the UTC offset before the transition by default. 148 * In this example, 1:30 AM is interpreted as 1:30 AM standard time (non-exist), 149 * so the final result will be 2:30 AM daylight time. 150 * 151 * <p>On the date switching back to standard time, wall clock time is moved back one 152 * hour at 2:00 AM. So wall clock time from 1:00 AM to 1:59 AM occur twice. In this 153 * case, the ICU Calendar resolves the time using the UTC offset after the transition 154 * by default. For example, 1:30 AM on the date is resolved as 1:30 AM standard time. 155 * 156 * <p>Ambiguous wall clock time resolution behaviors can be customized by Calendar APIs 157 * {@link #setRepeatedWallTimeOption(int)} and {@link #setSkippedWallTimeOption(int)}. 158 * These methods are available in ICU 49 or later versions. 159 * 160 * <p><strong>Note:</strong> for some non-Gregorian calendars, different 161 * fields may be necessary for complete disambiguation. For example, a full 162 * specification of the historial Arabic astronomical calendar requires year, 163 * month, day-of-month <em>and</em> day-of-week in some cases. 164 * 165 * <p><strong>Note:</strong> There are certain possible ambiguities in 166 * interpretation of certain singular times, which are resolved in the 167 * following ways: 168 * <ol> 169 * <li> 24:00:00 "belongs" to the following day. That is, 170 * 23:59 on Dec 31, 1969 < 24:00 on Jan 1, 1970 < 24:01:00 on Jan 1, 1970 171 * 172 * <li> Although historically not precise, midnight also belongs to "am", 173 * and noon belongs to "pm", so on the same day, 174 * 12:00 am (midnight) < 12:01 am, and 12:00 pm (noon) < 12:01 pm 175 * </ol> 176 * 177 * <p>The date or time format strings are not part of the definition of a 178 * calendar, as those must be modifiable or overridable by the user at 179 * runtime. Use {@link DateFormat} 180 * to format dates. 181 * 182 * <p><strong>Field manipulation methods</strong></p> 183 * 184 * <p><code>Calendar</code> fields can be changed using three methods: 185 * <code>set()</code>, <code>add()</code>, and <code>roll()</code>.</p> 186 * 187 * <p><strong><code>set(f, value)</code></strong> changes field 188 * <code>f</code> to <code>value</code>. In addition, it sets an 189 * internal member variable to indicate that field <code>f</code> has 190 * been changed. Although field <code>f</code> is changed immediately, 191 * the calendar's milliseconds is not recomputed until the next call to 192 * <code>get()</code>, <code>getTime()</code>, or 193 * <code>getTimeInMillis()</code> is made. Thus, multiple calls to 194 * <code>set()</code> do not trigger multiple, unnecessary 195 * computations. As a result of changing a field using 196 * <code>set()</code>, other fields may also change, depending on the 197 * field, the field value, and the calendar system. In addition, 198 * <code>get(f)</code> will not necessarily return <code>value</code> 199 * after the fields have been recomputed. The specifics are determined by 200 * the concrete calendar class.</p> 201 * 202 * <p><em>Example</em>: Consider a <code>GregorianCalendar</code> 203 * originally set to August 31, 1999. Calling <code>set(Calendar.MONTH, 204 * Calendar.SEPTEMBER)</code> sets the calendar to September 31, 205 * 1999. This is a temporary internal representation that resolves to 206 * October 1, 1999 if <code>getTime()</code>is then called. However, a 207 * call to <code>set(Calendar.DAY_OF_MONTH, 30)</code> before the call to 208 * <code>getTime()</code> sets the calendar to September 30, 1999, since 209 * no recomputation occurs after <code>set()</code> itself.</p> 210 * 211 * <p><strong><code>add(f, delta)</code></strong> adds <code>delta</code> 212 * to field <code>f</code>. This is equivalent to calling <code>set(f, 213 * get(f) + delta)</code> with two adjustments:</p> 214 * 215 * <blockquote> 216 * <p><strong>Add rule 1</strong>. The value of field <code>f</code> 217 * after the call minus the value of field <code>f</code> before the 218 * call is <code>delta</code>, modulo any overflow that has occurred in 219 * field <code>f</code>. Overflow occurs when a field value exceeds its 220 * range and, as a result, the next larger field is incremented or 221 * decremented and the field value is adjusted back into its range.</p> 222 * 223 * <p><strong>Add rule 2</strong>. If a smaller field is expected to be 224 * invariant, but it is impossible for it to be equal to its 225 * prior value because of changes in its minimum or maximum after field 226 * <code>f</code> is changed, then its value is adjusted to be as close 227 * as possible to its expected value. A smaller field represents a 228 * smaller unit of time. <code>HOUR</code> is a smaller field than 229 * <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields 230 * that are not expected to be invariant. The calendar system 231 * determines what fields are expected to be invariant.</p> 232 * </blockquote> 233 * 234 * <p>In addition, unlike <code>set()</code>, <code>add()</code> forces 235 * an immediate recomputation of the calendar's milliseconds and all 236 * fields.</p> 237 * 238 * <p><em>Example</em>: Consider a <code>GregorianCalendar</code> 239 * originally set to August 31, 1999. Calling <code>add(Calendar.MONTH, 240 * 13)</code> sets the calendar to September 30, 2000. <strong>Add rule 241 * 1</strong> sets the <code>MONTH</code> field to September, since 242 * adding 13 months to August gives September of the next year. Since 243 * <code>DAY_OF_MONTH</code> cannot be 31 in September in a 244 * <code>GregorianCalendar</code>, <strong>add rule 2</strong> sets the 245 * <code>DAY_OF_MONTH</code> to 30, the closest possible value. Although 246 * it is a smaller field, <code>DAY_OF_WEEK</code> is not adjusted by 247 * rule 2, since it is expected to change when the month changes in a 248 * <code>GregorianCalendar</code>.</p> 249 * 250 * <p><strong><code>roll(f, delta)</code></strong> adds 251 * <code>delta</code> to field <code>f</code> without changing larger 252 * fields. This is equivalent to calling <code>add(f, delta)</code> with 253 * the following adjustment:</p> 254 * 255 * <blockquote> 256 * <p><strong>Roll rule</strong>. Larger fields are unchanged after the 257 * call. A larger field represents a larger unit of 258 * time. <code>DAY_OF_MONTH</code> is a larger field than 259 * <code>HOUR</code>.</p> 260 * </blockquote> 261 * 262 * <p><em>Example</em>: Consider a <code>GregorianCalendar</code> 263 * originally set to August 31, 1999. Calling <code>roll(Calendar.MONTH, 264 * 8)</code> sets the calendar to April 30, <strong>1999</strong>. Add 265 * rule 1 sets the <code>MONTH</code> field to April. Using a 266 * <code>GregorianCalendar</code>, the <code>DAY_OF_MONTH</code> cannot 267 * be 31 in the month April. Add rule 2 sets it to the closest possible 268 * value, 30. Finally, the <strong>roll rule</strong> maintains the 269 * <code>YEAR</code> field value of 1999.</p> 270 * 271 * <p><em>Example</em>: Consider a <code>GregorianCalendar</code> 272 * originally set to Sunday June 6, 1999. Calling 273 * <code>roll(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to 274 * Tuesday June 1, 1999, whereas calling 275 * <code>add(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to 276 * Sunday May 30, 1999. This is because the roll rule imposes an 277 * additional constraint: The <code>MONTH</code> must not change when the 278 * <code>WEEK_OF_MONTH</code> is rolled. Taken together with add rule 1, 279 * the resultant date must be between Tuesday June 1 and Saturday June 280 * 5. According to add rule 2, the <code>DAY_OF_WEEK</code>, an invariant 281 * when changing the <code>WEEK_OF_MONTH</code>, is set to Tuesday, the 282 * closest possible value to Sunday (where Sunday is the first day of the 283 * week).</p> 284 * 285 * <p><strong>Usage model</strong>. To motivate the behavior of 286 * <code>add()</code> and <code>roll()</code>, consider a user interface 287 * component with increment and decrement buttons for the month, day, and 288 * year, and an underlying <code>GregorianCalendar</code>. If the 289 * interface reads January 31, 1999 and the user presses the month 290 * increment button, what should it read? If the underlying 291 * implementation uses <code>set()</code>, it might read March 3, 1999. A 292 * better result would be February 28, 1999. Furthermore, if the user 293 * presses the month increment button again, it should read March 31, 294 * 1999, not March 28, 1999. By saving the original date and using either 295 * <code>add()</code> or <code>roll()</code>, depending on whether larger 296 * fields should be affected, the user interface can behave as most users 297 * will intuitively expect.</p> 298 * 299 * <p><b>Note:</b> You should always use {@link #roll roll} and {@link #add add} rather 300 * than attempting to perform arithmetic operations directly on the fields 301 * of a <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses 302 * to have fields with non-linear behavior, for example missing months 303 * or days during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt> 304 * methods will take this into account, while simple arithmetic manipulations 305 * may give invalid results. 306 * 307 * <p><big><big><b>Calendar Architecture in ICU4J</b></big></big></p> 308 * 309 * <p>Recently the implementation of <code>Calendar</code> has changed 310 * significantly in order to better support subclassing. The original 311 * <code>Calendar</code> class was designed to support subclassing, but 312 * it had only one implemented subclass, <code>GregorianCalendar</code>. 313 * With the implementation of several new calendar subclasses, including 314 * the <code>BuddhistCalendar</code>, <code>ChineseCalendar</code>, 315 * <code>HebrewCalendar</code>, <code>IslamicCalendar</code>, and 316 * <code>JapaneseCalendar</code>, the subclassing API has been reworked 317 * thoroughly. This section details the new subclassing API and other 318 * ways in which <code>android.icu.util.Calendar</code> differs from 319 * <code>java.util.Calendar</code>. 320 * </p> 321 * 322 * <p><big><b>Changes</b></big></p> 323 * 324 * <p>Overview of changes between the classic <code>Calendar</code> 325 * architecture and the new architecture. 326 * 327 * <ul> 328 * 329 * <li>The <code>fields[]</code> array is <code>private</code> now 330 * instead of <code>protected</code>. Subclasses must access it 331 * using the methods {@link #internalSet} and 332 * {@link #internalGet}. <b>Motivation:</b> Subclasses should 333 * not directly access data members.</li> 334 * 335 * <li>The <code>time</code> long word is <code>private</code> now 336 * instead of <code>protected</code>. Subclasses may access it using 337 * the method {@link #internalGetTimeInMillis}, which does not 338 * provoke an update. <b>Motivation:</b> Subclasses should not 339 * directly access data members.</li> 340 * 341 * <li>The scope of responsibility of subclasses has been drastically 342 * reduced. As much functionality as possible is implemented in the 343 * <code>Calendar</code> base class. As a result, it is much easier 344 * to subclass <code>Calendar</code>. <b>Motivation:</b> Subclasses 345 * should not have to reimplement common code. Certain behaviors are 346 * common across calendar systems: The definition and behavior of 347 * week-related fields and time fields, the arithmetic 348 * ({@link #add(int, int) add} and {@link #roll(int, int) roll}) behavior of many 349 * fields, and the field validation system.</li> 350 * 351 * <li>The subclassing API has been completely redesigned.</li> 352 * 353 * <li>The <code>Calendar</code> base class contains some Gregorian 354 * calendar algorithmic support that subclasses can use (specifically 355 * in {@link #handleComputeFields}). Subclasses can use the 356 * methods <code>getGregorianXxx()</code> to obtain precomputed 357 * values. <b>Motivation:</b> This is required by all 358 * <code>Calendar</code> subclasses in order to implement consistent 359 * time zone behavior, and Gregorian-derived systems can use the 360 * already computed data.</li> 361 * 362 * <li>The <code>FIELD_COUNT</code> constant has been removed. Use 363 * {@link #getFieldCount}. In addition, framework API has been 364 * added to allow subclasses to define additional fields. 365 * <b>Motivation: </b>The number of fields is not constant across 366 * calendar systems.</li> 367 * 368 * <li>The range of handled dates has been narrowed from +/- 369 * ~300,000,000 years to +/- ~5,000,000 years. In practical terms 370 * this should not affect clients. However, it does mean that client 371 * code cannot be guaranteed well-behaved results with dates such as 372 * <code>Date(Long.MIN_VALUE)</code> or 373 * <code>Date(Long.MAX_VALUE)</code>. Instead, the 374 * <code>Calendar</code> protected constants should be used. 375 * <b>Motivation:</b> With 376 * the addition of the {@link #JULIAN_DAY} field, Julian day 377 * numbers must be restricted to a 32-bit <code>int</code>. This 378 * restricts the overall supported range. Furthermore, restricting 379 * the supported range simplifies the computations by removing 380 * special case code that was used to accomodate arithmetic overflow 381 * at millis near <code>Long.MIN_VALUE</code> and 382 * <code>Long.MAX_VALUE</code>.</li> 383 * 384 * <li>New fields are implemented: {@link #JULIAN_DAY} defines 385 * single-field specification of the 386 * date. {@link #MILLISECONDS_IN_DAY} defines a single-field 387 * specification of the wall time. {@link #DOW_LOCAL} and 388 * {@link #YEAR_WOY} implement localized day-of-week and 389 * week-of-year behavior.</li> 390 * 391 * <li>Subclasses can access protected millisecond constants 392 * defined in <code>Calendar</code>.</li> 393 * 394 * <li>New API has been added to support calendar-specific subclasses 395 * of <code>DateFormat</code>.</li> 396 * 397 * <li>Several subclasses have been implemented, representing 398 * various international calendar systems.</li> 399 * 400 * </ul> 401 * 402 * <p><big><b>Subclass API</b></big></p> 403 * 404 * <p>The original <code>Calendar</code> API was based on the experience 405 * of implementing a only a single subclass, 406 * <code>GregorianCalendar</code>. As a result, all of the subclassing 407 * kinks had not been worked out. The new subclassing API has been 408 * refined based on several implemented subclasses. This includes methods 409 * that must be overridden and methods for subclasses to call. Subclasses 410 * no longer have direct access to <code>fields</code> and 411 * <code>stamp</code>. Instead, they have new API to access 412 * these. Subclasses are able to allocate the <code>fields</code> array 413 * through a protected framework method; this allows subclasses to 414 * specify additional fields. </p> 415 * 416 * <p>More functionality has been moved into the base class. The base 417 * class now contains much of the computational machinery to support the 418 * Gregorian calendar. This is based on two things: (1) Many calendars 419 * are based on the Gregorian calendar (such as the Buddhist and Japanese 420 * imperial calendars). (2) <em>All</em> calendars require basic 421 * Gregorian support in order to handle timezone computations. </p> 422 * 423 * <p>Common computations have been moved into 424 * <code>Calendar</code>. Subclasses no longer compute the week related 425 * fields and the time related fields. These are commonly handled for all 426 * calendars by the base class. </p> 427 * 428 * <p><b>Subclass computation of time <tt>=></tt> fields</b> 429 * 430 * <p>The {@link #ERA}, {@link #YEAR}, 431 * {@link #EXTENDED_YEAR}, {@link #MONTH}, 432 * {@link #DAY_OF_MONTH}, and {@link #DAY_OF_YEAR} fields are 433 * computed by the subclass, based on the Julian day. All other fields 434 * are computed by <code>Calendar</code>. 435 * 436 * <ul> 437 * 438 * <li>Subclasses should implement {@link #handleComputeFields} 439 * to compute the {@link #ERA}, {@link #YEAR}, 440 * {@link #EXTENDED_YEAR}, {@link #MONTH}, 441 * {@link #DAY_OF_MONTH}, and {@link #DAY_OF_YEAR} fields, 442 * based on the value of the {@link #JULIAN_DAY} field. If there 443 * are calendar-specific fields not defined by <code>Calendar</code>, 444 * they must also be computed. These are the only fields that the 445 * subclass should compute. All other fields are computed by the base 446 * class, so time and week fields behave in a consistent way across 447 * all calendars. The default version of this method in 448 * <code>Calendar</code> implements a proleptic Gregorian 449 * calendar. Within this method, subclasses may call 450 * <code>getGregorianXxx()</code> to obtain the Gregorian calendar 451 * month, day of month, and extended year for the given date.</li> 452 * 453 * </ul> 454 * 455 * <p><b>Subclass computation of fields <tt>=></tt> time</b> 456 * 457 * <p>The interpretation of most field values is handled entirely by 458 * <code>Calendar</code>. <code>Calendar</code> determines which fields 459 * are set, which are not, which are set more recently, and so on. In 460 * addition, <code>Calendar</code> handles the computation of the time 461 * from the time fields and handles the week-related fields. The only 462 * thing the subclass must do is determine the extended year, based on 463 * the year fields, and then, given an extended year and a month, it must 464 * return a Julian day number. 465 * 466 * <ul> 467 * 468 * <li>Subclasses should implement {@link #handleGetExtendedYear} 469 * to return the extended year for this calendar system, based on the 470 * {@link #YEAR}, {@link #EXTENDED_YEAR}, and any fields that 471 * the calendar system uses that are larger than a year, such as 472 * {@link #ERA}.</li> 473 * 474 * <li>Subclasses should implement {@link #handleComputeMonthStart} 475 * to return the Julian day number 476 * associated with a month and extended year. This is the Julian day 477 * number of the day before the first day of the month. The month 478 * number is zero-based. This computation should not depend on any 479 * field values.</li> 480 * 481 * </ul> 482 * 483 * <p><b>Other methods</b> 484 * 485 * <ul> 486 * 487 * <li>Subclasses should implement {@link #handleGetMonthLength} 488 * to return the number of days in a 489 * given month of a given extended year. The month number, as always, 490 * is zero-based.</li> 491 * 492 * <li>Subclasses should implement {@link #handleGetYearLength} 493 * to return the number of days in the given 494 * extended year. This method is used by 495 * <tt>computeWeekFields</tt> to compute the 496 * {@link #WEEK_OF_YEAR} and {@link #YEAR_WOY} fields.</li> 497 * 498 * <li>Subclasses should implement {@link #handleGetLimit} 499 * to return the protected values of a field, depending on the value of 500 * <code>limitType</code>. This method only needs to handle the 501 * fields {@link #ERA}, {@link #YEAR}, {@link #MONTH}, 502 * {@link #WEEK_OF_YEAR}, {@link #WEEK_OF_MONTH}, 503 * {@link #DAY_OF_MONTH}, {@link #DAY_OF_YEAR}, 504 * {@link #DAY_OF_WEEK_IN_MONTH}, {@link #YEAR_WOY}, and 505 * {@link #EXTENDED_YEAR}. Other fields are invariant (with 506 * respect to calendar system) and are handled by the base 507 * class.</li> 508 * 509 * <li>Optionally, subclasses may override {@link #validateField} 510 * to check any subclass-specific fields. If the 511 * field's value is out of range, the method should throw an 512 * <code>IllegalArgumentException</code>. The method may call 513 * <code>super.validateField(field)</code> to handle fields in a 514 * generic way, that is, to compare them to the range 515 * <code>getMinimum(field)</code>..<code>getMaximum(field)</code>.</li> 516 * 517 * <li>Optionally, subclasses may override 518 * {@link #handleCreateFields} to create an <code>int[]</code> 519 * array large enough to hold the calendar's fields. This is only 520 * necessary if the calendar defines additional fields beyond those 521 * defined by <code>Calendar</code>. The length of the result must be 522 * be between the base and maximum field counts.</li> 523 * 524 * <li>Optionally, subclasses may override 525 * {@link #handleGetDateFormat} to create a 526 * <code>DateFormat</code> appropriate to this calendar. This is only 527 * required if a calendar subclass redefines the use of a field (for 528 * example, changes the {@link #ERA} field from a symbolic field 529 * to a numeric one) or defines an additional field.</li> 530 * 531 * <li>Optionally, subclasses may override {@link #roll roll} and 532 * {@link #add add} to handle fields that are discontinuous. For 533 * example, in the Hebrew calendar the month "Adar I" only 534 * occurs in leap years; in other years the calendar jumps from 535 * Shevat (month #4) to Adar (month #6). The {@link 536 * HebrewCalendar#add HebrewCalendar.add} and {@link 537 * HebrewCalendar#roll HebrewCalendar.roll} methods take this into 538 * account, so that adding 1 month to Shevat gives the proper result 539 * (Adar) in a non-leap year. The protected utility method {@link 540 * #pinField pinField} is often useful when implementing these two 541 * methods. </li> 542 * 543 * </ul> 544 * 545 * <p><big><b>Normalized behavior</b></big> 546 * 547 * <p>The behavior of certain fields has been made consistent across all 548 * calendar systems and implemented in <code>Calendar</code>. 549 * 550 * <ul> 551 * 552 * <li>Time is normalized. Even though some calendar systems transition 553 * between days at sunset or at other times, all ICU4J calendars 554 * transition between days at <em>local zone midnight</em>. This 555 * allows ICU4J to centralize the time computations in 556 * <code>Calendar</code> and to maintain basic correpsondences 557 * between calendar systems. Affected fields: {@link #AM_PM}, 558 * {@link #HOUR}, {@link #HOUR_OF_DAY}, {@link #MINUTE}, 559 * {@link #SECOND}, {@link #MILLISECOND}, 560 * {@link #ZONE_OFFSET}, and {@link #DST_OFFSET}.</li> 561 * 562 * <li>DST behavior is normalized. Daylight savings time behavior is 563 * computed the same for all calendar systems, and depends on the 564 * value of several <code>GregorianCalendar</code> fields: the 565 * {@link #YEAR}, {@link #MONTH}, and 566 * {@link #DAY_OF_MONTH}. As a result, <code>Calendar</code> 567 * always computes these fields, even for non-Gregorian calendar 568 * systems. These fields are available to subclasses.</li> 569 * 570 * <li>Weeks are normalized. Although locales define the week 571 * differently, in terms of the day on which it starts, and the 572 * designation of week number one of a month or year, they all use a 573 * common mechanism. Furthermore, the day of the week has a simple 574 * and consistent definition throughout history. For example, 575 * although the Gregorian calendar introduced a discontinuity when 576 * first instituted, the day of week was not disrupted. For this 577 * reason, the fields {@link #DAY_OF_WEEK}, <code>WEEK_OF_YEAR, 578 * WEEK_OF_MONTH</code>, {@link #DAY_OF_WEEK_IN_MONTH}, 579 * {@link #DOW_LOCAL}, {@link #YEAR_WOY} are all computed in 580 * a consistent way in the base class, based on the 581 * {@link #EXTENDED_YEAR}, {@link #DAY_OF_YEAR}, 582 * {@link #MONTH}, and {@link #DAY_OF_MONTH}, which are 583 * computed by the subclass.</li> 584 * 585 * </ul> 586 * 587 * <p><big><b>Supported range</b></big> 588 * 589 * <p>The allowable range of <code>Calendar</code> has been 590 * narrowed. <code>GregorianCalendar</code> used to attempt to support 591 * the range of dates with millisecond values from 592 * <code>Long.MIN_VALUE</code> to <code>Long.MAX_VALUE</code>. This 593 * introduced awkward constructions (hacks) which slowed down 594 * performance. It also introduced non-uniform behavior at the 595 * boundaries. The new <code>Calendar</code> protocol specifies the 596 * maximum range of supportable dates as those having Julian day numbers 597 * of <code>-0x7F000000</code> to <code>+0x7F000000</code>. This 598 * corresponds to years from ~5,800,000 BCE to ~5,800,000 CE. Programmers 599 * should use the protected constants in <code>Calendar</code> to 600 * specify an extremely early or extremely late date.</p> 601 * 602 * <p><big><b>General notes</b></big> 603 * 604 * <ul> 605 * 606 * <li>Calendars implementations are <em>proleptic</em>. For example, 607 * even though the Gregorian calendar was not instituted until the 608 * 16th century, the <code>GregorianCalendar</code> class supports 609 * dates before the historical onset of the calendar by extending the 610 * calendar system backward in time. Similarly, the 611 * <code>HebrewCalendar</code> extends backward before the start of 612 * its epoch into zero and negative years. Subclasses do not throw 613 * exceptions because a date precedes the historical start of a 614 * calendar system. Instead, they implement 615 * {@link #handleGetLimit} to return appropriate limits on 616 * {@link #YEAR}, {@link #ERA}, etc. fields. Then, if the 617 * calendar is set to not be lenient, out-of-range field values will 618 * trigger an exception.</li> 619 * 620 * <li>Calendar system subclasses compute a <em>extended 621 * year</em>. This differs from the {@link #YEAR} field in that 622 * it ranges over all integer values, including zero and negative 623 * values, and it encapsulates the information of the 624 * {@link #YEAR} field and all larger fields. Thus, for the 625 * Gregorian calendar, the {@link #EXTENDED_YEAR} is computed as 626 * <code>ERA==AD ? YEAR : 1-YEAR</code>. Another example is the Mayan 627 * long count, which has years (<code>KUN</code>) and nested cycles 628 * of years (<code>KATUN</code> and <code>BAKTUN</code>). The Mayan 629 * {@link #EXTENDED_YEAR} is computed as <code>TUN + 20 * (KATUN 630 * + 20 * BAKTUN)</code>. The <code>Calendar</code> base class uses 631 * the {@link #EXTENDED_YEAR} field to compute the week-related 632 * fields.</li> 633 * 634 * </ul> 635 * 636 * @see Date 637 * @see GregorianCalendar 638 * @see TimeZone 639 * @see DateFormat 640 * @author Mark Davis, Deborah Goldsmith, Chen-Lieh Huang, Alan Liu, Laura Werner 641 */ 642 public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> { 643 644 // Data flow in Calendar 645 // --------------------- 646 647 // The current time is represented in two ways by Calendar: as UTC 648 // milliseconds from the epoch start (1 January 1970 0:00 UTC), and as local 649 // fields such as MONTH, HOUR, AM_PM, etc. It is possible to compute the 650 // millis from the fields, and vice versa. The data needed to do this 651 // conversion is encapsulated by a TimeZone object owned by the Calendar. 652 // The data provided by the TimeZone object may also be overridden if the 653 // user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class 654 // keeps track of what information was most recently set by the caller, and 655 // uses that to compute any other information as needed. 656 657 // If the user sets the fields using set(), the data flow is as follows. 658 // This is implemented by the Calendar subclass's computeTime() method. 659 // During this process, certain fields may be ignored. The disambiguation 660 // algorithm for resolving which fields to pay attention to is described 661 // above. 662 663 // local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.) 664 // | 665 // | Using Calendar-specific algorithm 666 // V 667 // local standard millis 668 // | 669 // | Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET 670 // V 671 // UTC millis (in time data member) 672 673 // If the user sets the UTC millis using setTime(), the data flow is as 674 // follows. This is implemented by the Calendar subclass's computeFields() 675 // method. 676 677 // UTC millis (in time data member) 678 // | 679 // | Using TimeZone getOffset() 680 // V 681 // local standard millis 682 // | 683 // | Using Calendar-specific algorithm 684 // V 685 // local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.) 686 687 // In general, a round trip from fields, through local and UTC millis, and 688 // back out to fields is made when necessary. This is implemented by the 689 // complete() method. Resolving a partial set of fields into a UTC millis 690 // value allows all remaining fields to be generated from that value. If 691 // the Calendar is lenient, the fields are also renormalized to standard 692 // ranges when they are regenerated. 693 694 /** 695 * Field number for <code>get</code> and <code>set</code> indicating the 696 * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific 697 * value; see subclass documentation. 698 * @see GregorianCalendar#AD 699 * @see GregorianCalendar#BC 700 */ 701 public final static int ERA = 0; 702 703 /** 704 * Field number for <code>get</code> and <code>set</code> indicating the 705 * year. This is a calendar-specific value; see subclass documentation. 706 */ 707 public final static int YEAR = 1; 708 709 /** 710 * Field number for <code>get</code> and <code>set</code> indicating the 711 * month. This is a calendar-specific value. The first month of the year is 712 * <code>JANUARY</code>; the last depends on the number of months in a year. 713 * @see #JANUARY 714 * @see #FEBRUARY 715 * @see #MARCH 716 * @see #APRIL 717 * @see #MAY 718 * @see #JUNE 719 * @see #JULY 720 * @see #AUGUST 721 * @see #SEPTEMBER 722 * @see #OCTOBER 723 * @see #NOVEMBER 724 * @see #DECEMBER 725 * @see #UNDECIMBER 726 */ 727 public final static int MONTH = 2; 728 729 /** 730 * Field number for <code>get</code> and <code>set</code> indicating the 731 * week number within the current year. The first week of the year, as 732 * defined by {@link #getFirstDayOfWeek()} and 733 * {@link #getMinimalDaysInFirstWeek()}, has value 1. Subclasses define 734 * the value of {@link #WEEK_OF_YEAR} for days before the first week of 735 * the year. 736 * @see #getFirstDayOfWeek 737 * @see #getMinimalDaysInFirstWeek 738 */ 739 public final static int WEEK_OF_YEAR = 3; 740 741 /** 742 * Field number for <code>get</code> and <code>set</code> indicating the 743 * week number within the current month. The first week of the month, as 744 * defined by {@link #getFirstDayOfWeek()} and 745 * {@link #getMinimalDaysInFirstWeek()}, has value 1. Subclasses define 746 * the value of {@link #WEEK_OF_MONTH} for days before the first week of 747 * the month. 748 * @see #getFirstDayOfWeek 749 * @see #getMinimalDaysInFirstWeek 750 */ 751 public final static int WEEK_OF_MONTH = 4; 752 753 /** 754 * Field number for <code>get</code> and <code>set</code> indicating the 755 * day of the month. This is a synonym for {@link #DAY_OF_MONTH}. 756 * The first day of the month has value 1. 757 * @see #DAY_OF_MONTH 758 */ 759 public final static int DATE = 5; 760 761 /** 762 * Field number for <code>get</code> and <code>set</code> indicating the 763 * day of the month. This is a synonym for {@link #DATE}. 764 * The first day of the month has value 1. 765 * @see #DATE 766 */ 767 public final static int DAY_OF_MONTH = 5; 768 769 /** 770 * Field number for <code>get</code> and <code>set</code> indicating the day 771 * number within the current year. The first day of the year has value 1. 772 */ 773 public final static int DAY_OF_YEAR = 6; 774 775 /** 776 * Field number for <code>get</code> and <code>set</code> indicating the day 777 * of the week. This field takes values {@link #SUNDAY}, 778 * {@link #MONDAY}, {@link #TUESDAY}, {@link #WEDNESDAY}, 779 * {@link #THURSDAY}, {@link #FRIDAY}, and {@link #SATURDAY}. 780 * @see #SUNDAY 781 * @see #MONDAY 782 * @see #TUESDAY 783 * @see #WEDNESDAY 784 * @see #THURSDAY 785 * @see #FRIDAY 786 * @see #SATURDAY 787 */ 788 public final static int DAY_OF_WEEK = 7; 789 790 /** 791 * Field number for <code>get</code> and <code>set</code> indicating the 792 * ordinal number of the day of the week within the current month. Together 793 * with the {@link #DAY_OF_WEEK} field, this uniquely specifies a day 794 * within a month. Unlike {@link #WEEK_OF_MONTH} and 795 * {@link #WEEK_OF_YEAR}, this field's value does <em>not</em> depend on 796 * {@link #getFirstDayOfWeek()} or 797 * {@link #getMinimalDaysInFirstWeek()}. <code>DAY_OF_MONTH 1</code> 798 * through <code>7</code> always correspond to <code>DAY_OF_WEEK_IN_MONTH 799 * 1</code>; <code>8</code> through <code>15</code> correspond to 800 * <code>DAY_OF_WEEK_IN_MONTH 2</code>, and so on. 801 * <code>DAY_OF_WEEK_IN_MONTH 0</code> indicates the week before 802 * <code>DAY_OF_WEEK_IN_MONTH 1</code>. Negative values count back from the 803 * end of the month, so the last Sunday of a month is specified as 804 * <code>DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1</code>. Because 805 * negative values count backward they will usually be aligned differently 806 * within the month than positive values. For example, if a month has 31 807 * days, <code>DAY_OF_WEEK_IN_MONTH -1</code> will overlap 808 * <code>DAY_OF_WEEK_IN_MONTH 5</code> and the end of <code>4</code>. 809 * @see #DAY_OF_WEEK 810 * @see #WEEK_OF_MONTH 811 */ 812 public final static int DAY_OF_WEEK_IN_MONTH = 8; 813 814 /** 815 * Field number for <code>get</code> and <code>set</code> indicating 816 * whether the <code>HOUR</code> is before or after noon. 817 * E.g., at 10:04:15.250 PM the <code>AM_PM</code> is <code>PM</code>. 818 * @see #AM 819 * @see #PM 820 * @see #HOUR 821 */ 822 public final static int AM_PM = 9; 823 824 /** 825 * Field number for <code>get</code> and <code>set</code> indicating the 826 * hour of the morning or afternoon. <code>HOUR</code> is used for the 12-hour 827 * clock. 828 * E.g., at 10:04:15.250 PM the <code>HOUR</code> is 10. 829 * @see #AM_PM 830 * @see #HOUR_OF_DAY 831 */ 832 public final static int HOUR = 10; 833 834 /** 835 * Field number for <code>get</code> and <code>set</code> indicating the 836 * hour of the day. <code>HOUR_OF_DAY</code> is used for the 24-hour clock. 837 * E.g., at 10:04:15.250 PM the <code>HOUR_OF_DAY</code> is 22. 838 * @see #HOUR 839 */ 840 public final static int HOUR_OF_DAY = 11; 841 842 /** 843 * Field number for <code>get</code> and <code>set</code> indicating the 844 * minute within the hour. 845 * E.g., at 10:04:15.250 PM the <code>MINUTE</code> is 4. 846 */ 847 public final static int MINUTE = 12; 848 849 /** 850 * Field number for <code>get</code> and <code>set</code> indicating the 851 * second within the minute. 852 * E.g., at 10:04:15.250 PM the <code>SECOND</code> is 15. 853 */ 854 public final static int SECOND = 13; 855 856 /** 857 * Field number for <code>get</code> and <code>set</code> indicating the 858 * millisecond within the second. 859 * E.g., at 10:04:15.250 PM the <code>MILLISECOND</code> is 250. 860 */ 861 public final static int MILLISECOND = 14; 862 863 /** 864 * Field number for <code>get</code> and <code>set</code> indicating the 865 * raw offset from GMT in milliseconds. 866 */ 867 public final static int ZONE_OFFSET = 15; 868 869 /** 870 * Field number for <code>get</code> and <code>set</code> indicating the 871 * daylight savings offset in milliseconds. 872 */ 873 public final static int DST_OFFSET = 16; 874 875 /** 876 * <strong>[icu]</strong> Field number for <code>get()</code> and <code>set()</code> 877 * indicating the extended year corresponding to the 878 * {@link #WEEK_OF_YEAR} field. This may be one greater or less 879 * than the value of {@link #EXTENDED_YEAR}. 880 */ 881 public static final int YEAR_WOY = 17; 882 883 /** 884 * <strong>[icu]</strong> Field number for <code>get()</code> and <code>set()</code> 885 * indicating the localized day of week. This will be a value from 1 886 * to 7 inclusive, with 1 being the localized first day of the week. 887 */ 888 public static final int DOW_LOCAL = 18; 889 890 /** 891 * <strong>[icu]</strong> Field number for <code>get()</code> and <code>set()</code> 892 * indicating the extended year. This is a single number designating 893 * the year of this calendar system, encompassing all supra-year 894 * fields. For example, for the Julian calendar system, year numbers 895 * are positive, with an era of BCE or CE. An extended year value for 896 * the Julian calendar system assigns positive values to CE years and 897 * negative values to BCE years, with 1 BCE being year 0. 898 */ 899 public static final int EXTENDED_YEAR = 19; 900 901 /** 902 * <strong>[icu]</strong> Field number for <code>get()</code> and <code>set()</code> 903 * indicating the modified Julian day number. This is different from 904 * the conventional Julian day number in two regards. First, it 905 * demarcates days at local zone midnight, rather than noon GMT. 906 * Second, it is a local number; that is, it depends on the local time 907 * zone. It can be thought of as a single number that encompasses all 908 * the date-related fields. 909 */ 910 public static final int JULIAN_DAY = 20; 911 912 /** 913 * <strong>[icu]</strong> Field number for <code>get()</code> and <code>set()</code> 914 * indicating the milliseconds in the day. This ranges from 0 to 915 * 23:59:59.999 (regardless of DST). This field behaves 916 * <em>exactly</em> like a composite of all time-related fields, not 917 * including the zone fields. As such, it also reflects 918 * discontinuities of those fields on DST transition days. On a day of 919 * DST onset, it will jump forward. On a day of DST cessation, it will 920 * jump backward. This reflects the fact that is must be combined with 921 * the DST_OFFSET field to obtain a unique local time value. 922 */ 923 public static final int MILLISECONDS_IN_DAY = 21; 924 925 /** 926 * <strong>[icu]</strong> Field indicating whether or not the current month is a leap month. 927 * Should have a value of 0 for non-leap months, and 1 for leap months. 928 */ 929 public static final int IS_LEAP_MONTH = 22; 930 931 /** 932 * The number of fields defined by this class. Subclasses may define 933 * addition fields starting with this number. 934 * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. 935 */ 936 @Deprecated 937 protected static final int BASE_FIELD_COUNT = 23; 938 939 /** 940 * The maximum number of fields possible. Subclasses must not define 941 * more total fields than this number. 942 * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. 943 */ 944 @Deprecated 945 protected static final int MAX_FIELD_COUNT = 32; 946 947 /** 948 * Value of the <code>DAY_OF_WEEK</code> field indicating 949 * Sunday. 950 */ 951 public final static int SUNDAY = 1; 952 953 /** 954 * Value of the <code>DAY_OF_WEEK</code> field indicating 955 * Monday. 956 */ 957 public final static int MONDAY = 2; 958 959 /** 960 * Value of the <code>DAY_OF_WEEK</code> field indicating 961 * Tuesday. 962 */ 963 public final static int TUESDAY = 3; 964 965 /** 966 * Value of the <code>DAY_OF_WEEK</code> field indicating 967 * Wednesday. 968 */ 969 public final static int WEDNESDAY = 4; 970 971 /** 972 * Value of the <code>DAY_OF_WEEK</code> field indicating 973 * Thursday. 974 */ 975 public final static int THURSDAY = 5; 976 977 /** 978 * Value of the <code>DAY_OF_WEEK</code> field indicating 979 * Friday. 980 */ 981 public final static int FRIDAY = 6; 982 983 /** 984 * Value of the <code>DAY_OF_WEEK</code> field indicating 985 * Saturday. 986 */ 987 public final static int SATURDAY = 7; 988 989 /** 990 * Value of the <code>MONTH</code> field indicating the 991 * first month of the year. 992 */ 993 public final static int JANUARY = 0; 994 995 /** 996 * Value of the <code>MONTH</code> field indicating the 997 * second month of the year. 998 */ 999 public final static int FEBRUARY = 1; 1000 1001 /** 1002 * Value of the <code>MONTH</code> field indicating the 1003 * third month of the year. 1004 */ 1005 public final static int MARCH = 2; 1006 1007 /** 1008 * Value of the <code>MONTH</code> field indicating the 1009 * fourth month of the year. 1010 */ 1011 public final static int APRIL = 3; 1012 1013 /** 1014 * Value of the <code>MONTH</code> field indicating the 1015 * fifth month of the year. 1016 */ 1017 public final static int MAY = 4; 1018 1019 /** 1020 * Value of the <code>MONTH</code> field indicating the 1021 * sixth month of the year. 1022 */ 1023 public final static int JUNE = 5; 1024 1025 /** 1026 * Value of the <code>MONTH</code> field indicating the 1027 * seventh month of the year. 1028 */ 1029 public final static int JULY = 6; 1030 1031 /** 1032 * Value of the <code>MONTH</code> field indicating the 1033 * eighth month of the year. 1034 */ 1035 public final static int AUGUST = 7; 1036 1037 /** 1038 * Value of the <code>MONTH</code> field indicating the 1039 * ninth month of the year. 1040 */ 1041 public final static int SEPTEMBER = 8; 1042 1043 /** 1044 * Value of the <code>MONTH</code> field indicating the 1045 * tenth month of the year. 1046 */ 1047 public final static int OCTOBER = 9; 1048 1049 /** 1050 * Value of the <code>MONTH</code> field indicating the 1051 * eleventh month of the year. 1052 */ 1053 public final static int NOVEMBER = 10; 1054 1055 /** 1056 * Value of the <code>MONTH</code> field indicating the 1057 * twelfth month of the year. 1058 */ 1059 public final static int DECEMBER = 11; 1060 1061 /** 1062 * Value of the <code>MONTH</code> field indicating the 1063 * thirteenth month of the year. Although {@link GregorianCalendar} 1064 * does not use this value, lunar calendars do. 1065 */ 1066 public final static int UNDECIMBER = 12; 1067 1068 /** 1069 * Value of the <code>AM_PM</code> field indicating the 1070 * period of the day from midnight to just before noon. 1071 */ 1072 public final static int AM = 0; 1073 1074 /** 1075 * Value of the <code>AM_PM</code> field indicating the 1076 * period of the day from noon to just before midnight. 1077 */ 1078 public final static int PM = 1; 1079 1080 /** 1081 * <strong>[icu]</strong> Value returned by getDayOfWeekType(int dayOfWeek) to indicate a 1082 * weekday. 1083 * @see #WEEKEND 1084 * @see #WEEKEND_ONSET 1085 * @see #WEEKEND_CEASE 1086 * @see #getDayOfWeekType 1087 * @deprecated ICU 54 use {@link #getWeekDataForRegion(String)}, {@link #getWeekData()}, {@link #setWeekData(WeekData)} 1088 * @hide original deprecated declaration 1089 */ 1090 @Deprecated 1091 public static final int WEEKDAY = 0; 1092 1093 /** 1094 * <strong>[icu]</strong> Value returned by getDayOfWeekType(int dayOfWeek) to indicate a 1095 * weekend day. 1096 * @see #WEEKDAY 1097 * @see #WEEKEND_ONSET 1098 * @see #WEEKEND_CEASE 1099 * @see #getDayOfWeekType 1100 * @deprecated ICU 54 use {@link #getWeekDataForRegion(String)}, {@link #getWeekData()}, {@link #setWeekData(WeekData)} 1101 * @hide original deprecated declaration 1102 */ 1103 @Deprecated 1104 public static final int WEEKEND = 1; 1105 1106 /** 1107 * <strong>[icu]</strong> Value returned by getDayOfWeekType(int dayOfWeek) to indicate a 1108 * day that starts as a weekday and transitions to the weekend. 1109 * Call getWeekendTransition() to get the point of transition. 1110 * @see #WEEKDAY 1111 * @see #WEEKEND 1112 * @see #WEEKEND_CEASE 1113 * @see #getDayOfWeekType 1114 * @deprecated ICU 54 use {@link #getWeekDataForRegion(String)}, {@link #getWeekData()}, {@link #setWeekData(WeekData)} 1115 * @hide original deprecated declaration 1116 */ 1117 @Deprecated 1118 public static final int WEEKEND_ONSET = 2; 1119 1120 /** 1121 * <strong>[icu]</strong> Value returned by getDayOfWeekType(int dayOfWeek) to indicate a 1122 * day that starts as the weekend and transitions to a weekday. 1123 * Call getWeekendTransition() to get the point of transition. 1124 * @see #WEEKDAY 1125 * @see #WEEKEND 1126 * @see #WEEKEND_ONSET 1127 * @see #getDayOfWeekType 1128 * @deprecated ICU 54 use {@link #getWeekDataForRegion(String)}, {@link #getWeekData()}, {@link #setWeekData(WeekData)} 1129 * @hide original deprecated declaration 1130 */ 1131 @Deprecated 1132 public static final int WEEKEND_CEASE = 3; 1133 1134 /** 1135 * <strong>[icu]</strong>Option used by {@link #setRepeatedWallTimeOption(int)} and 1136 * {@link #setSkippedWallTimeOption(int)} specifying an ambiguous wall time 1137 * to be interpreted as the latest. 1138 * @see #setRepeatedWallTimeOption(int) 1139 * @see #getRepeatedWallTimeOption() 1140 * @see #setSkippedWallTimeOption(int) 1141 * @see #getSkippedWallTimeOption() 1142 */ 1143 public static final int WALLTIME_LAST = 0; 1144 1145 /** 1146 * <strong>[icu]</strong>Option used by {@link #setRepeatedWallTimeOption(int)} and 1147 * {@link #setSkippedWallTimeOption(int)} specifying an ambiguous wall time 1148 * to be interpreted as the earliest. 1149 * @see #setRepeatedWallTimeOption(int) 1150 * @see #getRepeatedWallTimeOption() 1151 * @see #setSkippedWallTimeOption(int) 1152 * @see #getSkippedWallTimeOption() 1153 */ 1154 public static final int WALLTIME_FIRST = 1; 1155 1156 /** 1157 * <strong>[icu]</strong>Option used by {@link #setSkippedWallTimeOption(int)} specifying an 1158 * ambiguous wall time to be interpreted as the next valid wall time. 1159 * @see #setSkippedWallTimeOption(int) 1160 * @see #getSkippedWallTimeOption() 1161 */ 1162 public static final int WALLTIME_NEXT_VALID = 2; 1163 1164 /** 1165 * The number of milliseconds in one second. 1166 */ 1167 protected static final int ONE_SECOND = 1000; 1168 1169 /** 1170 * The number of milliseconds in one minute. 1171 */ 1172 protected static final int ONE_MINUTE = 60*ONE_SECOND; 1173 1174 /** 1175 * The number of milliseconds in one hour. 1176 */ 1177 protected static final int ONE_HOUR = 60*ONE_MINUTE; 1178 1179 /** 1180 * The number of milliseconds in one day. Although ONE_DAY and 1181 * ONE_WEEK can fit into ints, they must be longs in order to prevent 1182 * arithmetic overflow when performing (bug 4173516). 1183 */ 1184 protected static final long ONE_DAY = 24*ONE_HOUR; 1185 1186 /** 1187 * The number of milliseconds in one week. Although ONE_DAY and 1188 * ONE_WEEK can fit into ints, they must be longs in order to prevent 1189 * arithmetic overflow when performing (bug 4173516). 1190 */ 1191 protected static final long ONE_WEEK = 7*ONE_DAY; 1192 1193 /** 1194 * The Julian day of the Gregorian epoch, that is, January 1, 1 on the 1195 * Gregorian calendar. 1196 */ 1197 protected static final int JAN_1_1_JULIAN_DAY = 1721426; 1198 1199 /** 1200 * The Julian day of the epoch, that is, January 1, 1970 on the 1201 * Gregorian calendar. 1202 */ 1203 protected static final int EPOCH_JULIAN_DAY = 2440588; 1204 1205 /** 1206 * The minimum supported Julian day. This value is equivalent to 1207 * {@link #MIN_MILLIS} and {@link #MIN_DATE}. 1208 * @see #JULIAN_DAY 1209 */ 1210 protected static final int MIN_JULIAN = -0x7F000000; 1211 1212 /** 1213 * The minimum supported epoch milliseconds. This value is equivalent 1214 * to {@link #MIN_JULIAN} and {@link #MIN_DATE}. 1215 */ 1216 protected static final long MIN_MILLIS = -184303902528000000L; 1217 1218 // Get around bug in jikes 1.12 for now. Later, use: 1219 //protected static final long MIN_MILLIS = (MIN_JULIAN - EPOCH_JULIAN_DAY) * ONE_DAY; 1220 1221 /** 1222 * The minimum supported <code>Date</code>. This value is equivalent 1223 * to {@link #MIN_JULIAN} and {@link #MIN_MILLIS}. 1224 */ 1225 protected static final Date MIN_DATE = new Date(MIN_MILLIS); 1226 1227 /** 1228 * The maximum supported Julian day. This value is equivalent to 1229 * {@link #MAX_MILLIS} and {@link #MAX_DATE}. 1230 * @see #JULIAN_DAY 1231 */ 1232 protected static final int MAX_JULIAN = +0x7F000000; 1233 1234 /** 1235 * The maximum supported epoch milliseconds. This value is equivalent 1236 * to {@link #MAX_JULIAN} and {@link #MAX_DATE}. 1237 */ 1238 protected static final long MAX_MILLIS = (MAX_JULIAN - EPOCH_JULIAN_DAY) * ONE_DAY; 1239 1240 /** 1241 * The maximum supported <code>Date</code>. This value is equivalent 1242 * to {@link #MAX_JULIAN} and {@link #MAX_MILLIS}. 1243 */ 1244 protected static final Date MAX_DATE = new Date(MAX_MILLIS); 1245 1246 // Internal notes: 1247 // Calendar contains two kinds of time representations: current "time" in 1248 // milliseconds, and a set of time "fields" representing the current time. 1249 // The two representations are usually in sync, but can get out of sync 1250 // as follows. 1251 // 1. Initially, no fields are set, and the time is invalid. 1252 // 2. If the time is set, all fields are computed and in sync. 1253 // 3. If a single field is set, the time is invalid. 1254 // Recomputation of the time and fields happens when the object needs 1255 // to return a result to the user, or use a result for a computation. 1256 1257 /** 1258 * The field values for the currently set time for this calendar. 1259 * This is an array of at least {@link #BASE_FIELD_COUNT} integers. 1260 * @see #handleCreateFields 1261 * @serial 1262 */ 1263 private transient int fields[]; 1264 1265 /** 1266 * Pseudo-time-stamps which specify when each field was set. There 1267 * are two special values, UNSET and INTERNALLY_SET. Values from 1268 * MINIMUM_USER_SET to Integer.MAX_VALUE are legal user set values. 1269 */ 1270 private transient int stamp[]; 1271 1272 /** 1273 * The currently set time for this calendar, expressed in milliseconds after 1274 * January 1, 1970, 0:00:00 GMT. 1275 * @serial 1276 */ 1277 private long time; 1278 1279 /** 1280 * True if then the value of <code>time</code> is valid. 1281 * The time is made invalid by a change to an item of <code>field[]</code>. 1282 * @see #time 1283 * @serial 1284 */ 1285 private transient boolean isTimeSet; 1286 1287 /** 1288 * True if <code>fields[]</code> are in sync with the currently set time. 1289 * If false, then the next attempt to get the value of a field will 1290 * force a recomputation of all fields from the current value of 1291 * <code>time</code>. 1292 * @serial 1293 */ 1294 private transient boolean areFieldsSet; 1295 1296 /** 1297 * True if all fields have been set. This is only false in a few 1298 * situations: In a newly created, partially constructed object. After 1299 * a call to clear(). In an object just read from a stream using 1300 * readObject(). Once computeFields() has been called this is set to 1301 * true and stays true until one of the above situations recurs. 1302 * @serial 1303 */ 1304 private transient boolean areAllFieldsSet; 1305 1306 /** 1307 * True if all fields have been virtually set, but have not yet been 1308 * computed. This occurs only in setTimeInMillis(), or after readObject(). 1309 * A calendar set to this state will compute all fields from the time if it 1310 * becomes necessary, but otherwise will delay such computation. 1311 */ 1312 private transient boolean areFieldsVirtuallySet; 1313 1314 /** 1315 * True if this calendar allows out-of-range field values during computation 1316 * of <code>time</code> from <code>fields[]</code>. 1317 * @see #setLenient 1318 * @serial 1319 */ 1320 private boolean lenient = true; 1321 1322 /** 1323 * The {@link TimeZone} used by this calendar. {@link Calendar} 1324 * uses the time zone data to translate between local and GMT time. 1325 * @serial 1326 */ 1327 private TimeZone zone; 1328 1329 /** 1330 * The first day of the week, with possible values {@link #SUNDAY}, 1331 * {@link #MONDAY}, etc. This is a locale-dependent value. 1332 * @serial 1333 */ 1334 private int firstDayOfWeek; 1335 1336 /** 1337 * The number of days required for the first week in a month or year, 1338 * with possible values from 1 to 7. This is a locale-dependent value. 1339 * @serial 1340 */ 1341 private int minimalDaysInFirstWeek; 1342 1343 /** 1344 * First day of the weekend in this calendar's locale. Must be in 1345 * the range SUNDAY...SATURDAY (1..7). The weekend starts at 1346 * weekendOnsetMillis milliseconds after midnight on that day of 1347 * the week. This value is taken from locale resource data. 1348 */ 1349 private int weekendOnset; 1350 1351 /** 1352 * Milliseconds after midnight at which the weekend starts on the 1353 * day of the week weekendOnset. Times that are greater than or 1354 * equal to weekendOnsetMillis are considered part of the weekend. 1355 * Must be in the range 0..24*60*60*1000-1. This value is taken 1356 * from locale resource data. 1357 */ 1358 private int weekendOnsetMillis; 1359 1360 /** 1361 * Day of the week when the weekend stops in this calendar's 1362 * locale. Must be in the range SUNDAY...SATURDAY (1..7). The 1363 * weekend stops at weekendCeaseMillis milliseconds after midnight 1364 * on that day of the week. This value is taken from locale 1365 * resource data. 1366 */ 1367 private int weekendCease; 1368 1369 /** 1370 * Milliseconds after midnight at which the weekend stops on the 1371 * day of the week weekendCease. Times that are greater than or 1372 * equal to weekendCeaseMillis are considered not to be the 1373 * weekend. Must be in the range 0..24*60*60*1000-1. This value 1374 * is taken from locale resource data. 1375 */ 1376 private int weekendCeaseMillis; 1377 1378 /** 1379 * Option used when the specified wall time occurs multiple times. 1380 */ 1381 private int repeatedWallTime = WALLTIME_LAST; 1382 1383 /** 1384 * Option used when the specified wall time does not exist. 1385 */ 1386 private int skippedWallTime = WALLTIME_LAST; 1387 1388 /** 1389 * Value of the time stamp <code>stamp[]</code> indicating that 1390 * a field has not been set since the last call to <code>clear()</code>. 1391 * @see #INTERNALLY_SET 1392 * @see #MINIMUM_USER_STAMP 1393 */ 1394 protected static final int UNSET = 0; 1395 1396 /** 1397 * Value of the time stamp <code>stamp[]</code> indicating that a field 1398 * has been set via computations from the time or from other fields. 1399 * @see #UNSET 1400 * @see #MINIMUM_USER_STAMP 1401 */ 1402 protected static final int INTERNALLY_SET = 1; 1403 1404 /** 1405 * If the time stamp <code>stamp[]</code> has a value greater than or 1406 * equal to <code>MINIMUM_USER_SET</code> then it has been set by the 1407 * user via a call to <code>set()</code>. 1408 * @see #UNSET 1409 * @see #INTERNALLY_SET 1410 */ 1411 protected static final int MINIMUM_USER_STAMP = 2; 1412 1413 /** 1414 * The next available value for <code>stamp[]</code>, an internal array. 1415 * @serial 1416 */ 1417 private transient int nextStamp = MINIMUM_USER_STAMP; 1418 1419 /* Max value for stamp allowable before recalcution */ 1420 private static int STAMP_MAX = 10000; 1421 1422 // the internal serial version which says which version was written 1423 // - 0 (default) for version up to JDK 1.1.5 1424 // - 1 for version from JDK 1.1.6, which writes a correct 'time' value 1425 // as well as compatible values for other fields. This is a 1426 // transitional format. 1427 // - 2 (not implemented yet) a future version, in which fields[], 1428 // areFieldsSet, and isTimeSet become transient, and isSet[] is 1429 // removed. In JDK 1.1.6 we write a format compatible with version 2. 1430 // static final int currentSerialVersion = 1; 1431 1432 /** 1433 * The version of the serialized data on the stream. Possible values: 1434 * <dl> 1435 * <dt><b>0</b> or not present on stream</dt> 1436 * <dd> 1437 * JDK 1.1.5 or earlier. 1438 * </dd> 1439 * <dt><b>1</b></dt> 1440 * <dd> 1441 * JDK 1.1.6 or later. Writes a correct 'time' value 1442 * as well as compatible values for other fields. This is a 1443 * transitional format. 1444 * </dd> 1445 * </dl> 1446 * When streaming out this class, the most recent format 1447 * and the highest allowable <code>serialVersionOnStream</code> 1448 * is written. 1449 * @serial 1450 */ 1451 // private int serialVersionOnStream = currentSerialVersion; 1452 1453 // Proclaim serialization compatibility with JDK 1.1 1454 // static final long serialVersionUID = -1807547505821590642L; 1455 1456 // haven't been compatible for awhile, no longer try 1457 // jdk1.4.2 serialver 1458 private static final long serialVersionUID = 6222646104888790989L; 1459 1460 /** 1461 * Bitmask for internalSet() defining which fields may legally be set 1462 * by subclasses. Any attempt to set a field not in this bitmask 1463 * results in an exception, because such fields must be set by the base 1464 * class. 1465 */ 1466 private transient int internalSetMask; 1467 1468 /** 1469 * The Gregorian year, as computed by computeGregorianFields() and 1470 * returned by getGregorianYear(). 1471 */ 1472 private transient int gregorianYear; 1473 1474 /** 1475 * The Gregorian month, as computed by computeGregorianFields() and 1476 * returned by getGregorianMonth(). 1477 */ 1478 private transient int gregorianMonth; 1479 1480 /** 1481 * The Gregorian day of the year, as computed by 1482 * computeGregorianFields() and returned by getGregorianDayOfYear(). 1483 */ 1484 private transient int gregorianDayOfYear; 1485 1486 /** 1487 * The Gregorian day of the month, as computed by 1488 * computeGregorianFields() and returned by getGregorianDayOfMonth(). 1489 */ 1490 private transient int gregorianDayOfMonth; 1491 1492 /** 1493 * Constructs a Calendar with the default time zone 1494 * and the default <code>FORMAT</code> locale. 1495 * @see TimeZone#getDefault 1496 * @see Category#FORMAT 1497 */ Calendar()1498 protected Calendar() 1499 { 1500 this(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT)); 1501 } 1502 1503 /** 1504 * Constructs a calendar with the specified time zone and locale. 1505 * @param zone the time zone to use 1506 * @param aLocale the locale for the week data 1507 */ Calendar(TimeZone zone, Locale aLocale)1508 protected Calendar(TimeZone zone, Locale aLocale) 1509 { 1510 this(zone, ULocale.forLocale(aLocale)); 1511 } 1512 1513 /** 1514 * Constructs a calendar with the specified time zone and locale. 1515 * @param zone the time zone to use 1516 * @param locale the ulocale for the week data 1517 */ Calendar(TimeZone zone, ULocale locale)1518 protected Calendar(TimeZone zone, ULocale locale) 1519 { 1520 this.zone = zone; 1521 1522 // week data 1523 setWeekData(getRegionForCalendar(locale)); 1524 1525 // set valid/actual locale 1526 setCalendarLocale(locale); 1527 1528 initInternal(); 1529 } 1530 1531 /* 1532 * Set valid/actual locale to this calendar during initialization. 1533 * 1534 * Valid or actual locale does not make much sense for Calendar 1535 * object. An instance of Calendar is initialized by week data 1536 * determine by region and calendar type (either region or keyword). 1537 * Language is not really used for calendar creation. 1538 */ setCalendarLocale(ULocale locale)1539 private void setCalendarLocale(ULocale locale) { 1540 ULocale calLocale = locale; 1541 1542 if (locale.getVariant().length() != 0 || locale.getKeywords() != null) { 1543 // Construct a ULocale, without variant and keywords (except calendar). 1544 StringBuilder buf = new StringBuilder(); 1545 1546 buf.append(locale.getLanguage()); 1547 1548 String script = locale.getScript(); 1549 if (script.length() > 0) { 1550 buf.append("_").append(script); 1551 } 1552 1553 String region = locale.getCountry(); 1554 if (region.length() > 0) { 1555 buf.append("_").append(region); 1556 } 1557 1558 String calType = locale.getKeywordValue("calendar"); 1559 if (calType != null) { 1560 buf.append("@calendar=").append(calType); 1561 } 1562 1563 calLocale = new ULocale(buf.toString()); 1564 } 1565 1566 setLocale(calLocale, calLocale); 1567 } 1568 recalculateStamp()1569 private void recalculateStamp() { 1570 int index; 1571 int currentValue; 1572 int j, i; 1573 1574 nextStamp = 1; 1575 1576 for (j = 0; j < stamp.length; j++) { 1577 currentValue = STAMP_MAX; 1578 index = -1; 1579 1580 for (i = 0; i < stamp.length; i++) { 1581 if (stamp[i] > nextStamp && stamp[i] < currentValue) { 1582 currentValue = stamp[i]; 1583 index = i; 1584 } 1585 } 1586 1587 if (index >= 0) { 1588 stamp[index] = ++nextStamp; 1589 } else { 1590 break; 1591 } 1592 } 1593 nextStamp++; 1594 } 1595 initInternal()1596 private void initInternal() 1597 { 1598 // Allocate fields through the framework method. Subclasses 1599 // may override this to define additional fields. 1600 fields = handleCreateFields(); 1601 ///CLOVER:OFF 1602 // todo: fix, difficult to test without subclassing 1603 if (fields == null || fields.length < BASE_FIELD_COUNT || 1604 fields.length > MAX_FIELD_COUNT) { 1605 throw new IllegalStateException("Invalid fields[]"); 1606 } 1607 ///CLOVER:ON 1608 stamp = new int[fields.length]; 1609 int mask = (1 << ERA) | 1610 (1 << YEAR) | 1611 (1 << MONTH) | 1612 (1 << DAY_OF_MONTH) | 1613 (1 << DAY_OF_YEAR) | 1614 (1 << EXTENDED_YEAR) | 1615 (1 << IS_LEAP_MONTH); 1616 for (int i=BASE_FIELD_COUNT; i<fields.length; ++i) { 1617 mask |= (1 << i); 1618 } 1619 internalSetMask = mask; 1620 } 1621 1622 /** 1623 * Returns a calendar using the default time zone and locale. 1624 * @return a Calendar. 1625 */ getInstance()1626 public static Calendar getInstance() 1627 { 1628 return getInstanceInternal(null, null); 1629 } 1630 1631 /** 1632 * Returns a calendar using the specified time zone and default locale. 1633 * @param zone the time zone to use 1634 * @return a Calendar. 1635 */ getInstance(TimeZone zone)1636 public static Calendar getInstance(TimeZone zone) 1637 { 1638 return getInstanceInternal(zone, null); 1639 } 1640 1641 /** 1642 * Returns a calendar using the default time zone and specified locale. 1643 * @param aLocale the locale for the week data 1644 * @return a Calendar. 1645 */ getInstance(Locale aLocale)1646 public static Calendar getInstance(Locale aLocale) 1647 { 1648 return getInstanceInternal(null, ULocale.forLocale(aLocale)); 1649 } 1650 1651 /** 1652 * Returns a calendar using the default time zone and specified locale. 1653 * @param locale the ulocale for the week data 1654 * @return a Calendar. 1655 */ getInstance(ULocale locale)1656 public static Calendar getInstance(ULocale locale) 1657 { 1658 return getInstanceInternal(null, locale); 1659 } 1660 1661 /** 1662 * Returns a calendar with the specified time zone and locale. 1663 * @param zone the time zone to use 1664 * @param aLocale the locale for the week data 1665 * @return a Calendar. 1666 */ getInstance(TimeZone zone, Locale aLocale)1667 public static Calendar getInstance(TimeZone zone, Locale aLocale) { 1668 return getInstanceInternal(zone, ULocale.forLocale(aLocale)); 1669 } 1670 1671 /** 1672 * Returns a calendar with the specified time zone and locale. 1673 * @param zone the time zone to use 1674 * @param locale the ulocale for the week data 1675 * @return a Calendar. 1676 */ getInstance(TimeZone zone, ULocale locale)1677 public static Calendar getInstance(TimeZone zone, ULocale locale) { 1678 return getInstanceInternal(zone, locale); 1679 } 1680 1681 /* 1682 * All getInstance implementations call this private method to create a new 1683 * Calendar instance. 1684 */ getInstanceInternal(TimeZone tz, ULocale locale)1685 private static Calendar getInstanceInternal(TimeZone tz, ULocale locale) { 1686 if (locale == null) { 1687 locale = ULocale.getDefault(Category.FORMAT); 1688 } 1689 if (tz == null) { 1690 tz = TimeZone.getDefault(); 1691 } 1692 1693 Calendar cal = createInstance(locale); 1694 cal.setTimeZone(tz); 1695 cal.setTimeInMillis(System.currentTimeMillis()); 1696 return cal; 1697 } 1698 getRegionForCalendar(ULocale loc)1699 private static String getRegionForCalendar(ULocale loc) { 1700 String region = ULocale.getRegionForSupplementalData(loc, true); 1701 if (region.length() == 0) { 1702 region = "001"; 1703 } 1704 return region; 1705 } 1706 1707 private enum CalType { 1708 GREGORIAN("gregorian"), 1709 ISO8601("iso8601"), 1710 1711 BUDDHIST("buddhist"), 1712 CHINESE("chinese"), 1713 COPTIC("coptic"), 1714 DANGI("dangi"), 1715 ETHIOPIC("ethiopic"), 1716 ETHIOPIC_AMETE_ALEM("ethiopic-amete-alem"), 1717 HEBREW("hebrew"), 1718 INDIAN("indian"), 1719 ISLAMIC("islamic"), 1720 ISLAMIC_CIVIL("islamic-civil"), 1721 ISLAMIC_RGSA("islamic-rgsa"), 1722 ISLAMIC_TBLA("islamic-tbla"), 1723 ISLAMIC_UMALQURA("islamic-umalqura"), 1724 JAPANESE("japanese"), 1725 PERSIAN("persian"), 1726 ROC("roc"), 1727 1728 UNKNOWN("unknown"); 1729 1730 String id; 1731 CalType(String id)1732 CalType(String id) { 1733 this.id = id; 1734 } 1735 } 1736 getCalendarTypeForLocale(ULocale l)1737 private static CalType getCalendarTypeForLocale(ULocale l) { 1738 String s = CalendarUtil.getCalendarType(l); 1739 if (s != null) { 1740 s = s.toLowerCase(Locale.ENGLISH); 1741 for (CalType type : CalType.values()) { 1742 if (s.equals(type.id)) { 1743 return type; 1744 } 1745 } 1746 } 1747 return CalType.UNKNOWN; 1748 } 1749 createInstance(ULocale locale)1750 private static Calendar createInstance(ULocale locale) { 1751 Calendar cal = null; 1752 TimeZone zone = TimeZone.getDefault(); 1753 CalType calType = getCalendarTypeForLocale(locale); 1754 if (calType == CalType.UNKNOWN) { 1755 // fallback to Gregorian 1756 calType = CalType.GREGORIAN; 1757 } 1758 1759 switch (calType) { 1760 case GREGORIAN: 1761 cal = new GregorianCalendar(zone, locale); 1762 break; 1763 case ISO8601: 1764 // Only differs week numbering rule from Gregorian 1765 cal = new GregorianCalendar(zone, locale); 1766 cal.setFirstDayOfWeek(MONDAY); 1767 cal.setMinimalDaysInFirstWeek(4); 1768 break; 1769 1770 case BUDDHIST: 1771 cal = new BuddhistCalendar(zone, locale); 1772 break; 1773 case CHINESE: 1774 cal = new ChineseCalendar(zone, locale); 1775 break; 1776 case COPTIC: 1777 cal = new CopticCalendar(zone, locale); 1778 break; 1779 case DANGI: 1780 cal = new DangiCalendar(zone, locale); 1781 break; 1782 case ETHIOPIC: 1783 cal = new EthiopicCalendar(zone, locale); 1784 break; 1785 case ETHIOPIC_AMETE_ALEM: 1786 cal = new EthiopicCalendar(zone, locale); 1787 ((EthiopicCalendar)cal).setAmeteAlemEra(true); 1788 break; 1789 case HEBREW: 1790 cal = new HebrewCalendar(zone, locale); 1791 break; 1792 case INDIAN: 1793 cal = new IndianCalendar(zone, locale); 1794 break; 1795 case ISLAMIC_CIVIL: 1796 case ISLAMIC_UMALQURA : 1797 case ISLAMIC_TBLA: 1798 case ISLAMIC_RGSA: 1799 case ISLAMIC: 1800 cal = new IslamicCalendar(zone, locale); 1801 break; 1802 case JAPANESE: 1803 cal = new JapaneseCalendar(zone, locale); 1804 break; 1805 case PERSIAN: 1806 cal = new PersianCalendar(zone, locale); 1807 break; 1808 case ROC: 1809 cal = new TaiwanCalendar(zone, locale); 1810 break; 1811 1812 default: 1813 // we must not get here, because unknown type is mapped to 1814 // Gregorian at the beginning of this method. 1815 throw new IllegalArgumentException("Unknown calendar type"); 1816 } 1817 1818 return cal; 1819 } 1820 1821 /** 1822 * Returns the list of locales for which Calendars are installed. 1823 * @return the list of locales for which Calendars are installed. 1824 */ getAvailableLocales()1825 public static Locale[] getAvailableLocales() 1826 { 1827 // TODO 1828 return ICUResourceBundle.getAvailableLocales(); 1829 } 1830 1831 /** 1832 * <strong>[icu]</strong> Returns the list of locales for which Calendars are installed. 1833 * @return the list of locales for which Calendars are installed. 1834 * @hide draft / provisional / internal are hidden on Android 1835 */ getAvailableULocales()1836 public static ULocale[] getAvailableULocales() 1837 { 1838 // TODO 1839 return ICUResourceBundle.getAvailableULocales(); 1840 } 1841 1842 /** 1843 * <strong>[icu]</strong> Given a key and a locale, returns an array of string values in a preferred 1844 * order that would make a difference. These are all and only those values where 1845 * the open (creation) of the service with the locale formed from the input locale 1846 * plus input keyword and that value has different behavior than creation with the 1847 * input locale alone. 1848 * @param key one of the keys supported by this service. For now, only 1849 * "calendar" is supported. 1850 * @param locale the locale 1851 * @param commonlyUsed if set to true it will return only commonly used values 1852 * with the given locale in preferred order. Otherwise, 1853 * it will return all the available values for the locale. 1854 * @return an array of string values for the given key and the locale. 1855 */ getKeywordValuesForLocale(String key, ULocale locale, boolean commonlyUsed)1856 public static final String[] getKeywordValuesForLocale(String key, ULocale locale, 1857 boolean commonlyUsed) { 1858 // Resolve region 1859 String prefRegion = ULocale.getRegionForSupplementalData(locale, true); 1860 1861 // Read preferred calendar values from supplementalData calendarPreferences 1862 ArrayList<String> values = new ArrayList<String>(); 1863 1864 UResourceBundle rb = UResourceBundle.getBundleInstance( 1865 ICUData.ICU_BASE_NAME, 1866 "supplementalData", 1867 ICUResourceBundle.ICU_DATA_CLASS_LOADER); 1868 UResourceBundle calPref = rb.get("calendarPreferenceData"); 1869 UResourceBundle order = null; 1870 try { 1871 order = calPref.get(prefRegion); 1872 } catch (MissingResourceException mre) { 1873 // use "001" as fallback 1874 order = calPref.get("001"); 1875 } 1876 1877 String[] caltypes = order.getStringArray(); 1878 if (commonlyUsed) { 1879 // we have all commonly used calendar for the target region 1880 return caltypes; 1881 } 1882 1883 // if not commonlyUsed, add all preferred calendars in the order 1884 for (int i = 0; i < caltypes.length; i++) { 1885 values.add(caltypes[i]); 1886 } 1887 // then, add other available clanedars 1888 for (CalType t : CalType.values()) { 1889 if (!values.contains(t.id)) { 1890 values.add(t.id); 1891 } 1892 } 1893 return values.toArray(new String[values.size()]); 1894 } 1895 1896 /** 1897 * Returns this Calendar's current time. 1898 * @return the current time. 1899 */ getTime()1900 public final Date getTime() { 1901 return new Date( getTimeInMillis() ); 1902 } 1903 1904 /** 1905 * Sets this Calendar's current time with the given Date. 1906 * 1907 * <p>Note: Calling <code>setTime</code> with 1908 * <code>Date(Long.MAX_VALUE)</code> or <code>Date(Long.MIN_VALUE)</code> 1909 * may yield incorrect field values from {@link #get(int)}. 1910 * @param date the given Date. 1911 */ setTime(Date date)1912 public final void setTime(Date date) { 1913 setTimeInMillis( date.getTime() ); 1914 } 1915 1916 /** 1917 * Returns this Calendar's current time as a long. 1918 * @return the current time as UTC milliseconds from the epoch. 1919 */ getTimeInMillis()1920 public long getTimeInMillis() { 1921 if (!isTimeSet) updateTime(); 1922 return time; 1923 } 1924 1925 /** 1926 * Sets this Calendar's current time from the given long value. 1927 * An IllegalIcuArgumentException is thrown when millis is outside the range permitted 1928 * by a Calendar object when in strict mode. 1929 * When in lenient mode the out of range values are pinned to their respective min/max. 1930 * @param millis the new time in UTC milliseconds from the epoch. 1931 */ setTimeInMillis( long millis )1932 public void setTimeInMillis( long millis ) { 1933 if (millis > MAX_MILLIS) { 1934 if(isLenient()) { 1935 millis = MAX_MILLIS; 1936 } else { 1937 throw new IllegalArgumentException("millis value greater than upper bounds for a Calendar : " + millis); 1938 } 1939 } else if (millis < MIN_MILLIS) { 1940 if(isLenient()) { 1941 millis = MIN_MILLIS; 1942 } else { 1943 throw new IllegalArgumentException("millis value less than lower bounds for a Calendar : " + millis); 1944 } 1945 } 1946 time = millis; 1947 areFieldsSet = areAllFieldsSet = false; 1948 isTimeSet = areFieldsVirtuallySet = true; 1949 1950 for (int i=0; i<fields.length; ++i) { 1951 fields[i] = stamp[i] = 0; // UNSET == 0 1952 } 1953 1954 } 1955 1956 /** 1957 * Returns the value for a given time field. 1958 * @param field the given time field. 1959 * @return the value for the given time field. 1960 */ get(int field)1961 public final int get(int field) 1962 { 1963 complete(); 1964 return fields[field]; 1965 } 1966 1967 /** 1968 * Returns the value for a given time field. This is an internal method 1969 * for subclasses that does <em>not</em> trigger any calculations. 1970 * @param field the given time field. 1971 * @return the value for the given time field. 1972 */ internalGet(int field)1973 protected final int internalGet(int field) 1974 { 1975 return fields[field]; 1976 } 1977 1978 /** 1979 * Returns the value for a given time field, or return the given default 1980 * value if the field is not set. This is an internal method for 1981 * subclasses that does <em>not</em> trigger any calculations. 1982 * @param field the given time field. 1983 * @param defaultValue value to return if field is not set 1984 * @return the value for the given time field of defaultValue if the 1985 * field is unset 1986 */ internalGet(int field, int defaultValue)1987 protected final int internalGet(int field, int defaultValue) { 1988 return (stamp[field] > UNSET) ? fields[field] : defaultValue; 1989 } 1990 1991 /** 1992 * Sets the time field with the given value. 1993 * @param field the given time field. 1994 * @param value the value to be set for the given time field. 1995 */ set(int field, int value)1996 public final void set(int field, int value) 1997 { 1998 if (areFieldsVirtuallySet) { 1999 computeFields(); 2000 } 2001 fields[field] = value; 2002 /* Ensure that the fNextStamp value doesn't go pass max value for 32 bit integer */ 2003 if (nextStamp == STAMP_MAX) { 2004 recalculateStamp(); 2005 } 2006 stamp[field] = nextStamp++; 2007 isTimeSet = areFieldsSet = areFieldsVirtuallySet = false; 2008 } 2009 2010 /** 2011 * Sets the values for the fields year, month, and date. 2012 * Previous values of other fields are retained. If this is not desired, 2013 * call {@link #clear()} first. 2014 * @param year the value used to set the YEAR time field. 2015 * @param month the value used to set the MONTH time field. 2016 * Month value is 0-based. e.g., 0 for January. 2017 * @param date the value used to set the DATE time field. 2018 */ set(int year, int month, int date)2019 public final void set(int year, int month, int date) 2020 { 2021 set(YEAR, year); 2022 set(MONTH, month); 2023 set(DATE, date); 2024 } 2025 2026 /** 2027 * Sets the values for the fields year, month, date, hour, and minute. 2028 * Previous values of other fields are retained. If this is not desired, 2029 * call {@link #clear()} first. 2030 * @param year the value used to set the YEAR time field. 2031 * @param month the value used to set the MONTH time field. 2032 * Month value is 0-based. e.g., 0 for January. 2033 * @param date the value used to set the DATE time field. 2034 * @param hour the value used to set the HOUR_OF_DAY time field. 2035 * @param minute the value used to set the MINUTE time field. 2036 */ set(int year, int month, int date, int hour, int minute)2037 public final void set(int year, int month, int date, int hour, int minute) 2038 { 2039 set(YEAR, year); 2040 set(MONTH, month); 2041 set(DATE, date); 2042 set(HOUR_OF_DAY, hour); 2043 set(MINUTE, minute); 2044 } 2045 2046 /** 2047 * Sets the values for the fields year, month, date, hour, minute, and second. 2048 * Previous values of other fields are retained. If this is not desired, 2049 * call {@link #clear} first. 2050 * @param year the value used to set the YEAR time field. 2051 * @param month the value used to set the MONTH time field. 2052 * Month value is 0-based. e.g., 0 for January. 2053 * @param date the value used to set the DATE time field. 2054 * @param hour the value used to set the HOUR_OF_DAY time field. 2055 * @param minute the value used to set the MINUTE time field. 2056 * @param second the value used to set the SECOND time field. 2057 */ set(int year, int month, int date, int hour, int minute, int second)2058 public final void set(int year, int month, int date, int hour, int minute, 2059 int second) 2060 { 2061 set(YEAR, year); 2062 set(MONTH, month); 2063 set(DATE, date); 2064 set(HOUR_OF_DAY, hour); 2065 set(MINUTE, minute); 2066 set(SECOND, second); 2067 } 2068 2069 // ------------------------------------- 2070 // For now the full getRelatedYear implementation is here; 2071 // per #10752 move the non-default implementation to subclasses 2072 // (default implementation will do no year adjustment) 2073 2074 /** 2075 * utility function for getRelatedYear 2076 */ gregoYearFromIslamicStart(int year)2077 private static int gregoYearFromIslamicStart(int year) { 2078 // ad hoc conversion, improve under #10752 2079 // rough est for now, ok for grego 1846-2138, 2080 // otherwise occasionally wrong (for 3% of years) 2081 int cycle, offset, shift = 0; 2082 if (year >= 1397) { 2083 cycle = (year - 1397) / 67; 2084 offset = (year - 1397) % 67; 2085 shift = 2*cycle + ((offset >= 33)? 1: 0); 2086 } else { 2087 cycle = (year - 1396) / 67 - 1; 2088 offset = -(year - 1396) % 67; 2089 shift = 2*cycle + ((offset <= 33)? 1: 0); 2090 } 2091 return year + 579 - shift; 2092 } 2093 2094 /** 2095 * @deprecated This API is ICU internal only. 2096 * @hide original deprecated declaration 2097 * @hide draft / provisional / internal are hidden on Android 2098 */ 2099 @Deprecated getRelatedYear()2100 public final int getRelatedYear() { 2101 int year = get(EXTENDED_YEAR); 2102 CalType type = CalType.GREGORIAN; 2103 String typeString = getType(); 2104 for (CalType testType : CalType.values()) { 2105 if (typeString.equals(testType.id)) { 2106 type = testType; 2107 break; 2108 } 2109 } 2110 switch (type) { 2111 case PERSIAN: 2112 year += 622; break; 2113 case HEBREW: 2114 year -= 3760; break; 2115 case CHINESE: 2116 year -= 2637; break; 2117 case INDIAN: 2118 year += 79; break; 2119 case COPTIC: 2120 year += 284; break; 2121 case ETHIOPIC: 2122 year += 8; break; 2123 case ETHIOPIC_AMETE_ALEM: 2124 year -=5492; break; 2125 case DANGI: 2126 year -= 2333; break; 2127 case ISLAMIC_CIVIL: 2128 case ISLAMIC: 2129 case ISLAMIC_UMALQURA: 2130 case ISLAMIC_TBLA: 2131 case ISLAMIC_RGSA: 2132 year = gregoYearFromIslamicStart(year); break; 2133 // case GREGORIAN: 2134 // case JAPANESE: 2135 // case BUDDHIST: 2136 // case ROC: 2137 // case ISO8601: 2138 default: 2139 // do nothing, EXTENDED_YEAR same as Gregorian 2140 break; 2141 } 2142 return year; 2143 } 2144 2145 // ------------------------------------- 2146 // For now the full setRelatedYear implementation is here; 2147 // per #10752 move the non-default implementation to subclasses 2148 // (default implementation will do no year adjustment) 2149 2150 /** 2151 * utility function for setRelatedYear 2152 */ firstIslamicStartYearFromGrego(int year)2153 private static int firstIslamicStartYearFromGrego(int year) { 2154 // ad hoc conversion, improve under #10752 2155 // rough est for now, ok for grego 1846-2138, 2156 // otherwise occasionally wrong (for 3% of years) 2157 int cycle, offset, shift = 0; 2158 if (year >= 1977) { 2159 cycle = (year - 1977) / 65; 2160 offset = (year - 1977) % 65; 2161 shift = 2*cycle + ((offset >= 32)? 1: 0); 2162 } else { 2163 cycle = (year - 1976) / 65 - 1; 2164 offset = -(year - 1976) % 65; 2165 shift = 2*cycle + ((offset <= 32)? 1: 0); 2166 } 2167 return year - 579 + shift; 2168 } 2169 2170 /** 2171 * @deprecated This API is ICU internal only. 2172 * @hide original deprecated declaration 2173 * @hide draft / provisional / internal are hidden on Android 2174 */ 2175 @Deprecated setRelatedYear(int year)2176 public final void setRelatedYear(int year) { 2177 CalType type = CalType.GREGORIAN; 2178 String typeString = getType(); 2179 for (CalType testType : CalType.values()) { 2180 if (typeString.equals(testType.id)) { 2181 type = testType; 2182 break; 2183 } 2184 } 2185 switch (type) { 2186 case PERSIAN: 2187 year -= 622; break; 2188 case HEBREW: 2189 year += 3760; break; 2190 case CHINESE: 2191 year += 2637; break; 2192 case INDIAN: 2193 year -= 79; break; 2194 case COPTIC: 2195 year -= 284; break; 2196 case ETHIOPIC: 2197 year -= 8; break; 2198 case ETHIOPIC_AMETE_ALEM: 2199 year +=5492; break; 2200 case DANGI: 2201 year += 2333; break; 2202 case ISLAMIC_CIVIL: 2203 case ISLAMIC: 2204 case ISLAMIC_UMALQURA: 2205 case ISLAMIC_TBLA: 2206 case ISLAMIC_RGSA: 2207 year = firstIslamicStartYearFromGrego(year); break; 2208 // case GREGORIAN: 2209 // case JAPANESE: 2210 // case BUDDHIST: 2211 // case ROC: 2212 // case ISO8601: 2213 default: 2214 // do nothing, EXTENDED_YEAR same as Gregorian 2215 break; 2216 } 2217 set(EXTENDED_YEAR, year); 2218 } 2219 2220 /** 2221 * Clears the values of all the time fields. 2222 */ clear()2223 public final void clear() 2224 { 2225 for (int i=0; i<fields.length; ++i) { 2226 fields[i] = stamp[i] = 0; // UNSET == 0 2227 } 2228 isTimeSet = areFieldsSet = areAllFieldsSet = areFieldsVirtuallySet = false; 2229 } 2230 2231 /** 2232 * Clears the value in the given time field. 2233 * @param field the time field to be cleared. 2234 */ clear(int field)2235 public final void clear(int field) 2236 { 2237 if (areFieldsVirtuallySet) { 2238 computeFields(); 2239 } 2240 fields[field] = 0; 2241 stamp[field] = UNSET; 2242 isTimeSet = areFieldsSet = areAllFieldsSet = areFieldsVirtuallySet = false; 2243 } 2244 2245 /** 2246 * Determines if the given time field has a value set. 2247 * @return true if the given time field has a value set; false otherwise. 2248 */ isSet(int field)2249 public final boolean isSet(int field) 2250 { 2251 return areFieldsVirtuallySet || (stamp[field] != UNSET); 2252 } 2253 2254 /** 2255 * Fills in any unset fields in the time field list. 2256 */ complete()2257 protected void complete() 2258 { 2259 if (!isTimeSet) updateTime(); 2260 if (!areFieldsSet) { 2261 computeFields(); // fills in unset fields 2262 areFieldsSet = true; 2263 areAllFieldsSet = true; 2264 } 2265 } 2266 2267 /** 2268 * Compares this calendar to the specified object. 2269 * The result is <code>true</code> if and only if the argument is 2270 * not <code>null</code> and is a <code>Calendar</code> object that 2271 * represents the same calendar as this object. 2272 * @param obj the object to compare with. 2273 * @return <code>true</code> if the objects are the same; 2274 * <code>false</code> otherwise. 2275 */ 2276 @Override equals(Object obj)2277 public boolean equals(Object obj) { 2278 if (obj == null) { 2279 return false; 2280 } 2281 if (this == obj) { 2282 return true; 2283 } 2284 if (this.getClass() != obj.getClass()) { 2285 return false; 2286 } 2287 2288 Calendar that = (Calendar) obj; 2289 2290 return isEquivalentTo(that) && 2291 getTimeInMillis() == that.getTime().getTime(); 2292 } 2293 2294 /** 2295 * <strong>[icu]</strong> Returns true if the given Calendar object is equivalent to this 2296 * one. An equivalent Calendar will behave exactly as this one 2297 * does, but it may be set to a different time. By contrast, for 2298 * the equals() method to return true, the other Calendar must 2299 * be set to the same time. 2300 * 2301 * @param other the Calendar to be compared with this Calendar 2302 */ isEquivalentTo(Calendar other)2303 public boolean isEquivalentTo(Calendar other) { 2304 return this.getClass() == other.getClass() && 2305 isLenient() == other.isLenient() && 2306 getFirstDayOfWeek() == other.getFirstDayOfWeek() && 2307 getMinimalDaysInFirstWeek() == other.getMinimalDaysInFirstWeek() && 2308 getTimeZone().equals(other.getTimeZone()) && 2309 getRepeatedWallTimeOption() == other.getRepeatedWallTimeOption() && 2310 getSkippedWallTimeOption() == other.getSkippedWallTimeOption(); 2311 } 2312 2313 /** 2314 * Returns a hash code for this calendar. 2315 * @return a hash code value for this object. 2316 */ 2317 @Override hashCode()2318 public int hashCode() { 2319 /* Don't include the time because (a) we don't want the hash value to 2320 * move around just because a calendar is set to different times, and 2321 * (b) we don't want to trigger a time computation just to get a hash. 2322 * Note that it is not necessary for unequal objects to always have 2323 * unequal hashes, but equal objects must have equal hashes. */ 2324 return (lenient ? 1 : 0) 2325 | (firstDayOfWeek << 1) 2326 | (minimalDaysInFirstWeek << 4) 2327 | (repeatedWallTime << 7) 2328 | (skippedWallTime << 9) 2329 | (zone.hashCode() << 11); 2330 } 2331 2332 /** 2333 * Returns the difference in milliseconds between the moment this 2334 * calendar is set to and the moment the given calendar or Date object 2335 * is set to. 2336 */ compare(Object that)2337 private long compare(Object that) { 2338 long thatMs; 2339 if (that instanceof Calendar) { 2340 thatMs = ((Calendar)that).getTimeInMillis(); 2341 } else if (that instanceof Date) { 2342 thatMs = ((Date)that).getTime(); 2343 } else { 2344 throw new IllegalArgumentException(that + "is not a Calendar or Date"); 2345 } 2346 return getTimeInMillis() - thatMs; 2347 } 2348 2349 /** 2350 * Compares the time field records. 2351 * Equivalent to comparing result of conversion to UTC. 2352 * @param when the Calendar to be compared with this Calendar. 2353 * @return true if the current time of this Calendar is before 2354 * the time of Calendar when; false otherwise. 2355 */ before(Object when)2356 public boolean before(Object when) { 2357 return compare(when) < 0; 2358 } 2359 2360 /** 2361 * Compares the time field records. 2362 * Equivalent to comparing result of conversion to UTC. 2363 * @param when the Calendar to be compared with this Calendar. 2364 * @return true if the current time of this Calendar is after 2365 * the time of Calendar when; false otherwise. 2366 */ after(Object when)2367 public boolean after(Object when) { 2368 return compare(when) > 0; 2369 } 2370 2371 /** 2372 * Returns the maximum value that this field could have, given the 2373 * current date. For example, with the Gregorian date February 3, 1997 2374 * and the {@link #DAY_OF_MONTH DAY_OF_MONTH} field, the actual maximum 2375 * is 28; for February 3, 1996 it is 29. 2376 * 2377 * <p>The actual maximum computation ignores smaller fields and the 2378 * current value of like-sized fields. For example, the actual maximum 2379 * of the DAY_OF_YEAR or MONTH depends only on the year and supra-year 2380 * fields. The actual maximum of the DAY_OF_MONTH depends, in 2381 * addition, on the MONTH field and any other fields at that 2382 * granularity (such as IS_LEAP_MONTH). The 2383 * DAY_OF_WEEK_IN_MONTH field does not depend on the current 2384 * DAY_OF_WEEK; it returns the maximum for any day of week in the 2385 * current month. Likewise for the WEEK_OF_MONTH and WEEK_OF_YEAR 2386 * fields. 2387 * 2388 * @param field the field whose maximum is desired 2389 * @return the maximum of the given field for the current date of this calendar 2390 * @see #getMaximum 2391 * @see #getLeastMaximum 2392 */ getActualMaximum(int field)2393 public int getActualMaximum(int field) { 2394 int result; 2395 2396 switch (field) { 2397 case DAY_OF_MONTH: 2398 { 2399 Calendar cal = (Calendar) clone(); 2400 cal.setLenient(true); 2401 cal.prepareGetActual(field, false); 2402 result = handleGetMonthLength(cal.get(EXTENDED_YEAR), cal.get(MONTH)); 2403 } 2404 break; 2405 2406 case DAY_OF_YEAR: 2407 { 2408 Calendar cal = (Calendar) clone(); 2409 cal.setLenient(true); 2410 cal.prepareGetActual(field, false); 2411 result = handleGetYearLength(cal.get(EXTENDED_YEAR)); 2412 } 2413 break; 2414 2415 case ERA: 2416 case DAY_OF_WEEK: 2417 case AM_PM: 2418 case HOUR: 2419 case HOUR_OF_DAY: 2420 case MINUTE: 2421 case SECOND: 2422 case MILLISECOND: 2423 case ZONE_OFFSET: 2424 case DST_OFFSET: 2425 case DOW_LOCAL: 2426 case JULIAN_DAY: 2427 case MILLISECONDS_IN_DAY: 2428 // These fields all have fixed minima/maxima 2429 result = getMaximum(field); 2430 break; 2431 2432 default: 2433 // For all other fields, do it the hard way.... 2434 result = getActualHelper(field, getLeastMaximum(field), getMaximum(field)); 2435 break; 2436 } 2437 return result; 2438 } 2439 2440 /** 2441 * Returns the minimum value that this field could have, given the current date. 2442 * For most fields, this is the same as {@link #getMinimum getMinimum} 2443 * and {@link #getGreatestMinimum getGreatestMinimum}. However, some fields, 2444 * especially those related to week number, are more complicated. 2445 * <p> 2446 * For example, assume {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} 2447 * returns 4 and {@link #getFirstDayOfWeek getFirstDayOfWeek} returns SUNDAY. 2448 * If the first day of the month is Sunday, Monday, Tuesday, or Wednesday 2449 * there will be four or more days in the first week, so it will be week number 1, 2450 * and <code>getActualMinimum(WEEK_OF_MONTH)</code> will return 1. However, 2451 * if the first of the month is a Thursday, Friday, or Saturday, there are 2452 * <em>not</em> four days in that week, so it is week number 0, and 2453 * <code>getActualMinimum(WEEK_OF_MONTH)</code> will return 0. 2454 * <p> 2455 * @param field the field whose actual minimum value is desired. 2456 * @return the minimum of the given field for the current date of this calendar 2457 * 2458 * @see #getMinimum 2459 * @see #getGreatestMinimum 2460 */ getActualMinimum(int field)2461 public int getActualMinimum(int field) { 2462 int result; 2463 2464 switch (field) { 2465 case DAY_OF_WEEK: 2466 case AM_PM: 2467 case HOUR: 2468 case HOUR_OF_DAY: 2469 case MINUTE: 2470 case SECOND: 2471 case MILLISECOND: 2472 case ZONE_OFFSET: 2473 case DST_OFFSET: 2474 case DOW_LOCAL: 2475 case JULIAN_DAY: 2476 case MILLISECONDS_IN_DAY: 2477 // These fields all have fixed minima/maxima 2478 result = getMinimum(field); 2479 break; 2480 2481 default: 2482 // For all other fields, do it the hard way.... 2483 result = getActualHelper(field, getGreatestMinimum(field), getMinimum(field)); 2484 break; 2485 } 2486 return result; 2487 } 2488 2489 /** 2490 * Prepare this calendar for computing the actual minimum or maximum. 2491 * This method modifies this calendar's fields; it is called on a 2492 * temporary calendar. 2493 * 2494 * <p>Rationale: The semantics of getActualXxx() is to return the 2495 * maximum or minimum value that the given field can take, taking into 2496 * account other relevant fields. In general these other fields are 2497 * larger fields. For example, when computing the actual maximum 2498 * DAY_OF_MONTH, the current value of DAY_OF_MONTH itself is ignored, 2499 * as is the value of any field smaller. 2500 * 2501 * <p>The time fields all have fixed minima and maxima, so we don't 2502 * need to worry about them. This also lets us set the 2503 * MILLISECONDS_IN_DAY to zero to erase any effects the time fields 2504 * might have when computing date fields. 2505 * 2506 * <p>DAY_OF_WEEK is adjusted specially for the WEEK_OF_MONTH and 2507 * WEEK_OF_YEAR fields to ensure that they are computed correctly. 2508 */ prepareGetActual(int field, boolean isMinimum)2509 protected void prepareGetActual(int field, boolean isMinimum) { 2510 set(MILLISECONDS_IN_DAY, 0); 2511 2512 switch (field) { 2513 case YEAR: 2514 case EXTENDED_YEAR: 2515 set(DAY_OF_YEAR, getGreatestMinimum(DAY_OF_YEAR)); 2516 break; 2517 2518 case YEAR_WOY: 2519 set(WEEK_OF_YEAR, getGreatestMinimum(WEEK_OF_YEAR)); 2520 break; 2521 2522 case MONTH: 2523 set(DAY_OF_MONTH, getGreatestMinimum(DAY_OF_MONTH)); 2524 break; 2525 2526 case DAY_OF_WEEK_IN_MONTH: 2527 // For dowim, the maximum occurs for the DOW of the first of the 2528 // month. 2529 set(DAY_OF_MONTH, 1); 2530 set(DAY_OF_WEEK, get(DAY_OF_WEEK)); // Make this user set 2531 break; 2532 2533 case WEEK_OF_MONTH: 2534 case WEEK_OF_YEAR: 2535 // If we're counting weeks, set the day of the week to either the 2536 // first or last localized DOW. We know the last week of a month 2537 // or year will contain the first day of the week, and that the 2538 // first week will contain the last DOW. 2539 { 2540 int dow = firstDayOfWeek; 2541 if (isMinimum) { 2542 dow = (dow + 6) % 7; // set to last DOW 2543 if (dow < SUNDAY) { 2544 dow += 7; 2545 } 2546 } 2547 set(DAY_OF_WEEK, dow); 2548 } 2549 break; 2550 } 2551 2552 // Do this last to give it the newest time stamp 2553 set(field, getGreatestMinimum(field)); 2554 } 2555 getActualHelper(int field, int startValue, int endValue)2556 private int getActualHelper(int field, int startValue, int endValue) { 2557 2558 if (startValue == endValue) { 2559 // if we know that the maximum value is always the same, just return it 2560 return startValue; 2561 } 2562 2563 final int delta = (endValue > startValue) ? 1 : -1; 2564 2565 // clone the calendar so we don't mess with the real one, and set it to 2566 // accept anything for the field values 2567 Calendar work = (Calendar) clone(); 2568 2569 // need to resolve time here, otherwise, fields set for actual limit 2570 // may cause conflict with fields previously set (but not yet resolved). 2571 work.complete(); 2572 2573 work.setLenient(true); 2574 work.prepareGetActual(field, delta < 0); 2575 2576 // now try each value from the start to the end one by one until 2577 // we get a value that normalizes to another value. The last value that 2578 // normalizes to itself is the actual maximum for the current date 2579 2580 work.set(field, startValue); 2581 // prepareGetActual sets the first day of week in the same week with 2582 // the first day of a month. Unlike WEEK_OF_YEAR, week number for the 2583 // which week contains days from both previous and current month is 2584 // not unique. For example, last several days in the previous month 2585 // is week 5, and the rest of week is week 1. 2586 if (work.get(field) != startValue 2587 && field != WEEK_OF_MONTH && delta > 0) { 2588 return startValue; 2589 } 2590 int result = startValue; 2591 do { 2592 startValue += delta; 2593 work.add(field, delta); 2594 if (work.get(field) != startValue) { 2595 break; 2596 } 2597 result = startValue; 2598 } while (startValue != endValue); 2599 2600 return result; 2601 } 2602 2603 /** 2604 * Rolls (up/down) a single unit of time on the given field. If the 2605 * field is rolled past its maximum allowable value, it will "wrap" back 2606 * to its minimum and continue rolling. For 2607 * example, to roll the current date up by one day, you can call: 2608 * <p> 2609 * <code>roll({@link #DATE}, true)</code> 2610 * <p> 2611 * When rolling on the {@link #YEAR} field, it will roll the year 2612 * value in the range between 1 and the value returned by calling 2613 * {@link #getMaximum getMaximum}({@link #YEAR}). 2614 * <p> 2615 * When rolling on certain fields, the values of other fields may conflict and 2616 * need to be changed. For example, when rolling the <code>MONTH</code> field 2617 * for the Gregorian date 1/31/96 upward, the <code>DAY_OF_MONTH</code> field 2618 * must be adjusted so that the result is 2/29/96 rather than the invalid 2619 * 2/31/96. 2620 * <p> 2621 * Rolling up always means rolling forward in time (unless 2622 * the limit of the field is reached, in which case it may pin or wrap), so for the 2623 * Gregorian calendar, starting with 100 BC and rolling the year up results in 99 BC. 2624 * When eras have a definite beginning and end (as in the Chinese calendar, or as in 2625 * most eras in the Japanese calendar) then rolling the year past either limit of the 2626 * era will cause the year to wrap around. When eras only have a limit at one end, 2627 * then attempting to roll the year past that limit will result in pinning the year 2628 * at that limit. Note that for most calendars in which era 0 years move forward in 2629 * time (such as Buddhist, Hebrew, or Islamic), it is possible for add or roll to 2630 * result in negative years for era 0 (that is the only way to represent years before 2631 * the calendar epoch in such calendars). 2632 * <p> 2633 * <b>Note:</b> Calling <tt>roll(field, true)</tt> N times is <em>not</em> 2634 * necessarily equivalent to calling <tt>roll(field, N)</tt>. For example, 2635 * imagine that you start with the date Gregorian date January 31, 1995. If you call 2636 * <tt>roll(Calendar.MONTH, 2)</tt>, the result will be March 31, 1995. 2637 * But if you call <tt>roll(Calendar.MONTH, true)</tt>, the result will be 2638 * February 28, 1995. Calling it one more time will give March 28, 1995, which 2639 * is usually not the desired result. 2640 * <p> 2641 * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather 2642 * than attempting to perform arithmetic operations directly on the fields 2643 * of a <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses 2644 * to have fields with non-linear behavior, for example missing months 2645 * or days during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt> 2646 * methods will take this into account, while simple arithmetic manipulations 2647 * may give invalid results. 2648 * <p> 2649 * @param field the calendar field to roll. 2650 * 2651 * @param up indicates if the value of the specified time field is to be 2652 * rolled up or rolled down. Use <code>true</code> if rolling up, 2653 * <code>false</code> otherwise. 2654 * 2655 * @exception IllegalArgumentException if the field is invalid or refers 2656 * to a field that cannot be handled by this method. 2657 * @see #roll(int, int) 2658 * @see #add 2659 */ roll(int field, boolean up)2660 public final void roll(int field, boolean up) 2661 { 2662 roll(field, up ? +1 : -1); 2663 } 2664 2665 /** 2666 * Rolls (up/down) a specified amount time on the given field. For 2667 * example, to roll the current date up by three days, you can call 2668 * <code>roll(Calendar.DATE, 3)</code>. If the 2669 * field is rolled past its maximum allowable value, it will "wrap" back 2670 * to its minimum and continue rolling. 2671 * For example, calling <code>roll(Calendar.DATE, 10)</code> 2672 * on a Gregorian calendar set to 4/25/96 will result in the date 4/5/96. 2673 * <p> 2674 * When rolling on certain fields, the values of other fields may conflict and 2675 * need to be changed. For example, when rolling the {@link #MONTH MONTH} field 2676 * for the Gregorian date 1/31/96 by +1, the {@link #DAY_OF_MONTH DAY_OF_MONTH} field 2677 * must be adjusted so that the result is 2/29/96 rather than the invalid 2678 * 2/31/96. 2679 * <p> 2680 * Rolling by a positive value always means rolling forward in time (unless 2681 * the limit of the field is reached, in which case it may pin or wrap), so for the 2682 * Gregorian calendar, starting with 100 BC and rolling the year by + 1 results in 99 BC. 2683 * When eras have a definite beginning and end (as in the Chinese calendar, or as in 2684 * most eras in the Japanese calendar) then rolling the year past either limit of the 2685 * era will cause the year to wrap around. When eras only have a limit at one end, 2686 * then attempting to roll the year past that limit will result in pinning the year 2687 * at that limit. Note that for most calendars in which era 0 years move forward in 2688 * time (such as Buddhist, Hebrew, or Islamic), it is possible for add or roll to 2689 * result in negative years for era 0 (that is the only way to represent years before 2690 * the calendar epoch in such calendars). 2691 * <p> 2692 * <strong>[icu] Note:</strong> the ICU implementation of this method is able to roll 2693 * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET}, 2694 * and {@link #ZONE_OFFSET ZONE_OFFSET}. Subclasses may, of course, add support for 2695 * additional fields in their overrides of <code>roll</code>. 2696 * <p> 2697 * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather 2698 * than attempting to perform arithmetic operations directly on the fields 2699 * of a <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses 2700 * to have fields with non-linear behavior, for example missing months 2701 * or days during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt> 2702 * methods will take this into account, while simple arithmetic manipulations 2703 * may give invalid results. 2704 * <p> 2705 * <b>Subclassing:</b><br> 2706 * This implementation of <code>roll</code> assumes that the behavior of the 2707 * field is continuous between its minimum and maximum, which are found by 2708 * calling {@link #getActualMinimum getActualMinimum} and {@link #getActualMaximum getActualMaximum}. 2709 * For most such fields, simple addition, subtraction, and modulus operations 2710 * are sufficient to perform the roll. For week-related fields, 2711 * the results of {@link #getFirstDayOfWeek getFirstDayOfWeek} and 2712 * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} are also necessary. 2713 * Subclasses can override these two methods if their values differ from the defaults. 2714 * <p> 2715 * Subclasses that have fields for which the assumption of continuity breaks 2716 * down must overide <code>roll</code> to handle those fields specially. 2717 * For example, in the Hebrew calendar the month "Adar I" 2718 * only occurs in leap years; in other years the calendar jumps from 2719 * Shevat (month #4) to Adar (month #6). The 2720 * {@link HebrewCalendar#roll HebrewCalendar.roll} method takes this into account, 2721 * so that rolling the month of Shevat by one gives the proper result (Adar) in a 2722 * non-leap year. 2723 * <p> 2724 * @param field the calendar field to roll. 2725 * @param amount the amount by which the field should be rolled. 2726 * 2727 * @exception IllegalArgumentException if the field is invalid or refers 2728 * to a field that cannot be handled by this method. 2729 * @see #roll(int, boolean) 2730 * @see #add 2731 */ roll(int field, int amount)2732 public void roll(int field, int amount) { 2733 2734 if (amount == 0) { 2735 return; // Nothing to do 2736 } 2737 2738 complete(); 2739 2740 switch (field) { 2741 case DAY_OF_MONTH: 2742 case AM_PM: 2743 case MINUTE: 2744 case SECOND: 2745 case MILLISECOND: 2746 case MILLISECONDS_IN_DAY: 2747 case ERA: 2748 // These are the standard roll instructions. These work for all 2749 // simple cases, that is, cases in which the limits are fixed, such 2750 // as the hour, the day of the month, and the era. 2751 { 2752 int min = getActualMinimum(field); 2753 int max = getActualMaximum(field); 2754 int gap = max - min + 1; 2755 2756 int value = internalGet(field) + amount; 2757 value = (value - min) % gap; 2758 if (value < 0) { 2759 value += gap; 2760 } 2761 value += min; 2762 2763 set(field, value); 2764 return; 2765 } 2766 2767 case HOUR: 2768 case HOUR_OF_DAY: 2769 // Rolling the hour is difficult on the ONSET and CEASE days of 2770 // daylight savings. For example, if the change occurs at 2771 // 2 AM, we have the following progression: 2772 // ONSET: 12 Std -> 1 Std -> 3 Dst -> 4 Dst 2773 // CEASE: 12 Dst -> 1 Dst -> 1 Std -> 2 Std 2774 // To get around this problem we don't use fields; we manipulate 2775 // the time in millis directly. 2776 { 2777 // Assume min == 0 in calculations below 2778 long start = getTimeInMillis(); 2779 int oldHour = internalGet(field); 2780 int max = getMaximum(field); 2781 int newHour = (oldHour + amount) % (max + 1); 2782 if (newHour < 0) { 2783 newHour += max + 1; 2784 } 2785 setTimeInMillis(start + ONE_HOUR * ((long)newHour - oldHour)); 2786 return; 2787 } 2788 2789 case MONTH: 2790 // Rolling the month involves both pinning the final value 2791 // and adjusting the DAY_OF_MONTH if necessary. We only adjust the 2792 // DAY_OF_MONTH if, after updating the MONTH field, it is illegal. 2793 // E.g., <jan31>.roll(MONTH, 1) -> <feb28> or <feb29>. 2794 { 2795 int max = getActualMaximum(MONTH); 2796 int mon = (internalGet(MONTH) + amount) % (max+1); 2797 2798 if (mon < 0) { 2799 mon += (max + 1); 2800 } 2801 set(MONTH, mon); 2802 2803 // Keep the day of month in range. We don't want to spill over 2804 // into the next month; e.g., we don't want jan31 + 1 mo -> feb31 -> 2805 // mar3. 2806 pinField(DAY_OF_MONTH); 2807 return; 2808 } 2809 2810 case YEAR: 2811 case YEAR_WOY: 2812 // * If era==0 and years go backwards in time, change sign of amount. 2813 // * Until we have new API per #9393, we temporarily hardcode knowledge of 2814 // which calendars have era 0 years that go backwards. 2815 { 2816 boolean era0WithYearsThatGoBackwards = false; 2817 int era = get(ERA); 2818 if (era == 0) { 2819 String calType = getType(); 2820 if (calType.equals("gregorian") || calType.equals("roc") || calType.equals("coptic")) { 2821 amount = -amount; 2822 era0WithYearsThatGoBackwards = true; 2823 } 2824 } 2825 int newYear = internalGet(field) + amount; 2826 if (era > 0 || newYear >= 1) { 2827 int maxYear = getActualMaximum(field); 2828 if (maxYear < 32768) { 2829 // this era has real bounds, roll should wrap years 2830 if (newYear < 1) { 2831 newYear = maxYear - ((-newYear) % maxYear); 2832 } else if (newYear > maxYear) { 2833 newYear = ((newYear - 1) % maxYear) + 1; 2834 } 2835 // else era is unbounded, just pin low year instead of wrapping 2836 } else if (newYear < 1) { 2837 newYear = 1; 2838 } 2839 // else we are in era 0 with newYear < 1; 2840 // calendars with years that go backwards must pin the year value at 0, 2841 // other calendars can have years < 0 in era 0 2842 } else if (era0WithYearsThatGoBackwards) { 2843 newYear = 1; 2844 } 2845 set(field, newYear); 2846 pinField(MONTH); 2847 pinField(DAY_OF_MONTH); 2848 return; 2849 } 2850 case EXTENDED_YEAR: 2851 // Rolling the year can involve pinning the DAY_OF_MONTH. 2852 set(field, internalGet(field) + amount); 2853 pinField(MONTH); 2854 pinField(DAY_OF_MONTH); 2855 return; 2856 2857 case WEEK_OF_MONTH: 2858 { 2859 // This is tricky, because during the roll we may have to shift 2860 // to a different day of the week. For example: 2861 2862 // s m t w r f s 2863 // 1 2 3 4 5 2864 // 6 7 8 9 10 11 12 2865 2866 // When rolling from the 6th or 7th back one week, we go to the 2867 // 1st (assuming that the first partial week counts). The same 2868 // thing happens at the end of the month. 2869 2870 // The other tricky thing is that we have to figure out whether 2871 // the first partial week actually counts or not, based on the 2872 // minimal first days in the week. And we have to use the 2873 // correct first day of the week to delineate the week 2874 // boundaries. 2875 2876 // Here's our algorithm. First, we find the real boundaries of 2877 // the month. Then we discard the first partial week if it 2878 // doesn't count in this locale. Then we fill in the ends with 2879 // phantom days, so that the first partial week and the last 2880 // partial week are full weeks. We then have a nice square 2881 // block of weeks. We do the usual rolling within this block, 2882 // as is done elsewhere in this method. If we wind up on one of 2883 // the phantom days that we added, we recognize this and pin to 2884 // the first or the last day of the month. Easy, eh? 2885 2886 // Normalize the DAY_OF_WEEK so that 0 is the first day of the week 2887 // in this locale. We have dow in 0..6. 2888 int dow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek(); 2889 if (dow < 0) dow += 7; 2890 2891 // Find the day of the week (normalized for locale) for the first 2892 // of the month. 2893 int fdm = (dow - internalGet(DAY_OF_MONTH) + 1) % 7; 2894 if (fdm < 0) fdm += 7; 2895 2896 // Get the first day of the first full week of the month, 2897 // including phantom days, if any. Figure out if the first week 2898 // counts or not; if it counts, then fill in phantom days. If 2899 // not, advance to the first real full week (skip the partial week). 2900 int start; 2901 if ((7 - fdm) < getMinimalDaysInFirstWeek()) 2902 start = 8 - fdm; // Skip the first partial week 2903 else 2904 start = 1 - fdm; // This may be zero or negative 2905 2906 // Get the day of the week (normalized for locale) for the last 2907 // day of the month. 2908 int monthLen = getActualMaximum(DAY_OF_MONTH); 2909 int ldm = (monthLen - internalGet(DAY_OF_MONTH) + dow) % 7; 2910 // We know monthLen >= DAY_OF_MONTH so we skip the += 7 step here. 2911 2912 // Get the limit day for the blocked-off rectangular month; that 2913 // is, the day which is one past the last day of the month, 2914 // after the month has already been filled in with phantom days 2915 // to fill out the last week. This day has a normalized DOW of 0. 2916 int limit = monthLen + 7 - ldm; 2917 2918 // Now roll between start and (limit - 1). 2919 int gap = limit - start; 2920 int day_of_month = (internalGet(DAY_OF_MONTH) + amount*7 - 2921 start) % gap; 2922 if (day_of_month < 0) day_of_month += gap; 2923 day_of_month += start; 2924 2925 // Finally, pin to the real start and end of the month. 2926 if (day_of_month < 1) day_of_month = 1; 2927 if (day_of_month > monthLen) day_of_month = monthLen; 2928 2929 // Set the DAY_OF_MONTH. We rely on the fact that this field 2930 // takes precedence over everything else (since all other fields 2931 // are also set at this point). If this fact changes (if the 2932 // disambiguation algorithm changes) then we will have to unset 2933 // the appropriate fields here so that DAY_OF_MONTH is attended 2934 // to. 2935 set(DAY_OF_MONTH, day_of_month); 2936 return; 2937 } 2938 case WEEK_OF_YEAR: 2939 { 2940 // This follows the outline of WEEK_OF_MONTH, except it applies 2941 // to the whole year. Please see the comment for WEEK_OF_MONTH 2942 // for general notes. 2943 2944 // Normalize the DAY_OF_WEEK so that 0 is the first day of the week 2945 // in this locale. We have dow in 0..6. 2946 int dow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek(); 2947 if (dow < 0) dow += 7; 2948 2949 // Find the day of the week (normalized for locale) for the first 2950 // of the year. 2951 int fdy = (dow - internalGet(DAY_OF_YEAR) + 1) % 7; 2952 if (fdy < 0) fdy += 7; 2953 2954 // Get the first day of the first full week of the year, 2955 // including phantom days, if any. Figure out if the first week 2956 // counts or not; if it counts, then fill in phantom days. If 2957 // not, advance to the first real full week (skip the partial week). 2958 int start; 2959 if ((7 - fdy) < getMinimalDaysInFirstWeek()) 2960 start = 8 - fdy; // Skip the first partial week 2961 else 2962 start = 1 - fdy; // This may be zero or negative 2963 2964 // Get the day of the week (normalized for locale) for the last 2965 // day of the year. 2966 int yearLen = getActualMaximum(DAY_OF_YEAR); 2967 int ldy = (yearLen - internalGet(DAY_OF_YEAR) + dow) % 7; 2968 // We know yearLen >= DAY_OF_YEAR so we skip the += 7 step here. 2969 2970 // Get the limit day for the blocked-off rectangular year; that 2971 // is, the day which is one past the last day of the year, 2972 // after the year has already been filled in with phantom days 2973 // to fill out the last week. This day has a normalized DOW of 0. 2974 int limit = yearLen + 7 - ldy; 2975 2976 // Now roll between start and (limit - 1). 2977 int gap = limit - start; 2978 int day_of_year = (internalGet(DAY_OF_YEAR) + amount*7 - 2979 start) % gap; 2980 if (day_of_year < 0) day_of_year += gap; 2981 day_of_year += start; 2982 2983 // Finally, pin to the real start and end of the month. 2984 if (day_of_year < 1) day_of_year = 1; 2985 if (day_of_year > yearLen) day_of_year = yearLen; 2986 2987 // Make sure that the year and day of year are attended to by 2988 // clearing other fields which would normally take precedence. 2989 // If the disambiguation algorithm is changed, this section will 2990 // have to be updated as well. 2991 set(DAY_OF_YEAR, day_of_year); 2992 clear(MONTH); 2993 return; 2994 } 2995 case DAY_OF_YEAR: 2996 { 2997 // Roll the day of year using millis. Compute the millis for 2998 // the start of the year, and get the length of the year. 2999 long delta = amount * ONE_DAY; // Scale up from days to millis 3000 long min2 = time - (internalGet(DAY_OF_YEAR) - 1) * ONE_DAY; 3001 int yearLength = getActualMaximum(DAY_OF_YEAR); 3002 time = (time + delta - min2) % (yearLength*ONE_DAY); 3003 if (time < 0) time += yearLength*ONE_DAY; 3004 setTimeInMillis(time + min2); 3005 return; 3006 } 3007 case DAY_OF_WEEK: 3008 case DOW_LOCAL: 3009 { 3010 // Roll the day of week using millis. Compute the millis for 3011 // the start of the week, using the first day of week setting. 3012 // Restrict the millis to [start, start+7days). 3013 long delta = amount * ONE_DAY; // Scale up from days to millis 3014 // Compute the number of days before the current day in this 3015 // week. This will be a value 0..6. 3016 int leadDays = internalGet(field); 3017 leadDays -= (field == DAY_OF_WEEK) ? getFirstDayOfWeek() : 1; 3018 if (leadDays < 0) leadDays += 7; 3019 long min2 = time - leadDays * ONE_DAY; 3020 time = (time + delta - min2) % ONE_WEEK; 3021 if (time < 0) time += ONE_WEEK; 3022 setTimeInMillis(time + min2); 3023 return; 3024 } 3025 case DAY_OF_WEEK_IN_MONTH: 3026 { 3027 // Roll the day of week in the month using millis. Determine 3028 // the first day of the week in the month, and then the last, 3029 // and then roll within that range. 3030 long delta = amount * ONE_WEEK; // Scale up from weeks to millis 3031 // Find the number of same days of the week before this one 3032 // in this month. 3033 int preWeeks = (internalGet(DAY_OF_MONTH) - 1) / 7; 3034 // Find the number of same days of the week after this one 3035 // in this month. 3036 int postWeeks = (getActualMaximum(DAY_OF_MONTH) - 3037 internalGet(DAY_OF_MONTH)) / 7; 3038 // From these compute the min and gap millis for rolling. 3039 long min2 = time - preWeeks * ONE_WEEK; 3040 long gap2 = ONE_WEEK * (preWeeks + postWeeks + 1); // Must add 1! 3041 // Roll within this range 3042 time = (time + delta - min2) % gap2; 3043 if (time < 0) time += gap2; 3044 setTimeInMillis(time + min2); 3045 return; 3046 } 3047 case JULIAN_DAY: 3048 set(field, internalGet(field) + amount); 3049 return; 3050 default: 3051 // Other fields cannot be rolled by this method 3052 throw new IllegalArgumentException("Calendar.roll(" + fieldName(field) + 3053 ") not supported"); 3054 } 3055 } 3056 3057 /** 3058 * Add a signed amount to a specified field, using this calendar's rules. 3059 * For example, to add three days to the current date, you can call 3060 * <code>add(Calendar.DATE, 3)</code>. 3061 * <p> 3062 * When adding to certain fields, the values of other fields may conflict and 3063 * need to be changed. For example, when adding one to the {@link #MONTH MONTH} field 3064 * for the Gregorian date 1/31/96, the {@link #DAY_OF_MONTH DAY_OF_MONTH} field 3065 * must be adjusted so that the result is 2/29/96 rather than the invalid 3066 * 2/31/96. 3067 * <p> 3068 * Adding a positive value always means moving forward in time, so for the Gregorian 3069 * calendar, starting with 100 BC and adding +1 to year results in 99 BC (even though 3070 * this actually reduces the numeric value of the field itself). 3071 * <p> 3072 * <strong>[icu] Note:</strong> The ICU implementation of this method is able to add to 3073 * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET}, 3074 * and {@link #ZONE_OFFSET ZONE_OFFSET}. Subclasses may, of course, add support for 3075 * additional fields in their overrides of <code>add</code>. 3076 * <p> 3077 * <b>Note:</b> You should always use <tt>roll</tt> and <tt>add</tt> rather 3078 * than attempting to perform arithmetic operations directly on the fields 3079 * of a <tt>Calendar</tt>. It is quite possible for <tt>Calendar</tt> subclasses 3080 * to have fields with non-linear behavior, for example missing months 3081 * or days during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt> 3082 * methods will take this into account, while simple arithmetic manipulations 3083 * may give invalid results. 3084 * <p> 3085 * <b>Subclassing:</b><br> 3086 * This implementation of <code>add</code> assumes that the behavior of the 3087 * field is continuous between its minimum and maximum, which are found by 3088 * calling {@link #getActualMinimum getActualMinimum} and 3089 * {@link #getActualMaximum getActualMaximum}. 3090 * For such fields, simple arithmetic operations are sufficient to 3091 * perform the add. 3092 * <p> 3093 * Subclasses that have fields for which this assumption of continuity breaks 3094 * down must overide <code>add</code> to handle those fields specially. 3095 * For example, in the Hebrew calendar the month "Adar I" 3096 * only occurs in leap years; in other years the calendar jumps from 3097 * Shevat (month #4) to Adar (month #6). The 3098 * {@link HebrewCalendar#add HebrewCalendar.add} method takes this into account, 3099 * so that adding one month 3100 * to a date in Shevat gives the proper result (Adar) in a non-leap year. 3101 * <p> 3102 * @param field the time field. 3103 * @param amount the amount to add to the field. 3104 * 3105 * @exception IllegalArgumentException if the field is invalid or refers 3106 * to a field that cannot be handled by this method. 3107 * @see #roll(int, int) 3108 */ 3109 @SuppressWarnings("fallthrough") add(int field, int amount)3110 public void add(int field, int amount) { 3111 3112 if (amount == 0) { 3113 return; // Do nothing! 3114 } 3115 3116 // We handle most fields in the same way. The algorithm is to add 3117 // a computed amount of millis to the current millis. The only 3118 // wrinkle is with DST (and/or a change to the zone's UTC offset, which 3119 // we'll include with DST) -- for some fields, like the DAY_OF_MONTH, 3120 // we don't want the wall time to shift due to changes in DST. If the 3121 // result of the add operation is to move from DST to Standard, or 3122 // vice versa, we need to adjust by an hour forward or back, 3123 // respectively. For such fields we set keepWallTimeInvariant to true. 3124 3125 // We only adjust the DST for fields larger than an hour. For 3126 // fields smaller than an hour, we cannot adjust for DST without 3127 // causing problems. for instance, if you add one hour to April 5, 3128 // 1998, 1:00 AM, in PST, the time becomes "2:00 AM PDT" (an 3129 // illegal value), but then the adjustment sees the change and 3130 // compensates by subtracting an hour. As a result the time 3131 // doesn't advance at all. 3132 3133 // For some fields larger than a day, such as a MONTH, we pin the 3134 // DAY_OF_MONTH. This allows <March 31>.add(MONTH, 1) to be 3135 // <April 30>, rather than <April 31> => <May 1>. 3136 3137 long delta = amount; // delta in ms 3138 boolean keepWallTimeInvariant = true; 3139 3140 switch (field) { 3141 case ERA: 3142 set(field, get(field) + amount); 3143 pinField(ERA); 3144 return; 3145 3146 case YEAR: 3147 case YEAR_WOY: 3148 // * If era=0 and years go backwards in time, change sign of amount. 3149 // * Until we have new API per #9393, we temporarily hardcode knowledge of 3150 // which calendars have era 0 years that go backwards. 3151 // * Note that for YEAR (but not YEAR_WOY) we could instead handle 3152 // this by applying the amount to the EXTENDED_YEAR field; but since 3153 // we would still need to handle YEAR_WOY as below, might as well 3154 // also handle YEAR the same way. 3155 { 3156 int era = get(ERA); 3157 if (era == 0) { 3158 String calType = getType(); 3159 if (calType.equals("gregorian") || calType.equals("roc") || calType.equals("coptic")) { 3160 amount = -amount; 3161 } 3162 } 3163 } 3164 // Fall through into standard handling 3165 case EXTENDED_YEAR: 3166 case MONTH: 3167 { 3168 boolean oldLenient = isLenient(); 3169 setLenient(true); 3170 set(field, get(field) + amount); 3171 pinField(DAY_OF_MONTH); 3172 if(oldLenient==false) { 3173 complete(); 3174 setLenient(oldLenient); 3175 } 3176 } 3177 return; 3178 3179 case WEEK_OF_YEAR: 3180 case WEEK_OF_MONTH: 3181 case DAY_OF_WEEK_IN_MONTH: 3182 delta *= ONE_WEEK; 3183 break; 3184 3185 case AM_PM: 3186 delta *= 12 * ONE_HOUR; 3187 break; 3188 3189 case DAY_OF_MONTH: 3190 case DAY_OF_YEAR: 3191 case DAY_OF_WEEK: 3192 case DOW_LOCAL: 3193 case JULIAN_DAY: 3194 delta *= ONE_DAY; 3195 break; 3196 3197 case HOUR_OF_DAY: 3198 case HOUR: 3199 delta *= ONE_HOUR; 3200 keepWallTimeInvariant = false; 3201 break; 3202 3203 case MINUTE: 3204 delta *= ONE_MINUTE; 3205 keepWallTimeInvariant = false; 3206 break; 3207 3208 case SECOND: 3209 delta *= ONE_SECOND; 3210 keepWallTimeInvariant = false; 3211 break; 3212 3213 case MILLISECOND: 3214 case MILLISECONDS_IN_DAY: 3215 keepWallTimeInvariant = false; 3216 break; 3217 3218 default: 3219 throw new IllegalArgumentException("Calendar.add(" + fieldName(field) + 3220 ") not supported"); 3221 } 3222 3223 // In order to keep the wall time invariant (for fields where this is 3224 // appropriate), check the combined DST & ZONE offset before and 3225 // after the add() operation. If it changes, then adjust the millis 3226 // to compensate. 3227 int prevOffset = 0; 3228 int prevWallTime = 0; 3229 if (keepWallTimeInvariant) { 3230 prevOffset = get(DST_OFFSET) + get(ZONE_OFFSET); 3231 prevWallTime = get(MILLISECONDS_IN_DAY); 3232 } 3233 3234 setTimeInMillis(getTimeInMillis() + delta); 3235 3236 if (keepWallTimeInvariant) { 3237 int newWallTime = get(MILLISECONDS_IN_DAY); 3238 if (newWallTime != prevWallTime) { 3239 // There is at least one zone transition between the base 3240 // time and the result time. As the result, wall time has 3241 // changed. 3242 long t = internalGetTimeInMillis(); 3243 int newOffset = get(DST_OFFSET) + get(ZONE_OFFSET); 3244 if (newOffset != prevOffset) { 3245 // When the difference of the previous UTC offset and 3246 // the new UTC offset exceeds 1 full day, we do not want 3247 // to roll over/back the date. For now, this only happens 3248 // in Samoa (Pacific/Apia) on Dec 30, 2011. See ticket:9452. 3249 long adjAmount = (prevOffset - newOffset) % ONE_DAY; 3250 if (adjAmount != 0) { 3251 setTimeInMillis(t + adjAmount); 3252 newWallTime = get(MILLISECONDS_IN_DAY); 3253 } 3254 if (newWallTime != prevWallTime) { 3255 // The result wall time or adjusted wall time was shifted because 3256 // the target wall time does not exist on the result date. 3257 switch (skippedWallTime) { 3258 case WALLTIME_FIRST: 3259 if (adjAmount > 0) { 3260 setTimeInMillis(t); 3261 } 3262 break; 3263 case WALLTIME_LAST: 3264 if (adjAmount < 0) { 3265 setTimeInMillis(t); 3266 } 3267 break; 3268 case WALLTIME_NEXT_VALID: 3269 long tmpT = adjAmount > 0 ? internalGetTimeInMillis() : t; 3270 Long immediatePrevTrans = getImmediatePreviousZoneTransition(tmpT); 3271 if (immediatePrevTrans != null) { 3272 setTimeInMillis(immediatePrevTrans); 3273 } else { 3274 throw new RuntimeException("Could not locate a time zone transition before " + tmpT); 3275 } 3276 break; 3277 } 3278 } 3279 } 3280 } 3281 } 3282 } 3283 3284 /** 3285 * Returns the name of this calendar in the language of the given locale. 3286 */ getDisplayName(Locale loc)3287 public String getDisplayName(Locale loc) { 3288 return this.getClass().getName(); 3289 } 3290 3291 /** 3292 * Returns the name of this calendar in the language of the given locale. 3293 */ getDisplayName(ULocale loc)3294 public String getDisplayName(ULocale loc) { 3295 return this.getClass().getName(); 3296 } 3297 3298 /** 3299 * Compares the times (in millis) represented by two 3300 * <code>Calendar</code> objects. 3301 * 3302 * @param that the <code>Calendar</code> to compare to this. 3303 * @return <code>0</code> if the time represented by 3304 * this <code>Calendar</code> is equal to the time represented 3305 * by that <code>Calendar</code>, a value less than 3306 * <code>0</code> if the time represented by this is before 3307 * the time represented by that, and a value greater than 3308 * <code>0</code> if the time represented by this 3309 * is after the time represented by that. 3310 * @throws NullPointerException if that 3311 * <code>Calendar</code> is null. 3312 * @throws IllegalArgumentException if the time of that 3313 * <code>Calendar</code> can't be obtained because of invalid 3314 * calendar values. 3315 */ 3316 @Override compareTo(Calendar that)3317 public int compareTo(Calendar that) { 3318 long v = getTimeInMillis() - that.getTimeInMillis(); 3319 return v < 0 ? -1 : (v > 0 ? 1 : 0); 3320 } 3321 3322 //------------------------------------------------------------------------- 3323 // Interface for creating custon DateFormats for different types of Calendars 3324 //------------------------------------------------------------------------- 3325 3326 /** 3327 * <strong>[icu]</strong> Returns a <code>DateFormat</code> appropriate to this calendar. 3328 * Subclasses wishing to specialize this behavior should override 3329 * {@link #handleGetDateFormat}. 3330 */ getDateTimeFormat(int dateStyle, int timeStyle, Locale loc)3331 public DateFormat getDateTimeFormat(int dateStyle, int timeStyle, Locale loc) { 3332 return formatHelper(this, ULocale.forLocale(loc), dateStyle, timeStyle); 3333 } 3334 3335 /** 3336 * <strong>[icu]</strong> Returns a <code>DateFormat</code> appropriate to this calendar. 3337 * Subclasses wishing to specialize this behavior should override 3338 * {@link #handleGetDateFormat}. 3339 */ getDateTimeFormat(int dateStyle, int timeStyle, ULocale loc)3340 public DateFormat getDateTimeFormat(int dateStyle, int timeStyle, ULocale loc) { 3341 return formatHelper(this, loc, dateStyle, timeStyle); 3342 } 3343 3344 /** 3345 * Creates a <code>DateFormat</code> appropriate to this calendar. 3346 * This is a framework method for subclasses to override. This method 3347 * is responsible for creating the calendar-specific DateFormat and 3348 * DateFormatSymbols objects as needed. 3349 * @param pattern the pattern, specific to the <code>DateFormat</code> 3350 * subclass 3351 * @param locale the locale for which the symbols should be drawn 3352 * @return a <code>DateFormat</code> appropriate to this calendar 3353 */ handleGetDateFormat(String pattern, Locale locale)3354 protected DateFormat handleGetDateFormat(String pattern, Locale locale) { 3355 return handleGetDateFormat(pattern, null, ULocale.forLocale(locale)); 3356 } 3357 3358 /** 3359 * Creates a <code>DateFormat</code> appropriate to this calendar. 3360 * This is a framework method for subclasses to override. This method 3361 * is responsible for creating the calendar-specific DateFormat and 3362 * DateFormatSymbols objects as needed. 3363 * @param pattern the pattern, specific to the <code>DateFormat</code> 3364 * subclass 3365 * @param override The override string. A numbering system override string can take one of the following forms: 3366 * 1). If just a numbering system name is specified, it applies to all numeric fields in the date format pattern. 3367 * 2). To specify an alternate numbering system on a field by field basis, use the field letters from the pattern 3368 * followed by an = sign, followed by the numbering system name. For example, to specify that just the year 3369 * be formatted using Hebrew digits, use the override "y=hebr". Multiple overrides can be specified in a single 3370 * string by separating them with a semi-colon. For example, the override string "m=thai;y=deva" would format using 3371 * Thai digits for the month and Devanagari digits for the year. 3372 * @param locale the locale for which the symbols should be drawn 3373 * @return a <code>DateFormat</code> appropriate to this calendar 3374 */ handleGetDateFormat(String pattern, String override, Locale locale)3375 protected DateFormat handleGetDateFormat(String pattern, String override, Locale locale) { 3376 return handleGetDateFormat(pattern, override, ULocale.forLocale(locale)); 3377 } 3378 3379 /** 3380 * Creates a <code>DateFormat</code> appropriate to this calendar. 3381 * This is a framework method for subclasses to override. This method 3382 * is responsible for creating the calendar-specific DateFormat and 3383 * DateFormatSymbols objects as needed. 3384 * @param pattern the pattern, specific to the <code>DateFormat</code> 3385 * subclass 3386 * @param locale the locale for which the symbols should be drawn 3387 * @return a <code>DateFormat</code> appropriate to this calendar 3388 */ handleGetDateFormat(String pattern, ULocale locale)3389 protected DateFormat handleGetDateFormat(String pattern, ULocale locale) { 3390 return handleGetDateFormat(pattern, null, locale); 3391 } 3392 3393 /** 3394 * Creates a <code>DateFormat</code> appropriate to this calendar. 3395 * This is a framework method for subclasses to override. This method 3396 * is responsible for creating the calendar-specific DateFormat and 3397 * DateFormatSymbols objects as needed. 3398 * @param pattern the pattern, specific to the <code>DateFormat</code> 3399 * subclass 3400 * @param locale the locale for which the symbols should be drawn 3401 * @return a <code>DateFormat</code> appropriate to this calendar 3402 * @hide draft / provisional / internal are hidden on Android 3403 */ handleGetDateFormat(String pattern, String override, ULocale locale)3404 protected DateFormat handleGetDateFormat(String pattern, String override, ULocale locale) { 3405 FormatConfiguration fmtConfig = new FormatConfiguration(); 3406 fmtConfig.pattern = pattern; 3407 fmtConfig.override = override; 3408 fmtConfig.formatData = new DateFormatSymbols(this, locale); 3409 fmtConfig.loc = locale; 3410 fmtConfig.cal = this; 3411 3412 return SimpleDateFormat.getInstance(fmtConfig); 3413 } 3414 3415 // date format pattern cache 3416 private static final ICUCache<String, PatternData> PATTERN_CACHE = 3417 new SimpleCache<String, PatternData>(); 3418 // final fallback patterns 3419 private static final String[] DEFAULT_PATTERNS = { 3420 "HH:mm:ss z", 3421 "HH:mm:ss z", 3422 "HH:mm:ss", 3423 "HH:mm", 3424 "EEEE, yyyy MMMM dd", 3425 "yyyy MMMM d", 3426 "yyyy MMM d", 3427 "yy/MM/dd", 3428 "{1} {0}", 3429 "{1} {0}", 3430 "{1} {0}", 3431 "{1} {0}", 3432 "{1} {0}" 3433 }; 3434 formatHelper(Calendar cal, ULocale loc, int dateStyle, int timeStyle)3435 static private DateFormat formatHelper(Calendar cal, ULocale loc, int dateStyle, 3436 int timeStyle) { 3437 if (timeStyle < DateFormat.NONE || timeStyle > DateFormat.SHORT) { 3438 throw new IllegalArgumentException("Illegal time style " + timeStyle); 3439 } 3440 if (dateStyle < DateFormat.NONE || dateStyle > DateFormat.SHORT) { 3441 throw new IllegalArgumentException("Illegal date style " + dateStyle); 3442 } 3443 3444 PatternData patternData = PatternData.make(cal, loc); 3445 String override = null; 3446 3447 // Resolve a pattern for the date/time style 3448 String pattern = null; 3449 if ((timeStyle >= 0) && (dateStyle >= 0)) { 3450 pattern = SimpleFormatterImpl.formatRawPattern( 3451 patternData.getDateTimePattern(dateStyle), 2, 2, 3452 patternData.patterns[timeStyle], 3453 patternData.patterns[dateStyle + 4]); 3454 // Might need to merge the overrides from the date and time into a single 3455 // override string TODO: Right now we are forcing the date's override into the 3456 // time style. 3457 if ( patternData.overrides != null ) { 3458 String dateOverride = patternData.overrides[dateStyle + 4]; 3459 String timeOverride = patternData.overrides[timeStyle]; 3460 override = mergeOverrideStrings( 3461 patternData.patterns[dateStyle+4], 3462 patternData.patterns[timeStyle], 3463 dateOverride, timeOverride); 3464 } 3465 } else if (timeStyle >= 0) { 3466 pattern = patternData.patterns[timeStyle]; 3467 if ( patternData.overrides != null ) { 3468 override = patternData.overrides[timeStyle]; 3469 } 3470 } else if (dateStyle >= 0) { 3471 pattern = patternData.patterns[dateStyle + 4]; 3472 if ( patternData.overrides != null ) { 3473 override = patternData.overrides[dateStyle + 4]; 3474 } 3475 } else { 3476 throw new IllegalArgumentException("No date or time style specified"); 3477 } 3478 DateFormat result = cal.handleGetDateFormat(pattern, override, loc); 3479 result.setCalendar(cal); 3480 return result; 3481 } 3482 3483 // Android patch (http://b/28832222) start. 3484 // Expose method to get format string for java.time. 3485 /** 3486 * Get the date time format string for the specified values. 3487 * This is a copy of {@link #formatHelper(Calendar, ULocale, int, int)} with the following 3488 * changes: 3489 * <ul> 3490 * <li>Made public, but hidden</li> 3491 * <li>take calendar type string instead of Calendar</li> 3492 * <li>Ignore overrides</li> 3493 * <li>Return format string instead of DateFormat.</li> 3494 * </ul> 3495 * This is not meant as public API. 3496 * @hide draft / provisional / internal are hidden on Android 3497 */ 3498 // TODO: Check if calType can be passed via keyword on loc parameter instead. getDateTimeFormatString(ULocale loc, String calType, int dateStyle, int timeStyle)3499 public static String getDateTimeFormatString(ULocale loc, String calType, int dateStyle, 3500 int timeStyle) { 3501 if (timeStyle < DateFormat.NONE || timeStyle > DateFormat.SHORT) { 3502 throw new IllegalArgumentException("Illegal time style " + timeStyle); 3503 } 3504 if (dateStyle < DateFormat.NONE || dateStyle > DateFormat.SHORT) { 3505 throw new IllegalArgumentException("Illegal date style " + dateStyle); 3506 } 3507 3508 PatternData patternData = PatternData.make(loc, calType); 3509 3510 // Resolve a pattern for the date/time style 3511 String pattern = null; 3512 if ((timeStyle >= 0) && (dateStyle >= 0)) { 3513 pattern = SimpleFormatterImpl.formatRawPattern( 3514 patternData.getDateTimePattern(dateStyle), 2, 2, 3515 patternData.patterns[timeStyle], 3516 patternData.patterns[dateStyle + 4]); 3517 } else if (timeStyle >= 0) { 3518 pattern = patternData.patterns[timeStyle]; 3519 } else if (dateStyle >= 0) { 3520 pattern = patternData.patterns[dateStyle + 4]; 3521 } else { 3522 throw new IllegalArgumentException("No date or time style specified"); 3523 } 3524 return pattern; 3525 } 3526 // Android patch (http://b/28832222) end. 3527 3528 static class PatternData { 3529 // TODO make this even more object oriented 3530 private String[] patterns; 3531 private String[] overrides; PatternData(String[] patterns, String[] overrides)3532 public PatternData(String[] patterns, String[] overrides) { 3533 this.patterns = patterns; 3534 this.overrides = overrides; 3535 } getDateTimePattern(int dateStyle)3536 private String getDateTimePattern(int dateStyle) { 3537 int glueIndex = 8; 3538 if (patterns.length >= 13) { 3539 glueIndex += (dateStyle + 1); 3540 } 3541 final String dateTimePattern = patterns[glueIndex]; 3542 return dateTimePattern; 3543 } make(Calendar cal, ULocale loc)3544 private static PatternData make(Calendar cal, ULocale loc) { 3545 // Android patch (http://b/28832222) start. 3546 return make(loc, cal.getType()); 3547 } make(ULocale loc, String calType)3548 private static PatternData make(ULocale loc, String calType) { 3549 // Android patch (http://b/28832222) end. 3550 // First, try to get a pattern from PATTERN_CACHE 3551 String key = loc.getBaseName() + "+" + calType; 3552 PatternData patternData = PATTERN_CACHE.get(key); 3553 if (patternData == null) { 3554 // Cache missed. Get one from bundle 3555 try { 3556 patternData = getPatternData(loc, calType); 3557 } catch (MissingResourceException e) { 3558 patternData = new PatternData(DEFAULT_PATTERNS, null); 3559 } 3560 PATTERN_CACHE.put(key, patternData); 3561 } 3562 return patternData; 3563 } 3564 } 3565 3566 /** 3567 * Retrieves the DateTime patterns and overrides from the resource bundle and generates a 3568 * new PatternData object. 3569 * @param locale Locale to retrieve. 3570 * @param calType Calendar type to retrieve. If not found will fallback to gregorian. 3571 * @return PatternData object for this locale and calendarType. 3572 */ getPatternData(ULocale locale, String calType)3573 private static PatternData getPatternData(ULocale locale, String calType) { 3574 ICUResourceBundle rb = 3575 (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, locale); 3576 ICUResourceBundle dtPatternsRb = rb.findWithFallback("calendar/" + calType + "/DateTimePatterns"); 3577 if (dtPatternsRb == null) { 3578 dtPatternsRb = rb.getWithFallback("calendar/gregorian/DateTimePatterns"); 3579 } 3580 3581 int patternsSize = dtPatternsRb.getSize(); 3582 String[] dateTimePatterns = new String[patternsSize]; 3583 String[] dateTimePatternsOverrides = new String[patternsSize]; 3584 for (int i = 0; i < patternsSize; i++) { 3585 ICUResourceBundle concatenationPatternRb = (ICUResourceBundle) dtPatternsRb.get(i); 3586 switch (concatenationPatternRb.getType()) { 3587 case UResourceBundle.STRING: 3588 dateTimePatterns[i] = concatenationPatternRb.getString(); 3589 break; 3590 case UResourceBundle.ARRAY: 3591 dateTimePatterns[i] = concatenationPatternRb.getString(0); 3592 dateTimePatternsOverrides[i] = concatenationPatternRb.getString(1); 3593 break; 3594 } 3595 } 3596 return new PatternData(dateTimePatterns, dateTimePatternsOverrides); 3597 } 3598 3599 /** 3600 * @deprecated This API is ICU internal only. 3601 * @hide original deprecated declaration 3602 * @hide draft / provisional / internal are hidden on Android 3603 */ 3604 @Deprecated getDateTimePattern(Calendar cal, ULocale uLocale, int dateStyle)3605 public static String getDateTimePattern(Calendar cal, ULocale uLocale, int dateStyle) { 3606 PatternData patternData = PatternData.make(cal, uLocale); 3607 return patternData.getDateTimePattern(dateStyle); 3608 } 3609 mergeOverrideStrings( String datePattern, String timePattern, String dateOverride, String timeOverride )3610 private static String mergeOverrideStrings( String datePattern, String timePattern, 3611 String dateOverride, String timeOverride ) { 3612 3613 if ( dateOverride == null && timeOverride == null ) { 3614 return null; 3615 } 3616 3617 if ( dateOverride == null ) { 3618 return expandOverride(timePattern,timeOverride); 3619 } 3620 3621 if ( timeOverride == null ) { 3622 return expandOverride(datePattern,dateOverride); 3623 } 3624 3625 if ( dateOverride.equals(timeOverride) ) { 3626 return dateOverride; 3627 } 3628 3629 return (expandOverride(datePattern,dateOverride)+";"+ 3630 expandOverride(timePattern,timeOverride)); 3631 3632 } 3633 3634 private static final char QUOTE = '\''; expandOverride(String pattern, String override)3635 private static String expandOverride(String pattern, String override) { 3636 3637 if (override.indexOf('=') >= 0) { 3638 return override; 3639 } 3640 boolean inQuotes = false; 3641 char prevChar = ' '; 3642 StringBuilder result = new StringBuilder(); 3643 3644 StringCharacterIterator it = new StringCharacterIterator(pattern); 3645 3646 for (char c = it.first(); c!= StringCharacterIterator.DONE; c = it.next()) { 3647 if ( c == QUOTE ) { 3648 inQuotes = !inQuotes; 3649 prevChar = c; 3650 continue; 3651 } 3652 if ( !inQuotes && c != prevChar ) { 3653 if (result.length() > 0) { 3654 result.append(";"); 3655 } 3656 result.append(c); 3657 result.append("="); 3658 result.append(override); 3659 } 3660 prevChar = c; 3661 } 3662 return result.toString(); 3663 } 3664 /** 3665 * An instance of FormatConfiguration represents calendar specific 3666 * date format configuration and used for calling the ICU private 3667 * SimpleDateFormat factory method. 3668 * 3669 * @deprecated This API is ICU internal only. 3670 * @hide original deprecated declaration 3671 * @hide draft / provisional / internal are hidden on Android 3672 */ 3673 @Deprecated 3674 public static class FormatConfiguration { 3675 private String pattern; 3676 private String override; 3677 private DateFormatSymbols formatData; 3678 private Calendar cal; 3679 private ULocale loc; 3680 3681 // Only Calendar can instantiate FormatConfiguration()3682 private FormatConfiguration() { 3683 } 3684 3685 /** 3686 * Returns the pattern string 3687 * @return the format pattern string 3688 * @deprecated This API is ICU internal only. 3689 * @hide original deprecated declaration 3690 * @hide draft / provisional / internal are hidden on Android 3691 */ 3692 @Deprecated getPatternString()3693 public String getPatternString() { 3694 return pattern; 3695 } 3696 3697 /** 3698 * @deprecated This API is ICU internal only. 3699 * @hide original deprecated declaration 3700 * @hide draft / provisional / internal are hidden on Android 3701 */ 3702 @Deprecated getOverrideString()3703 public String getOverrideString() { 3704 return override; 3705 } 3706 3707 /** 3708 * Returns the calendar 3709 * @return the calendar 3710 * @deprecated This API is ICU internal only. 3711 * @hide original deprecated declaration 3712 * @hide draft / provisional / internal are hidden on Android 3713 */ 3714 @Deprecated getCalendar()3715 public Calendar getCalendar() { 3716 return cal; 3717 } 3718 3719 /** 3720 * Returns the locale 3721 * @return the locale 3722 * @deprecated This API is ICU internal only. 3723 * @hide original deprecated declaration 3724 * @hide draft / provisional / internal are hidden on Android 3725 */ 3726 @Deprecated getLocale()3727 public ULocale getLocale() { 3728 return loc; 3729 } 3730 3731 /** 3732 * Returns the format symbols 3733 * @return the format symbols 3734 * @deprecated This API is ICU internal only. 3735 * @hide original deprecated declaration 3736 * @hide draft / provisional / internal are hidden on Android 3737 */ 3738 @Deprecated getDateFormatSymbols()3739 public DateFormatSymbols getDateFormatSymbols() { 3740 return formatData; 3741 } 3742 } 3743 3744 //------------------------------------------------------------------------- 3745 // Protected utility methods for use by subclasses. These are very handy 3746 // for implementing add, roll, and computeFields. 3747 //------------------------------------------------------------------------- 3748 3749 /** 3750 * Adjust the specified field so that it is within 3751 * the allowable range for the date to which this calendar is set. 3752 * For example, in a Gregorian calendar pinning the {@link #DAY_OF_MONTH DAY_OF_MONTH} 3753 * field for a calendar set to April 31 would cause it to be set 3754 * to April 30. 3755 * <p> 3756 * <b>Subclassing:</b> 3757 * <br> 3758 * This utility method is intended for use by subclasses that need to implement 3759 * their own overrides of {@link #roll roll} and {@link #add add}. 3760 * <p> 3761 * <b>Note:</b> 3762 * <code>pinField</code> is implemented in terms of 3763 * {@link #getActualMinimum getActualMinimum} 3764 * and {@link #getActualMaximum getActualMaximum}. If either of those methods uses 3765 * a slow, iterative algorithm for a particular field, it would be 3766 * unwise to attempt to call <code>pinField</code> for that field. If you 3767 * really do need to do so, you should override this method to do 3768 * something more efficient for that field. 3769 * <p> 3770 * @param field The calendar field whose value should be pinned. 3771 * 3772 * @see #getActualMinimum 3773 * @see #getActualMaximum 3774 */ pinField(int field)3775 protected void pinField(int field) { 3776 int max = getActualMaximum(field); 3777 int min = getActualMinimum(field); 3778 3779 if (fields[field] > max) { 3780 set(field, max); 3781 } else if (fields[field] < min) { 3782 set(field, min); 3783 } 3784 } 3785 3786 /** 3787 * Returns the week number of a day, within a period. This may be the week number in 3788 * a year or the week number in a month. Usually this will be a value >= 1, but if 3789 * some initial days of the period are excluded from week 1, because 3790 * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} is > 1, then 3791 * the week number will be zero for those 3792 * initial days. This method requires the day number and day of week for some 3793 * known date in the period in order to determine the day of week 3794 * on the desired day. 3795 * <p> 3796 * <b>Subclassing:</b> 3797 * <br> 3798 * This method is intended for use by subclasses in implementing their 3799 * {@link #computeTime computeTime} and/or {@link #computeFields computeFields} methods. 3800 * It is often useful in {@link #getActualMinimum getActualMinimum} and 3801 * {@link #getActualMaximum getActualMaximum} as well. 3802 * <p> 3803 * This variant is handy for computing the week number of some other 3804 * day of a period (often the first or last day of the period) when its day 3805 * of the week is not known but the day number and day of week for some other 3806 * day in the period (e.g. the current date) <em>is</em> known. 3807 * <p> 3808 * @param desiredDay The {@link #DAY_OF_YEAR DAY_OF_YEAR} or 3809 * {@link #DAY_OF_MONTH DAY_OF_MONTH} whose week number is desired. 3810 * Should be 1 for the first day of the period. 3811 * 3812 * @param dayOfPeriod The {@link #DAY_OF_YEAR DAY_OF_YEAR} 3813 * or {@link #DAY_OF_MONTH DAY_OF_MONTH} for a day in the period whose 3814 * {@link #DAY_OF_WEEK DAY_OF_WEEK} is specified by the 3815 * <code>dayOfWeek</code> parameter. 3816 * Should be 1 for first day of period. 3817 * 3818 * @param dayOfWeek The {@link #DAY_OF_WEEK DAY_OF_WEEK} for the day 3819 * corresponding to the <code>dayOfPeriod</code> parameter. 3820 * 1-based with 1=Sunday. 3821 * 3822 * @return The week number (one-based), or zero if the day falls before 3823 * the first week because 3824 * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} 3825 * is more than one. 3826 */ weekNumber(int desiredDay, int dayOfPeriod, int dayOfWeek)3827 protected int weekNumber(int desiredDay, int dayOfPeriod, int dayOfWeek) 3828 { 3829 // Determine the day of the week of the first day of the period 3830 // in question (either a year or a month). Zero represents the 3831 // first day of the week on this calendar. 3832 int periodStartDayOfWeek = (dayOfWeek - getFirstDayOfWeek() - dayOfPeriod + 1) % 7; 3833 if (periodStartDayOfWeek < 0) periodStartDayOfWeek += 7; 3834 3835 // Compute the week number. Initially, ignore the first week, which 3836 // may be fractional (or may not be). We add periodStartDayOfWeek in 3837 // order to fill out the first week, if it is fractional. 3838 int weekNo = (desiredDay + periodStartDayOfWeek - 1)/7; 3839 3840 // If the first week is long enough, then count it. If 3841 // the minimal days in the first week is one, or if the period start 3842 // is zero, we always increment weekNo. 3843 if ((7 - periodStartDayOfWeek) >= getMinimalDaysInFirstWeek()) ++weekNo; 3844 3845 return weekNo; 3846 } 3847 3848 /** 3849 * Returns the week number of a day, within a period. This may be the week number in 3850 * a year, or the week number in a month. Usually this will be a value >= 1, but if 3851 * some initial days of the period are excluded from week 1, because 3852 * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} is > 1, 3853 * then the week number will be zero for those 3854 * initial days. This method requires the day of week for the given date in order to 3855 * determine the result. 3856 * <p> 3857 * <b>Subclassing:</b> 3858 * <br> 3859 * This method is intended for use by subclasses in implementing their 3860 * {@link #computeTime computeTime} and/or {@link #computeFields computeFields} methods. 3861 * It is often useful in {@link #getActualMinimum getActualMinimum} and 3862 * {@link #getActualMaximum getActualMaximum} as well. 3863 * <p> 3864 * @param dayOfPeriod The {@link #DAY_OF_YEAR DAY_OF_YEAR} or 3865 * {@link #DAY_OF_MONTH DAY_OF_MONTH} whose week number is desired. 3866 * Should be 1 for the first day of the period. 3867 * 3868 * @param dayOfWeek The {@link #DAY_OF_WEEK DAY_OF_WEEK} for the day 3869 * corresponding to the <code>dayOfPeriod</code> parameter. 3870 * 1-based with 1=Sunday. 3871 * 3872 * @return The week number (one-based), or zero if the day falls before 3873 * the first week because 3874 * {@link #getMinimalDaysInFirstWeek getMinimalDaysInFirstWeek} 3875 * is more than one. 3876 */ weekNumber(int dayOfPeriod, int dayOfWeek)3877 protected final int weekNumber(int dayOfPeriod, int dayOfWeek) 3878 { 3879 return weekNumber(dayOfPeriod, dayOfPeriod, dayOfWeek); 3880 } 3881 3882 //------------------------------------------------------------------------- 3883 // Constants 3884 //------------------------------------------------------------------------- 3885 3886 private static final int FIELD_DIFF_MAX_INT = Integer.MAX_VALUE; // 2147483647 3887 3888 /** 3889 * <strong>[icu]</strong> Returns the difference between the given time and the time this 3890 * calendar object is set to. If this calendar is set 3891 * <em>before</em> the given time, the returned value will be 3892 * positive. If this calendar is set <em>after</em> the given 3893 * time, the returned value will be negative. The 3894 * <code>field</code> parameter specifies the units of the return 3895 * value. For example, if <code>fieldDifference(when, 3896 * Calendar.MONTH)</code> returns 3, then this calendar is set to 3897 * 3 months before <code>when</code>, and possibly some additional 3898 * time less than one month. 3899 * 3900 * <p>As a side effect of this call, this calendar is advanced 3901 * toward <code>when</code> by the given amount. That is, calling 3902 * this method has the side effect of calling <code>add(field, 3903 * n)</code>, where <code>n</code> is the return value. 3904 * 3905 * <p>Usage: To use this method, call it first with the largest 3906 * field of interest, then with progressively smaller fields. For 3907 * example: 3908 * 3909 * <pre> 3910 * int y = cal.fieldDifference(when, Calendar.YEAR); 3911 * int m = cal.fieldDifference(when, Calendar.MONTH); 3912 * int d = cal.fieldDifference(when, Calendar.DATE);</pre> 3913 * 3914 * computes the difference between <code>cal</code> and 3915 * <code>when</code> in years, months, and days. 3916 * 3917 * <p>Note: <code>fieldDifference()</code> is 3918 * <em>asymmetrical</em>. That is, in the following code: 3919 * 3920 * <pre> 3921 * cal.setTime(date1); 3922 * int m1 = cal.fieldDifference(date2, Calendar.MONTH); 3923 * int d1 = cal.fieldDifference(date2, Calendar.DATE); 3924 * cal.setTime(date2); 3925 * int m2 = cal.fieldDifference(date1, Calendar.MONTH); 3926 * int d2 = cal.fieldDifference(date1, Calendar.DATE);</pre> 3927 * 3928 * one might expect that <code>m1 == -m2 && d1 == -d2</code>. 3929 * However, this is not generally the case, because of 3930 * irregularities in the underlying calendar system (e.g., the 3931 * Gregorian calendar has a varying number of days per month). 3932 * 3933 * @param when the date to compare this calendar's time to 3934 * @param field the field in which to compute the result 3935 * @return the difference, either positive or negative, between 3936 * this calendar's time and <code>when</code>, in terms of 3937 * <code>field</code>. 3938 */ fieldDifference(Date when, int field)3939 public int fieldDifference(Date when, int field) { 3940 int min = 0; 3941 long startMs = getTimeInMillis(); 3942 long targetMs = when.getTime(); 3943 // Always add from the start millis. This accomodates 3944 // operations like adding years from February 29, 2000 up to 3945 // February 29, 2004. If 1, 1, 1, 1 is added to the year 3946 // field, the DOM gets pinned to 28 and stays there, giving an 3947 // incorrect DOM difference of 1. We have to add 1, reset, 2, 3948 // reset, 3, reset, 4. 3949 if (startMs < targetMs) { 3950 int max = 1; 3951 // Find a value that is too large 3952 for (;;) { 3953 setTimeInMillis(startMs); 3954 add(field, max); 3955 long ms = getTimeInMillis(); 3956 if (ms == targetMs) { 3957 return max; 3958 } else if (ms > targetMs) { 3959 break; 3960 } else if (max < FIELD_DIFF_MAX_INT) { 3961 min = max; 3962 max <<= 1; 3963 if (max < 0) { 3964 max = FIELD_DIFF_MAX_INT; 3965 } 3966 } else { 3967 // Field difference too large to fit into int 3968 throw new RuntimeException(); 3969 } 3970 } 3971 // Do a binary search 3972 while ((max - min) > 1) { 3973 int t = min + (max - min)/2; // make sure intermediate values don't exceed FIELD_DIFF_MAX_INT 3974 setTimeInMillis(startMs); 3975 add(field, t); 3976 long ms = getTimeInMillis(); 3977 if (ms == targetMs) { 3978 return t; 3979 } else if (ms > targetMs) { 3980 max = t; 3981 } else { 3982 min = t; 3983 } 3984 } 3985 } else if (startMs > targetMs) { 3986 //Eclipse stated the following is "dead code" 3987 /*if (false) { 3988 // This works, and makes the code smaller, but costs 3989 // an extra object creation and an extra couple cycles 3990 // of calendar computation. 3991 setTimeInMillis(targetMs); 3992 min = -fieldDifference(new Date(startMs), field); 3993 }*/ 3994 int max = -1; 3995 // Find a value that is too small 3996 for (;;) { 3997 setTimeInMillis(startMs); 3998 add(field, max); 3999 long ms = getTimeInMillis(); 4000 if (ms == targetMs) { 4001 return max; 4002 } else if (ms < targetMs) { 4003 break; 4004 } else { 4005 min = max; 4006 max <<= 1; 4007 if (max == 0) { 4008 // Field difference too large to fit into int 4009 throw new RuntimeException(); 4010 } 4011 } 4012 } 4013 // Do a binary search 4014 while ((min - max) > 1) { 4015 int t = min + (max - min)/2; // make sure intermediate values don't exceed FIELD_DIFF_MAX_INT 4016 setTimeInMillis(startMs); 4017 add(field, t); 4018 long ms = getTimeInMillis(); 4019 if (ms == targetMs) { 4020 return t; 4021 } else if (ms < targetMs) { 4022 max = t; 4023 } else { 4024 min = t; 4025 } 4026 } 4027 } 4028 // Set calendar to end point 4029 setTimeInMillis(startMs); 4030 add(field, min); 4031 return min; 4032 } 4033 4034 /** 4035 * Sets the time zone with the given time zone value. 4036 * @param value the given time zone. 4037 */ setTimeZone(TimeZone value)4038 public void setTimeZone(TimeZone value) 4039 { 4040 zone = value; 4041 /* Recompute the fields from the time using the new zone. This also 4042 * works if isTimeSet is false (after a call to set()). In that case 4043 * the time will be computed from the fields using the new zone, then 4044 * the fields will get recomputed from that. Consider the sequence of 4045 * calls: cal.setTimeZone(EST); cal.set(HOUR, 1); cal.setTimeZone(PST). 4046 * Is cal set to 1 o'clock EST or 1 o'clock PST? Answer: PST. More 4047 * generally, a call to setTimeZone() affects calls to set() BEFORE AND 4048 * AFTER it up to the next call to complete(). 4049 */ 4050 areFieldsSet = false; 4051 } 4052 4053 /** 4054 * Returns the time zone. 4055 * @return the time zone object associated with this calendar. 4056 */ getTimeZone()4057 public TimeZone getTimeZone() 4058 { 4059 return zone; 4060 } 4061 4062 /** 4063 * Specify whether or not date/time interpretation is to be lenient. With 4064 * lenient interpretation, a date such as "February 942, 1996" will be 4065 * treated as being equivalent to the 941st day after February 1, 1996. 4066 * With strict interpretation, such dates will cause an exception to be 4067 * thrown. 4068 * 4069 * @see DateFormat#setLenient 4070 */ setLenient(boolean lenient)4071 public void setLenient(boolean lenient) 4072 { 4073 this.lenient = lenient; 4074 } 4075 4076 /** 4077 * Tell whether date/time interpretation is to be lenient. 4078 */ isLenient()4079 public boolean isLenient() 4080 { 4081 return lenient; 4082 } 4083 4084 /** 4085 * <strong>[icu]</strong>Sets the behavior for handling wall time repeating multiple times 4086 * at negative time zone offset transitions. For example, 1:30 AM on 4087 * November 6, 2011 in US Eastern time (Ameirca/New_York) occurs twice; 4088 * 1:30 AM EDT, then 1:30 AM EST one hour later. When <code>WALLTIME_FIRST</code> 4089 * is used, the wall time 1:30AM in this example will be interpreted as 1:30 AM EDT 4090 * (first occurrence). When <code>WALLTIME_LAST</code> is used, it will be 4091 * interpreted as 1:30 AM EST (last occurrence). The default value is 4092 * <code>WALLTIME_LAST</code>. 4093 * 4094 * @param option the behavior for handling repeating wall time, either 4095 * <code>WALLTIME_FIRST</code> or <code>WALLTIME_LAST</code>. 4096 * @throws IllegalArgumentException when <code>option</code> is neither 4097 * <code>WALLTIME_FIRST</code> nor <code>WALLTIME_LAST</code>. 4098 * 4099 * @see #getRepeatedWallTimeOption() 4100 * @see #WALLTIME_FIRST 4101 * @see #WALLTIME_LAST 4102 */ setRepeatedWallTimeOption(int option)4103 public void setRepeatedWallTimeOption(int option) { 4104 if (option != WALLTIME_LAST && option != WALLTIME_FIRST) { 4105 throw new IllegalArgumentException("Illegal repeated wall time option - " + option); 4106 } 4107 repeatedWallTime = option; 4108 } 4109 4110 /** 4111 * <strong>[icu]</strong>Gets the behavior for handling wall time repeating multiple times 4112 * at negative time zone offset transitions. 4113 * 4114 * @return the behavior for handling repeating wall time, either 4115 * <code>WALLTIME_FIRST</code> or <code>WALLTIME_LAST</code>. 4116 * 4117 * @see #setRepeatedWallTimeOption(int) 4118 * @see #WALLTIME_FIRST 4119 * @see #WALLTIME_LAST 4120 */ getRepeatedWallTimeOption()4121 public int getRepeatedWallTimeOption() { 4122 return repeatedWallTime; 4123 } 4124 4125 /** 4126 * <strong>[icu]</strong>Sets the behavior for handling skipped wall time at positive time zone offset 4127 * transitions. For example, 2:30 AM on March 13, 2011 in US Eastern time (America/New_York) 4128 * does not exist because the wall time jump from 1:59 AM EST to 3:00 AM EDT. When 4129 * <code>WALLTIME_FIRST</code> is used, 2:30 AM is interpreted as 30 minutes before 3:00 AM 4130 * EDT, therefore, it will be resolved as 1:30 AM EST. When <code>WALLTIME_LAST</code> 4131 * is used, 2:30 AM is interpreted as 31 minutes after 1:59 AM EST, therefore, it will be 4132 * resolved as 3:30 AM EDT. When <code>WALLTIME_NEXT_VALID</code> is used, 2:30 AM will 4133 * be resolved as next valid wall time, that is 3:00 AM EDT. The default value is 4134 * <code>WALLTIME_LAST</code>. 4135 * <p> 4136 * <b>Note:</b>This option is effective only when this calendar is {@link #isLenient() lenient}. 4137 * When the calendar is strict, such non-existing wall time will cause an exception. 4138 * 4139 * @param option the behavior for handling skipped wall time at positive time zone 4140 * offset transitions, one of <code>WALLTIME_FIRST</code>, <code>WALLTIME_LAST</code> and 4141 * <code>WALLTIME_NEXT_VALID</code>. 4142 * @throws IllegalArgumentException when <code>option</code> is not any of 4143 * <code>WALLTIME_FIRST</code>, <code>WALLTIME_LAST</code> and <code>WALLTIME_NEXT_VALID</code>. 4144 * 4145 * @see #getSkippedWallTimeOption() 4146 * @see #WALLTIME_FIRST 4147 * @see #WALLTIME_LAST 4148 * @see #WALLTIME_NEXT_VALID 4149 */ setSkippedWallTimeOption(int option)4150 public void setSkippedWallTimeOption(int option) { 4151 if (option != WALLTIME_LAST && option != WALLTIME_FIRST && option != WALLTIME_NEXT_VALID) { 4152 throw new IllegalArgumentException("Illegal skipped wall time option - " + option); 4153 } 4154 skippedWallTime = option; 4155 } 4156 4157 /** 4158 * <strong>[icu]</strong>Gets the behavior for handling skipped wall time at positive time zone offset 4159 * transitions. 4160 * 4161 * @return the behavior for handling skipped wall time, one of 4162 * <code>WALLTIME_FIRST</code>, <code>WALLTIME_LAST</code> and <code>WALLTIME_NEXT_VALID</code>. 4163 * 4164 * @see #setSkippedWallTimeOption(int) 4165 * @see #WALLTIME_FIRST 4166 * @see #WALLTIME_LAST 4167 * @see #WALLTIME_NEXT_VALID 4168 */ getSkippedWallTimeOption()4169 public int getSkippedWallTimeOption() { 4170 return skippedWallTime; 4171 } 4172 4173 /** 4174 * Sets what the first day of the week is, 4175 * where 1 = {@link #SUNDAY} and 7 = {@link #SATURDAY}. 4176 * @param value the given first day of the week, where 1 = {@link #SUNDAY} and 7 = {@link #SATURDAY}. 4177 */ setFirstDayOfWeek(int value)4178 public void setFirstDayOfWeek(int value) 4179 { 4180 if (firstDayOfWeek != value) { 4181 if (value < SUNDAY || value > SATURDAY) { 4182 throw new IllegalArgumentException("Invalid day of week"); 4183 } 4184 firstDayOfWeek = value; 4185 areFieldsSet = false; 4186 } 4187 } 4188 4189 /** 4190 * Returns what the first day of the week is, 4191 * where 1 = {@link #SUNDAY} and 7 = {@link #SATURDAY}. 4192 * e.g., Sunday in US, Monday in France 4193 * @return the first day of the week, where 1 = {@link #SUNDAY} and 7 = {@link #SATURDAY}. 4194 */ getFirstDayOfWeek()4195 public int getFirstDayOfWeek() 4196 { 4197 return firstDayOfWeek; 4198 } 4199 4200 /** 4201 * Sets what the minimal days required in the first week of the year are. 4202 * For example, if the first week is defined as one that contains the first 4203 * day of the first month of a year, call the method with value 1. If it 4204 * must be a full week, use value 7. 4205 * @param value the given minimal days required in the first week 4206 * of the year. 4207 */ setMinimalDaysInFirstWeek(int value)4208 public void setMinimalDaysInFirstWeek(int value) 4209 { 4210 // Values less than 1 have the same effect as 1; values greater 4211 // than 7 have the same effect as 7. However, we normalize values 4212 // so operator== and so forth work. 4213 if (value < 1) { 4214 value = 1; 4215 } else if (value > 7) { 4216 value = 7; 4217 } 4218 if (minimalDaysInFirstWeek != value) { 4219 minimalDaysInFirstWeek = value; 4220 areFieldsSet = false; 4221 } 4222 } 4223 4224 /** 4225 * Returns what the minimal days required in the first week of the year are. 4226 * That is, if the first week is defined as one that contains the first day 4227 * of the first month of a year, getMinimalDaysInFirstWeek returns 1. If 4228 * the minimal days required must be a full week, getMinimalDaysInFirstWeek 4229 * returns 7. 4230 * @return the minimal days required in the first week of the year. 4231 */ getMinimalDaysInFirstWeek()4232 public int getMinimalDaysInFirstWeek() 4233 { 4234 return minimalDaysInFirstWeek; 4235 } 4236 4237 private static final int LIMITS[][] = { 4238 // Minimum Greatest min Least max Greatest max 4239 {/* */}, // ERA 4240 {/* */}, // YEAR 4241 {/* */}, // MONTH 4242 {/* */}, // WEEK_OF_YEAR 4243 {/* */}, // WEEK_OF_MONTH 4244 {/* */}, // DAY_OF_MONTH 4245 {/* */}, // DAY_OF_YEAR 4246 { 1, 1, 7, 7 }, // DAY_OF_WEEK 4247 {/* */}, // DAY_OF_WEEK_IN_MONTH 4248 { 0, 0, 1, 1 }, // AM_PM 4249 { 0, 0, 11, 11 }, // HOUR 4250 { 0, 0, 23, 23 }, // HOUR_OF_DAY 4251 { 0, 0, 59, 59 }, // MINUTE 4252 { 0, 0, 59, 59 }, // SECOND 4253 { 0, 0, 999, 999 }, // MILLISECOND 4254 {-12*ONE_HOUR, -12*ONE_HOUR, 12*ONE_HOUR, 12*ONE_HOUR }, // ZONE_OFFSET 4255 { 0, 0, 1*ONE_HOUR, 1*ONE_HOUR }, // DST_OFFSET 4256 {/* */}, // YEAR_WOY 4257 { 1, 1, 7, 7 }, // DOW_LOCAL 4258 {/* */}, // EXTENDED_YEAR 4259 { -0x7F000000, -0x7F000000, 0x7F000000, 0x7F000000 }, // JULIAN_DAY 4260 { 0, 0, 24*ONE_HOUR-1, 24*ONE_HOUR-1 }, // MILLISECONDS_IN_DAY 4261 { 0, 0, 1, 1 }, // IS_LEAP_MONTH 4262 }; 4263 4264 /** 4265 * Subclass API for defining limits of different types. 4266 * Subclasses must implement this method to return limits for the 4267 * following fields: 4268 * 4269 * <pre>ERA 4270 * YEAR 4271 * MONTH 4272 * WEEK_OF_YEAR 4273 * WEEK_OF_MONTH 4274 * DAY_OF_MONTH 4275 * DAY_OF_YEAR 4276 * DAY_OF_WEEK_IN_MONTH 4277 * YEAR_WOY 4278 * EXTENDED_YEAR</pre> 4279 * 4280 * @param field one of the above field numbers 4281 * @param limitType one of <code>MINIMUM</code>, <code>GREATEST_MINIMUM</code>, 4282 * <code>LEAST_MAXIMUM</code>, or <code>MAXIMUM</code> 4283 */ handleGetLimit(int field, int limitType)4284 abstract protected int handleGetLimit(int field, int limitType); 4285 4286 /** 4287 * Returns a limit for a field. 4288 * @param field the field, from 0..<code>getFieldCount()-1</code> 4289 * @param limitType the type specifier for the limit 4290 * @see #MINIMUM 4291 * @see #GREATEST_MINIMUM 4292 * @see #LEAST_MAXIMUM 4293 * @see #MAXIMUM 4294 */ getLimit(int field, int limitType)4295 protected int getLimit(int field, int limitType) { 4296 switch (field) { 4297 case DAY_OF_WEEK: 4298 case AM_PM: 4299 case HOUR: 4300 case HOUR_OF_DAY: 4301 case MINUTE: 4302 case SECOND: 4303 case MILLISECOND: 4304 case ZONE_OFFSET: 4305 case DST_OFFSET: 4306 case DOW_LOCAL: 4307 case JULIAN_DAY: 4308 case MILLISECONDS_IN_DAY: 4309 case IS_LEAP_MONTH: 4310 return LIMITS[field][limitType]; 4311 4312 case WEEK_OF_MONTH: 4313 { 4314 int limit; 4315 if (limitType == MINIMUM) { 4316 limit = getMinimalDaysInFirstWeek() == 1 ? 1 : 0; 4317 } else if (limitType == GREATEST_MINIMUM){ 4318 limit = 1; 4319 } else { 4320 int minDaysInFirst = getMinimalDaysInFirstWeek(); 4321 int daysInMonth = handleGetLimit(DAY_OF_MONTH, limitType); 4322 if (limitType == LEAST_MAXIMUM) { 4323 limit = (daysInMonth + (7 - minDaysInFirst)) / 7; 4324 } else { // limitType == MAXIMUM 4325 limit = (daysInMonth + 6 + (7 - minDaysInFirst)) / 7; 4326 } 4327 } 4328 return limit; 4329 } 4330 4331 } 4332 return handleGetLimit(field, limitType); 4333 } 4334 4335 /** 4336 * Limit type for <code>getLimit()</code> and <code>handleGetLimit()</code> 4337 * indicating the minimum value that a field can take (least minimum). 4338 * @see #getLimit 4339 * @see #handleGetLimit 4340 */ 4341 protected static final int MINIMUM = 0; 4342 4343 /** 4344 * Limit type for <code>getLimit()</code> and <code>handleGetLimit()</code> 4345 * indicating the greatest minimum value that a field can take. 4346 * @see #getLimit 4347 * @see #handleGetLimit 4348 */ 4349 protected static final int GREATEST_MINIMUM = 1; 4350 4351 /** 4352 * Limit type for <code>getLimit()</code> and <code>handleGetLimit()</code> 4353 * indicating the least maximum value that a field can take. 4354 * @see #getLimit 4355 * @see #handleGetLimit 4356 */ 4357 protected static final int LEAST_MAXIMUM = 2; 4358 4359 /** 4360 * Limit type for <code>getLimit()</code> and <code>handleGetLimit()</code> 4361 * indicating the maximum value that a field can take (greatest maximum). 4362 * @see #getLimit 4363 * @see #handleGetLimit 4364 */ 4365 protected static final int MAXIMUM = 3; 4366 4367 /** 4368 * Returns the minimum value for the given time field. 4369 * e.g., for Gregorian DAY_OF_MONTH, 1. 4370 * @param field the given time field. 4371 * @return the minimum value for the given time field. 4372 */ getMinimum(int field)4373 public final int getMinimum(int field) { 4374 return getLimit(field, MINIMUM); 4375 } 4376 4377 /** 4378 * Returns the maximum value for the given time field. 4379 * e.g. for Gregorian DAY_OF_MONTH, 31. 4380 * @param field the given time field. 4381 * @return the maximum value for the given time field. 4382 */ getMaximum(int field)4383 public final int getMaximum(int field) { 4384 return getLimit(field, MAXIMUM); 4385 } 4386 4387 /** 4388 * Returns the highest minimum value for the given field if varies. 4389 * Otherwise same as getMinimum(). For Gregorian, no difference. 4390 * @param field the given time field. 4391 * @return the highest minimum value for the given time field. 4392 */ getGreatestMinimum(int field)4393 public final int getGreatestMinimum(int field) { 4394 return getLimit(field, GREATEST_MINIMUM); 4395 } 4396 4397 /** 4398 * Returns the lowest maximum value for the given field if varies. 4399 * Otherwise same as getMaximum(). e.g., for Gregorian DAY_OF_MONTH, 28. 4400 * @param field the given time field. 4401 * @return the lowest maximum value for the given time field. 4402 */ getLeastMaximum(int field)4403 public final int getLeastMaximum(int field) { 4404 return getLimit(field, LEAST_MAXIMUM); 4405 } 4406 4407 //------------------------------------------------------------------------- 4408 // Weekend support -- determining which days of the week are the weekend 4409 // in a given locale 4410 //------------------------------------------------------------------------- 4411 4412 /** 4413 * <strong>[icu]</strong> Returns whether the given day of the week is a weekday, a 4414 * weekend day, or a day that transitions from one to the other, for the 4415 * locale and calendar system associated with this Calendar (the locale's 4416 * region is often the most determinant factor). If a transition occurs at 4417 * midnight, then the days before and after the transition will have the 4418 * type WEEKDAY or WEEKEND. If a transition occurs at a time 4419 * other than midnight, then the day of the transition will have 4420 * the type WEEKEND_ONSET or WEEKEND_CEASE. In this case, the 4421 * method getWeekendTransition() will return the point of 4422 * transition. 4423 * @param dayOfWeek either SUNDAY, MONDAY, TUESDAY, WEDNESDAY, 4424 * THURSDAY, FRIDAY, or SATURDAY 4425 * @return either WEEKDAY, WEEKEND, WEEKEND_ONSET, or 4426 * WEEKEND_CEASE 4427 * @exception IllegalArgumentException if dayOfWeek is not 4428 * between SUNDAY and SATURDAY, inclusive 4429 * @see #WEEKDAY 4430 * @see #WEEKEND 4431 * @see #WEEKEND_ONSET 4432 * @see #WEEKEND_CEASE 4433 * @see #getWeekendTransition 4434 * @see #isWeekend(Date) 4435 * @see #isWeekend() 4436 * @deprecated ICU 54 use {@link #getWeekDataForRegion(String)}, {@link #getWeekData()}, {@link #setWeekData(WeekData)} 4437 * @hide original deprecated declaration 4438 */ 4439 @Deprecated getDayOfWeekType(int dayOfWeek)4440 public int getDayOfWeekType(int dayOfWeek) { 4441 if (dayOfWeek < SUNDAY || dayOfWeek > SATURDAY) { 4442 throw new IllegalArgumentException("Invalid day of week"); 4443 } 4444 if (weekendOnset == weekendCease) { 4445 if (dayOfWeek != weekendOnset) 4446 return WEEKDAY; 4447 return (weekendOnsetMillis == 0) ? WEEKEND : WEEKEND_ONSET; 4448 } 4449 if (weekendOnset < weekendCease) { 4450 if (dayOfWeek < weekendOnset || dayOfWeek > weekendCease) { 4451 return WEEKDAY; 4452 } 4453 } else { 4454 if (dayOfWeek > weekendCease && dayOfWeek < weekendOnset) { 4455 return WEEKDAY; 4456 } 4457 } 4458 if (dayOfWeek == weekendOnset) { 4459 return (weekendOnsetMillis == 0) ? WEEKEND : WEEKEND_ONSET; 4460 } 4461 if (dayOfWeek == weekendCease) { 4462 return (weekendCeaseMillis >= 86400000) ? WEEKEND : WEEKEND_CEASE; 4463 } 4464 return WEEKEND; 4465 } 4466 4467 /** 4468 * <strong>[icu]</strong> Returns the time during the day at which the weekend begins or end in this 4469 * calendar system. If getDayOfWeekType(dayOfWeek) == WEEKEND_ONSET return the time 4470 * at which the weekend begins. If getDayOfWeekType(dayOfWeek) == WEEKEND_CEASE 4471 * return the time at which the weekend ends. If getDayOfWeekType(dayOfWeek) has some 4472 * other value, then throw an exception. 4473 * @param dayOfWeek either SUNDAY, MONDAY, TUESDAY, WEDNESDAY, 4474 * THURSDAY, FRIDAY, or SATURDAY 4475 * @return the milliseconds after midnight at which the 4476 * weekend begins or ends 4477 * @exception IllegalArgumentException if dayOfWeek is not 4478 * WEEKEND_ONSET or WEEKEND_CEASE 4479 * @see #getDayOfWeekType 4480 * @see #isWeekend(Date) 4481 * @see #isWeekend() 4482 * @deprecated ICU 54 use {@link #getWeekDataForRegion(String)}, {@link #getWeekData()}, {@link #setWeekData(WeekData)} 4483 * @hide original deprecated declaration 4484 */ 4485 @Deprecated getWeekendTransition(int dayOfWeek)4486 public int getWeekendTransition(int dayOfWeek) { 4487 if (dayOfWeek == weekendOnset) { 4488 return weekendOnsetMillis; 4489 } else if (dayOfWeek == weekendCease) { 4490 return weekendCeaseMillis; 4491 } 4492 throw new IllegalArgumentException("Not weekend transition day"); 4493 } 4494 4495 /** 4496 * <strong>[icu]</strong> Returns true if the given date and time is in the weekend in this calendar 4497 * system. Equivalent to calling setTime() followed by isWeekend(). Note: This 4498 * method changes the time this calendar is set to. 4499 * @param date the date and time 4500 * @return true if the given date and time is part of the 4501 * weekend 4502 * @see #getDayOfWeekType 4503 * @see #getWeekendTransition 4504 * @see #isWeekend() 4505 */ isWeekend(Date date)4506 public boolean isWeekend(Date date) { 4507 setTime(date); 4508 return isWeekend(); 4509 } 4510 4511 /** 4512 * <strong>[icu]</strong> Returns true if this Calendar's current date and time is in the weekend in 4513 * this calendar system. 4514 * @return true if the given date and time is part of the 4515 * weekend 4516 * @see #getDayOfWeekType 4517 * @see #getWeekendTransition 4518 * @see #isWeekend(Date) 4519 */ isWeekend()4520 public boolean isWeekend() { 4521 int dow = get(DAY_OF_WEEK); 4522 int dowt = getDayOfWeekType(dow); 4523 switch (dowt) { 4524 case WEEKDAY: 4525 return false; 4526 case WEEKEND: 4527 return true; 4528 default: // That is, WEEKEND_ONSET or WEEKEND_CEASE 4529 // Use internalGet() because the above call to get() populated 4530 // all fields. 4531 // [Note: There should be a better way to get millis in day. 4532 // For ICU4J, submit request for a MILLIS_IN_DAY field 4533 // and a DAY_NUMBER field (could be Julian day #). - aliu] 4534 int millisInDay = internalGet(MILLISECOND) + 1000 * (internalGet(SECOND) + 4535 60 * (internalGet(MINUTE) + 60 * internalGet(HOUR_OF_DAY))); 4536 int transition = getWeekendTransition(dow); 4537 return (dowt == WEEKEND_ONSET) 4538 ? (millisInDay >= transition) 4539 : (millisInDay < transition); 4540 } 4541 // (We can never reach this point.) 4542 } 4543 4544 //------------------------------------------------------------------------- 4545 // End of weekend support 4546 //------------------------------------------------------------------------- 4547 4548 /** 4549 * Overrides Cloneable 4550 */ 4551 @Override clone()4552 public Object clone() 4553 { 4554 try { 4555 Calendar other = (Calendar) super.clone(); 4556 4557 other.fields = new int[fields.length]; 4558 other.stamp = new int[fields.length]; 4559 System.arraycopy(this.fields, 0, other.fields, 0, fields.length); 4560 System.arraycopy(this.stamp, 0, other.stamp, 0, fields.length); 4561 4562 other.zone = (TimeZone) zone.clone(); 4563 return other; 4564 } 4565 catch (CloneNotSupportedException e) { 4566 // this shouldn't happen, since we are Cloneable 4567 throw new ICUCloneNotSupportedException(e); 4568 } 4569 } 4570 4571 /** 4572 * Returns a string representation of this calendar. This method 4573 * is intended to be used only for debugging purposes, and the 4574 * format of the returned string may vary between implementations. 4575 * The returned string may be empty but may not be <code>null</code>. 4576 * 4577 * @return a string representation of this calendar. 4578 */ 4579 @Override toString()4580 public String toString() { 4581 StringBuilder buffer = new StringBuilder(); 4582 buffer.append(getClass().getName()); 4583 buffer.append("[time="); 4584 buffer.append(isTimeSet ? String.valueOf(time) : "?"); 4585 buffer.append(",areFieldsSet="); 4586 buffer.append(areFieldsSet); 4587 buffer.append(",areAllFieldsSet="); 4588 buffer.append(areAllFieldsSet); 4589 buffer.append(",lenient="); 4590 buffer.append(lenient); 4591 buffer.append(",zone="); 4592 buffer.append(zone); 4593 buffer.append(",firstDayOfWeek="); 4594 buffer.append(firstDayOfWeek); 4595 buffer.append(",minimalDaysInFirstWeek="); 4596 buffer.append(minimalDaysInFirstWeek); 4597 buffer.append(",repeatedWallTime="); 4598 buffer.append(repeatedWallTime); 4599 buffer.append(",skippedWallTime="); 4600 buffer.append(skippedWallTime); 4601 for (int i=0; i<fields.length; ++i) { 4602 buffer.append(',').append(fieldName(i)).append('='); 4603 buffer.append(isSet(i) ? String.valueOf(fields[i]) : "?"); 4604 } 4605 buffer.append(']'); 4606 return buffer.toString(); 4607 } 4608 4609 /** 4610 * Simple, immutable struct-like class for access to the CLDR weekend data. 4611 */ 4612 public static final class WeekData { 4613 /** 4614 * the first day of the week, where 1 = {@link #SUNDAY} and 7 = {@link #SATURDAY} 4615 */ 4616 public final int firstDayOfWeek; 4617 /** 4618 * the minimal number of days in the first week 4619 */ 4620 public final int minimalDaysInFirstWeek; 4621 /** 4622 * the onset day, where 1 = {@link #SUNDAY} and 7 = {@link #SATURDAY} 4623 */ 4624 public final int weekendOnset; 4625 /** 4626 * the onset time in millis during the onset day 4627 */ 4628 public final int weekendOnsetMillis; 4629 /** 4630 * the cease day, where 1 = {@link #SUNDAY} and 7 = {@link #SATURDAY} 4631 */ 4632 public final int weekendCease; 4633 /** 4634 * the cease time in millis during the cease day. Exclusive, so the max is 24:00:00.000. 4635 * Note that this will format as 00:00 the next day. 4636 */ 4637 public final int weekendCeaseMillis; 4638 4639 /** 4640 * Constructor 4641 * 4642 * @param fdow the first day of the week, where 1 = {@link #SUNDAY} and 7 = {@link #SATURDAY} 4643 * @param mdifw the minimal number of days in the first week 4644 * @param weekendOnset the onset day, where 1 = Sunday and 7 = Saturday 4645 * @param weekendOnsetMillis the onset time in millis during the onset day 4646 * @param weekendCease the cease day, where 1 = Sunday and 7 = Saturday 4647 * @param weekendCeaseMillis the cease time in millis during the cease day. 4648 */ WeekData(int fdow, int mdifw, int weekendOnset, int weekendOnsetMillis, int weekendCease, int weekendCeaseMillis)4649 public WeekData(int fdow, int mdifw, 4650 int weekendOnset, int weekendOnsetMillis, 4651 int weekendCease, int weekendCeaseMillis) { 4652 this.firstDayOfWeek = fdow; 4653 this.minimalDaysInFirstWeek = mdifw; 4654 this.weekendOnset = weekendOnset; 4655 this.weekendOnsetMillis = weekendOnsetMillis; 4656 this.weekendCease = weekendCease; 4657 this.weekendCeaseMillis = weekendCeaseMillis; 4658 } 4659 4660 /** 4661 * {@inheritDoc} 4662 */ 4663 @Override hashCode()4664 public int hashCode() { 4665 return ((((firstDayOfWeek * 37 + minimalDaysInFirstWeek) * 37 + weekendOnset) * 37 4666 + weekendOnsetMillis) * 37 + weekendCease) * 37 + weekendCeaseMillis; 4667 } 4668 4669 /** 4670 * {@inheritDoc} 4671 */ 4672 @Override equals(Object other)4673 public boolean equals(Object other) { 4674 if (this == other) { 4675 return true; 4676 } 4677 if (!(other instanceof WeekData)) { 4678 return false; 4679 } 4680 WeekData that = (WeekData) other; 4681 return firstDayOfWeek == that.firstDayOfWeek 4682 && minimalDaysInFirstWeek == that.minimalDaysInFirstWeek 4683 && weekendOnset == that.weekendOnset 4684 && weekendOnsetMillis == that.weekendOnsetMillis 4685 && weekendCease == that.weekendCease 4686 && weekendCeaseMillis == that.weekendCeaseMillis; 4687 } 4688 4689 /** 4690 * {@inheritDoc} 4691 */ 4692 @Override toString()4693 public String toString() { 4694 return "{" + firstDayOfWeek 4695 + ", " + minimalDaysInFirstWeek 4696 + ", " + weekendOnset 4697 + ", " + weekendOnsetMillis 4698 + ", " + weekendCease 4699 + ", " + weekendCeaseMillis 4700 + "}"; 4701 } 4702 } 4703 4704 /** 4705 * <strong>[icu]</strong> Return simple, immutable struct-like class for access to the CLDR weekend data. 4706 * @param region The input region. The results are undefined if the region code is not valid. 4707 * @return the WeekData for the input region. It is never null. 4708 */ getWeekDataForRegion(String region)4709 public static WeekData getWeekDataForRegion(String region) { 4710 return WEEK_DATA_CACHE.createInstance(region, region); 4711 } 4712 4713 /** 4714 * <strong>[icu]</strong> Return simple, immutable struct-like class for access to the weekend data in this calendar. 4715 * @return the WeekData for this calendar. 4716 */ getWeekData()4717 public WeekData getWeekData() { 4718 return new WeekData(firstDayOfWeek, minimalDaysInFirstWeek, weekendOnset, weekendOnsetMillis, weekendCease, weekendCeaseMillis); 4719 } 4720 4721 /** 4722 * <strong>[icu]</strong> Set data in this calendar based on the WeekData input. 4723 * @param wdata The week data to use 4724 * @return this, for chaining 4725 */ setWeekData(WeekData wdata)4726 public Calendar setWeekData(WeekData wdata) { 4727 setFirstDayOfWeek(wdata.firstDayOfWeek); 4728 setMinimalDaysInFirstWeek(wdata.minimalDaysInFirstWeek); 4729 4730 weekendOnset = wdata.weekendOnset; 4731 weekendOnsetMillis = wdata.weekendOnsetMillis; 4732 weekendCease = wdata.weekendCease; 4733 weekendCeaseMillis = wdata.weekendCeaseMillis; 4734 return this; 4735 } 4736 getWeekDataForRegionInternal(String region)4737 private static WeekData getWeekDataForRegionInternal(String region) { 4738 if (region == null) { 4739 region = "001"; 4740 } 4741 4742 UResourceBundle rb = UResourceBundle.getBundleInstance( 4743 ICUData.ICU_BASE_NAME, 4744 "supplementalData", 4745 ICUResourceBundle.ICU_DATA_CLASS_LOADER); 4746 UResourceBundle weekDataInfo = rb.get("weekData"); 4747 UResourceBundle weekDataBundle = null; 4748 4749 try { 4750 weekDataBundle = weekDataInfo.get(region); 4751 } catch (MissingResourceException mre) { 4752 if (!region.equals("001")) { 4753 // use "001" as fallback 4754 weekDataBundle = weekDataInfo.get("001"); 4755 } else { 4756 throw mre; 4757 } 4758 } 4759 4760 int[] wdi = weekDataBundle.getIntVector(); 4761 return new WeekData(wdi[0],wdi[1],wdi[2],wdi[3],wdi[4],wdi[5]); 4762 } 4763 4764 /* 4765 * Cache to hold week data by region 4766 */ 4767 private static class WeekDataCache extends SoftCache<String, WeekData, String> { 4768 4769 /* (non-Javadoc) 4770 * @see android.icu.impl.CacheBase#createInstance(java.lang.Object, java.lang.Object) 4771 */ 4772 @Override createInstance(String key, String data)4773 protected WeekData createInstance(String key, String data) { 4774 return getWeekDataForRegionInternal(key); 4775 } 4776 } 4777 4778 private static final WeekDataCache WEEK_DATA_CACHE = new WeekDataCache(); 4779 4780 /* 4781 * Set this calendar to contain week and weekend data for the given region. 4782 */ setWeekData(String region)4783 private void setWeekData(String region) { 4784 if (region == null) { 4785 region = "001"; 4786 } 4787 WeekData wdata = WEEK_DATA_CACHE.getInstance(region, region); 4788 setWeekData(wdata); 4789 } 4790 4791 /** 4792 * Recompute the time and update the status fields isTimeSet 4793 * and areFieldsSet. Callers should check isTimeSet and only 4794 * call this method if isTimeSet is false. 4795 */ updateTime()4796 private void updateTime() { 4797 computeTime(); 4798 // If we are lenient, we need to recompute the fields to normalize 4799 // the values. Also, if we haven't set all the fields yet (i.e., 4800 // in a newly-created object), we need to fill in the fields. [LIU] 4801 if (isLenient() || !areAllFieldsSet) areFieldsSet = false; 4802 isTimeSet = true; 4803 areFieldsVirtuallySet = false; 4804 } 4805 4806 /** 4807 * Save the state of this object to a stream (i.e., serialize it). 4808 */ writeObject(ObjectOutputStream stream)4809 private void writeObject(ObjectOutputStream stream) 4810 throws IOException 4811 { 4812 // Try to compute the time correctly, for the future (stream 4813 // version 2) in which we don't write out fields[] or isSet[]. 4814 if (!isTimeSet) { 4815 try { 4816 updateTime(); 4817 } 4818 catch (IllegalArgumentException e) {} 4819 } 4820 4821 // Write out the 1.1 FCS object. 4822 stream.defaultWriteObject(); 4823 } 4824 4825 /** 4826 * Reconstitute this object from a stream (i.e., deserialize it). 4827 */ readObject(ObjectInputStream stream)4828 private void readObject(ObjectInputStream stream) 4829 throws IOException, ClassNotFoundException { 4830 4831 stream.defaultReadObject(); 4832 4833 initInternal(); 4834 4835 isTimeSet = true; 4836 areFieldsSet = areAllFieldsSet = false; 4837 areFieldsVirtuallySet = true; // cause fields to be recalculated if requested. 4838 nextStamp = MINIMUM_USER_STAMP; 4839 } 4840 4841 4842 //---------------------------------------------------------------------- 4843 // Time -> Fields 4844 //---------------------------------------------------------------------- 4845 4846 /** 4847 * Converts the current millisecond time value <code>time</code> to 4848 * field values in <code>fields[]</code>. This synchronizes the time 4849 * field values with a new time that is set for the calendar. The time 4850 * is <em>not</em> recomputed first; to recompute the time, then the 4851 * fields, call the <code>complete</code> method. 4852 * @see #complete 4853 */ computeFields()4854 protected void computeFields() { 4855 int offsets[] = new int[2]; 4856 getTimeZone().getOffset(time, false, offsets); 4857 long localMillis = time + offsets[0] + offsets[1]; 4858 4859 // Mark fields as set. Do this before calling handleComputeFields(). 4860 int mask = internalSetMask; 4861 for (int i=0; i<fields.length; ++i) { 4862 if ((mask & 1) == 0) { 4863 stamp[i] = INTERNALLY_SET; 4864 } else { 4865 stamp[i] = UNSET; 4866 } 4867 mask >>= 1; 4868 } 4869 4870 // We used to check for and correct extreme millis values (near 4871 // Long.MIN_VALUE or Long.MAX_VALUE) here. Such values would cause 4872 // overflows from positive to negative (or vice versa) and had to 4873 // be manually tweaked. We no longer need to do this because we 4874 // have limited the range of supported dates to those that have a 4875 // Julian day that fits into an int. This allows us to implement a 4876 // JULIAN_DAY field and also removes some inelegant code. - Liu 4877 // 11/6/00 4878 4879 long days = floorDivide(localMillis, ONE_DAY); 4880 4881 fields[JULIAN_DAY] = (int) days + EPOCH_JULIAN_DAY; 4882 4883 computeGregorianAndDOWFields(fields[JULIAN_DAY]); 4884 4885 // Call framework method to have subclass compute its fields. 4886 // These must include, at a minimum, MONTH, DAY_OF_MONTH, 4887 // EXTENDED_YEAR, YEAR, DAY_OF_YEAR. This method will call internalSet(), 4888 // which will update stamp[]. 4889 handleComputeFields(fields[JULIAN_DAY]); 4890 4891 // Compute week-related fields, based on the subclass-computed 4892 // fields computed by handleComputeFields(). 4893 computeWeekFields(); 4894 4895 // Compute time-related fields. These are indepent of the date and 4896 // of the subclass algorithm. They depend only on the local zone 4897 // wall milliseconds in day. 4898 int millisInDay = (int) (localMillis - (days * ONE_DAY)); 4899 fields[MILLISECONDS_IN_DAY] = millisInDay; 4900 fields[MILLISECOND] = millisInDay % 1000; 4901 millisInDay /= 1000; 4902 fields[SECOND] = millisInDay % 60; 4903 millisInDay /= 60; 4904 fields[MINUTE] = millisInDay % 60; 4905 millisInDay /= 60; 4906 fields[HOUR_OF_DAY] = millisInDay; 4907 fields[AM_PM] = millisInDay / 12; // Assume AM == 0 4908 fields[HOUR] = millisInDay % 12; 4909 fields[ZONE_OFFSET] = offsets[0]; 4910 fields[DST_OFFSET] = offsets[1]; 4911 } 4912 4913 /** 4914 * Compute the Gregorian calendar year, month, and day of month from 4915 * the given Julian day. These values are not stored in fields, but in 4916 * member variables gregorianXxx. Also compute the DAY_OF_WEEK and 4917 * DOW_LOCAL fields. 4918 */ computeGregorianAndDOWFields(int julianDay)4919 private final void computeGregorianAndDOWFields(int julianDay) { 4920 computeGregorianFields(julianDay); 4921 4922 // Compute day of week: JD 0 = Monday 4923 int dow = fields[DAY_OF_WEEK] = julianDayToDayOfWeek(julianDay); 4924 4925 // Calculate 1-based localized day of week 4926 int dowLocal = dow - getFirstDayOfWeek() + 1; 4927 if (dowLocal < 1) { 4928 dowLocal += 7; 4929 } 4930 fields[DOW_LOCAL] = dowLocal; 4931 } 4932 4933 /** 4934 * Compute the Gregorian calendar year, month, and day of month from the 4935 * Julian day. These values are not stored in fields, but in member 4936 * variables gregorianXxx. They are used for time zone computations and by 4937 * subclasses that are Gregorian derivatives. Subclasses may call this 4938 * method to perform a Gregorian calendar millis->fields computation. 4939 * To perform a Gregorian calendar fields->millis computation, call 4940 * computeGregorianMonthStart(). 4941 * @see #computeGregorianMonthStart 4942 */ computeGregorianFields(int julianDay)4943 protected final void computeGregorianFields(int julianDay) { 4944 int year, month, dayOfMonth, dayOfYear; 4945 4946 // The Gregorian epoch day is zero for Monday January 1, year 1. 4947 long gregorianEpochDay = julianDay - JAN_1_1_JULIAN_DAY; 4948 4949 // Here we convert from the day number to the multiple radix 4950 // representation. We use 400-year, 100-year, and 4-year cycles. 4951 // For example, the 4-year cycle has 4 years + 1 leap day; giving 4952 // 1461 == 365*4 + 1 days. 4953 int[] rem = new int[1]; 4954 int n400 = floorDivide(gregorianEpochDay, 146097, rem); // 400-year cycle length 4955 int n100 = floorDivide(rem[0], 36524, rem); // 100-year cycle length 4956 int n4 = floorDivide(rem[0], 1461, rem); // 4-year cycle length 4957 int n1 = floorDivide(rem[0], 365, rem); 4958 year = 400*n400 + 100*n100 + 4*n4 + n1; 4959 dayOfYear = rem[0]; // zero-based day of year 4960 if (n100 == 4 || n1 == 4) { 4961 dayOfYear = 365; // Dec 31 at end of 4- or 400-yr cycle 4962 } else { 4963 ++year; 4964 } 4965 4966 boolean isLeap = ((year&0x3) == 0) && // equiv. to (year%4 == 0) 4967 (year%100 != 0 || year%400 == 0); 4968 4969 int correction = 0; 4970 int march1 = isLeap ? 60 : 59; // zero-based DOY for March 1 4971 if (dayOfYear >= march1) correction = isLeap ? 1 : 2; 4972 month = (12 * (dayOfYear + correction) + 6) / 367; // zero-based month 4973 dayOfMonth = dayOfYear - 4974 GREGORIAN_MONTH_COUNT[month][isLeap?3:2] + 1; // one-based DOM 4975 4976 gregorianYear = year; 4977 gregorianMonth = month; // 0-based already 4978 gregorianDayOfMonth = dayOfMonth; // 1-based already 4979 gregorianDayOfYear = dayOfYear + 1; // Convert from 0-based to 1-based 4980 } 4981 4982 /** 4983 * Compute the fields WEEK_OF_YEAR, YEAR_WOY, WEEK_OF_MONTH, 4984 * DAY_OF_WEEK_IN_MONTH, and DOW_LOCAL from EXTENDED_YEAR, YEAR, 4985 * DAY_OF_WEEK, and DAY_OF_YEAR. The latter fields are computed by the 4986 * subclass based on the calendar system. 4987 * 4988 * <p>The YEAR_WOY field is computed simplistically. It is equal to YEAR 4989 * most of the time, but at the year boundary it may be adjusted to YEAR-1 4990 * or YEAR+1 to reflect the overlap of a week into an adjacent year. In 4991 * this case, a simple increment or decrement is performed on YEAR, even 4992 * though this may yield an invalid YEAR value. For instance, if the YEAR 4993 * is part of a calendar system with an N-year cycle field CYCLE, then 4994 * incrementing the YEAR may involve incrementing CYCLE and setting YEAR 4995 * back to 0 or 1. This is not handled by this code, and in fact cannot be 4996 * simply handled without having subclasses define an entire parallel set of 4997 * fields for fields larger than or equal to a year. This additional 4998 * complexity is not warranted, since the intention of the YEAR_WOY field is 4999 * to support ISO 8601 notation, so it will typically be used with a 5000 * proleptic Gregorian calendar, which has no field larger than a year. 5001 */ computeWeekFields()5002 private final void computeWeekFields() { 5003 int eyear = fields[EXTENDED_YEAR]; 5004 int dayOfWeek = fields[DAY_OF_WEEK]; 5005 int dayOfYear = fields[DAY_OF_YEAR]; 5006 5007 // WEEK_OF_YEAR start 5008 // Compute the week of the year. For the Gregorian calendar, valid week 5009 // numbers run from 1 to 52 or 53, depending on the year, the first day 5010 // of the week, and the minimal days in the first week. For other 5011 // calendars, the valid range may be different -- it depends on the year 5012 // length. Days at the start of the year may fall into the last week of 5013 // the previous year; days at the end of the year may fall into the 5014 // first week of the next year. ASSUME that the year length is less than 5015 // 7000 days. 5016 int yearOfWeekOfYear = eyear; 5017 int relDow = (dayOfWeek + 7 - getFirstDayOfWeek()) % 7; // 0..6 5018 int relDowJan1 = (dayOfWeek - dayOfYear + 7001 - getFirstDayOfWeek()) % 7; // 0..6 5019 int woy = (dayOfYear - 1 + relDowJan1) / 7; // 0..53 5020 if ((7 - relDowJan1) >= getMinimalDaysInFirstWeek()) { 5021 ++woy; 5022 } 5023 5024 // Adjust for weeks at the year end that overlap into the previous or 5025 // next calendar year. 5026 if (woy == 0) { 5027 // We are the last week of the previous year. 5028 // Check to see if we are in the last week; if so, we need 5029 // to handle the case in which we are the first week of the 5030 // next year. 5031 5032 int prevDoy = dayOfYear + handleGetYearLength(eyear - 1); 5033 woy = weekNumber(prevDoy, dayOfWeek); 5034 yearOfWeekOfYear--; 5035 } else { 5036 int lastDoy = handleGetYearLength(eyear); 5037 // Fast check: For it to be week 1 of the next year, the DOY 5038 // must be on or after L-5, where L is yearLength(), then it 5039 // cannot possibly be week 1 of the next year: 5040 // L-5 L 5041 // doy: 359 360 361 362 363 364 365 001 5042 // dow: 1 2 3 4 5 6 7 5043 if (dayOfYear >= (lastDoy - 5)) { 5044 int lastRelDow = (relDow + lastDoy - dayOfYear) % 7; 5045 if (lastRelDow < 0) { 5046 lastRelDow += 7; 5047 } 5048 if (((6 - lastRelDow) >= getMinimalDaysInFirstWeek()) && 5049 ((dayOfYear + 7 - relDow) > lastDoy)) { 5050 woy = 1; 5051 yearOfWeekOfYear++; 5052 } 5053 } 5054 } 5055 fields[WEEK_OF_YEAR] = woy; 5056 fields[YEAR_WOY] = yearOfWeekOfYear; 5057 // WEEK_OF_YEAR end 5058 5059 int dayOfMonth = fields[DAY_OF_MONTH]; 5060 fields[WEEK_OF_MONTH] = weekNumber(dayOfMonth, dayOfWeek); 5061 fields[DAY_OF_WEEK_IN_MONTH] = (dayOfMonth-1) / 7 + 1; 5062 } 5063 5064 //---------------------------------------------------------------------- 5065 // Fields -> Time 5066 //---------------------------------------------------------------------- 5067 5068 /** 5069 * Value to OR against resolve table field values for remapping. 5070 * @see #resolveFields 5071 */ 5072 protected static final int RESOLVE_REMAP = 32; 5073 // A power of 2 greater than or equal to MAX_FIELD_COUNT 5074 5075 // Default table for day in year 5076 static final int[][][] DATE_PRECEDENCE = { 5077 { 5078 { DAY_OF_MONTH }, 5079 { WEEK_OF_YEAR, DAY_OF_WEEK }, 5080 { WEEK_OF_MONTH, DAY_OF_WEEK }, 5081 { DAY_OF_WEEK_IN_MONTH, DAY_OF_WEEK }, 5082 { WEEK_OF_YEAR, DOW_LOCAL }, 5083 { WEEK_OF_MONTH, DOW_LOCAL }, 5084 { DAY_OF_WEEK_IN_MONTH, DOW_LOCAL }, 5085 { DAY_OF_YEAR }, 5086 { RESOLVE_REMAP | DAY_OF_MONTH, YEAR }, // if YEAR is set over YEAR_WOY use DAY_OF_MONTH 5087 { RESOLVE_REMAP | WEEK_OF_YEAR, YEAR_WOY }, // if YEAR_WOY is set, calc based on WEEK_OF_YEAR 5088 }, 5089 { 5090 { WEEK_OF_YEAR }, 5091 { WEEK_OF_MONTH }, 5092 { DAY_OF_WEEK_IN_MONTH }, 5093 { RESOLVE_REMAP | DAY_OF_WEEK_IN_MONTH, DAY_OF_WEEK }, 5094 { RESOLVE_REMAP | DAY_OF_WEEK_IN_MONTH, DOW_LOCAL }, 5095 }, 5096 }; 5097 5098 static final int[][][] DOW_PRECEDENCE = { 5099 { 5100 { DAY_OF_WEEK }, 5101 { DOW_LOCAL }, 5102 }, 5103 }; 5104 5105 /** 5106 * Given a precedence table, return the newest field combination in 5107 * the table, or -1 if none is found. 5108 * 5109 * <p>The precedence table is a 3-dimensional array of integers. It 5110 * may be thought of as an array of groups. Each group is an array of 5111 * lines. Each line is an array of field numbers. Within a line, if 5112 * all fields are set, then the time stamp of the line is taken to be 5113 * the stamp of the most recently set field. If any field of a line is 5114 * unset, then the line fails to match. Within a group, the line with 5115 * the newest time stamp is selected. The first field of the line is 5116 * returned to indicate which line matched. 5117 * 5118 * <p>In some cases, it may be desirable to map a line to field that 5119 * whose stamp is NOT examined. For example, if the best field is 5120 * DAY_OF_WEEK then the DAY_OF_WEEK_IN_MONTH algorithm may be used. In 5121 * order to do this, insert the value <code>REMAP_RESOLVE | F</code> at 5122 * the start of the line, where <code>F</code> is the desired return 5123 * field value. This field will NOT be examined; it only determines 5124 * the return value if the other fields in the line are the newest. 5125 * 5126 * <p>If all lines of a group contain at least one unset field, then no 5127 * line will match, and the group as a whole will fail to match. In 5128 * that case, the next group will be processed. If all groups fail to 5129 * match, then -1 is returned. 5130 */ resolveFields(int[][][] precedenceTable)5131 protected int resolveFields(int[][][] precedenceTable) { 5132 int bestField = -1; 5133 int tempBestField; 5134 for (int g=0; g<precedenceTable.length && bestField < 0; ++g) { 5135 int[][] group = precedenceTable[g]; 5136 int bestStamp = UNSET; 5137 linesInGroup: 5138 for (int l=0; l<group.length; ++l) { 5139 int[] line= group[l]; 5140 int lineStamp = UNSET; 5141 // Skip over first entry if it is negative 5142 for (int i=(line[0]>=RESOLVE_REMAP)?1:0; i<line.length; ++i) { 5143 int s = stamp[line[i]]; 5144 // If any field is unset then don't use this line 5145 if (s == UNSET) { 5146 continue linesInGroup; 5147 } else { 5148 lineStamp = Math.max(lineStamp, s); 5149 } 5150 } 5151 // Record new maximum stamp & field no. 5152 if (lineStamp > bestStamp) { 5153 tempBestField = line[0]; // First field refers to entire line 5154 if (tempBestField >= RESOLVE_REMAP) { 5155 tempBestField &= (RESOLVE_REMAP-1); 5156 // This check is needed to resolve some issues with UCAL_YEAR precedence mapping 5157 if (tempBestField != DATE || (stamp[WEEK_OF_MONTH] < stamp[tempBestField])) { 5158 bestField = tempBestField; 5159 } 5160 } else { 5161 bestField = tempBestField; 5162 } 5163 5164 if (bestField == tempBestField) { 5165 bestStamp = lineStamp; 5166 } 5167 } 5168 } 5169 } 5170 return (bestField>=RESOLVE_REMAP)?(bestField&(RESOLVE_REMAP-1)):bestField; 5171 } 5172 5173 /** 5174 * Returns the newest stamp of a given range of fields. 5175 */ newestStamp(int first, int last, int bestStampSoFar)5176 protected int newestStamp(int first, int last, int bestStampSoFar) { 5177 int bestStamp = bestStampSoFar; 5178 for (int i=first; i<=last; ++i) { 5179 if (stamp[i] > bestStamp) { 5180 bestStamp = stamp[i]; 5181 } 5182 } 5183 return bestStamp; 5184 } 5185 5186 /** 5187 * Returns the timestamp of a field. 5188 */ getStamp(int field)5189 protected final int getStamp(int field) { 5190 return stamp[field]; 5191 } 5192 5193 /** 5194 * Returns the field that is newer, either defaultField, or 5195 * alternateField. If neither is newer or neither is set, return defaultField. 5196 */ newerField(int defaultField, int alternateField)5197 protected int newerField(int defaultField, int alternateField) { 5198 if (stamp[alternateField] > stamp[defaultField]) { 5199 return alternateField; 5200 } 5201 return defaultField; 5202 } 5203 5204 /** 5205 * Ensure that each field is within its valid range by calling {@link 5206 * #validateField(int)} on each field that has been set. This method 5207 * should only be called if this calendar is not lenient. 5208 * @see #isLenient 5209 * @see #validateField(int) 5210 */ validateFields()5211 protected void validateFields() { 5212 for (int field = 0; field < fields.length; field++) { 5213 if (stamp[field] >= MINIMUM_USER_STAMP) { 5214 validateField(field); 5215 } 5216 } 5217 } 5218 5219 /** 5220 * Validate a single field of this calendar. Subclasses should 5221 * override this method to validate any calendar-specific fields. 5222 * Generic fields can be handled by 5223 * <code>Calendar.validateField()</code>. 5224 * @see #validateField(int, int, int) 5225 */ validateField(int field)5226 protected void validateField(int field) { 5227 int y; 5228 switch (field) { 5229 case DAY_OF_MONTH: 5230 y = handleGetExtendedYear(); 5231 validateField(field, 1, handleGetMonthLength(y, internalGet(MONTH))); 5232 break; 5233 case DAY_OF_YEAR: 5234 y = handleGetExtendedYear(); 5235 validateField(field, 1, handleGetYearLength(y)); 5236 break; 5237 case DAY_OF_WEEK_IN_MONTH: 5238 if (internalGet(field) == 0) { 5239 throw new IllegalArgumentException("DAY_OF_WEEK_IN_MONTH cannot be zero"); 5240 } 5241 validateField(field, getMinimum(field), getMaximum(field)); 5242 break; 5243 default: 5244 validateField(field, getMinimum(field), getMaximum(field)); 5245 break; 5246 } 5247 } 5248 5249 /** 5250 * Validate a single field of this calendar given its minimum and 5251 * maximum allowed value. If the field is out of range, throw a 5252 * descriptive <code>IllegalArgumentException</code>. Subclasses may 5253 * use this method in their implementation of {@link 5254 * #validateField(int)}. 5255 */ validateField(int field, int min, int max)5256 protected final void validateField(int field, int min, int max) { 5257 int value = fields[field]; 5258 if (value < min || value > max) { 5259 throw new IllegalArgumentException(fieldName(field) + 5260 '=' + value + ", valid range=" + 5261 min + ".." + max); 5262 } 5263 } 5264 5265 /** 5266 * Converts the current field values in <code>fields[]</code> to the 5267 * millisecond time value <code>time</code>. 5268 */ computeTime()5269 protected void computeTime() { 5270 if (!isLenient()) { 5271 validateFields(); 5272 } 5273 5274 // Compute the Julian day 5275 int julianDay = computeJulianDay(); 5276 5277 long millis = julianDayToMillis(julianDay); 5278 5279 int millisInDay; 5280 5281 // We only use MILLISECONDS_IN_DAY if it has been set by the user. 5282 // This makes it possible for the caller to set the calendar to a 5283 // time and call clear(MONTH) to reset the MONTH to January. This 5284 // is legacy behavior. Without this, clear(MONTH) has no effect, 5285 // since the internally set JULIAN_DAY is used. 5286 if (stamp[MILLISECONDS_IN_DAY] >= MINIMUM_USER_STAMP && 5287 newestStamp(AM_PM, MILLISECOND, UNSET) <= stamp[MILLISECONDS_IN_DAY]) { 5288 millisInDay = internalGet(MILLISECONDS_IN_DAY); 5289 } else { 5290 millisInDay = computeMillisInDay(); 5291 } 5292 5293 if (stamp[ZONE_OFFSET] >= MINIMUM_USER_STAMP || 5294 stamp[DST_OFFSET] >= MINIMUM_USER_STAMP) { 5295 time = millis + millisInDay - (internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET)); 5296 } else { 5297 // Compute the time zone offset and DST offset. There are two potential 5298 // ambiguities here. We'll assume a 2:00 am (wall time) switchover time 5299 // for discussion purposes here. 5300 // 5301 // 1. The positive offset change such as transition into DST. 5302 // Here, a designated time of 2:00 am - 2:59 am does not actually exist. 5303 // For this case, skippedWallTime option specifies the behavior. 5304 // For example, 2:30 am is interpreted as; 5305 // - WALLTIME_LAST(default): 3:30 am (DST) (interpreting 2:30 am as 31 minutes after 1:59 am (STD)) 5306 // - WALLTIME_FIRST: 1:30 am (STD) (interpreting 2:30 am as 30 minutes before 3:00 am (DST)) 5307 // - WALLTIME_NEXT_VALID: 3:00 am (DST) (next valid time after 2:30 am on a wall clock) 5308 // 2. The negative offset change such as transition out of DST. 5309 // Here, a designated time of 1:00 am - 1:59 am can be in standard or DST. Both are valid 5310 // representations (the rep jumps from 1:59:59 DST to 1:00:00 Std). 5311 // For this case, repeatedWallTime option specifies the behavior. 5312 // For example, 1:30 am is interpreted as; 5313 // - WALLTIME_LAST(default): 1:30 am (STD) - latter occurrence 5314 // - WALLTIME_FIRST: 1:30 am (DST) - former occurrence 5315 // 5316 // In addition to above, when calendar is strict (not default), wall time falls into 5317 // the skipped time range will be processed as an error case. 5318 // 5319 // These special cases are mostly handled in #computeZoneOffset(long), except WALLTIME_NEXT_VALID 5320 // at positive offset change. The protected method computeZoneOffset(long) is exposed to Calendar 5321 // subclass implementations and marked as @stable. Strictly speaking, WALLTIME_NEXT_VALID 5322 // should be also handled in the same place, but we cannot change the code flow without deprecating 5323 // the protected method. 5324 // 5325 // We use the TimeZone object, unless the user has explicitly set the ZONE_OFFSET 5326 // or DST_OFFSET fields; then we use those fields. 5327 5328 if (!lenient || skippedWallTime == WALLTIME_NEXT_VALID) { 5329 // When strict, invalidate a wall time falls into a skipped wall time range. 5330 // When lenient and skipped wall time option is WALLTIME_NEXT_VALID, 5331 // the result time will be adjusted to the next valid time (on wall clock). 5332 int zoneOffset = computeZoneOffset(millis, millisInDay); 5333 long tmpTime = millis + millisInDay - zoneOffset; 5334 5335 int zoneOffset1 = zone.getOffset(tmpTime); 5336 5337 // zoneOffset != zoneOffset1 only when the given wall time fall into 5338 // a skipped wall time range caused by positive zone offset transition. 5339 if (zoneOffset != zoneOffset1) { 5340 if (!lenient) { 5341 throw new IllegalArgumentException("The specified wall time does not exist due to time zone offset transition."); 5342 } 5343 5344 assert skippedWallTime == WALLTIME_NEXT_VALID : skippedWallTime; 5345 // Adjust time to the next valid wall clock time. 5346 // At this point, tmpTime is on or after the zone offset transition causing 5347 // the skipped time range. 5348 Long immediatePrevTransition = getImmediatePreviousZoneTransition(tmpTime); 5349 if (immediatePrevTransition == null) { 5350 throw new RuntimeException("Could not locate a time zone transition before " + tmpTime); 5351 } 5352 time = immediatePrevTransition; 5353 } else { 5354 time = tmpTime; 5355 } 5356 } else { 5357 time = millis + millisInDay - computeZoneOffset(millis, millisInDay); 5358 } 5359 } 5360 } 5361 5362 /** 5363 * Find the previous zone transtion near the given time. 5364 * 5365 * @param base The base time, inclusive. 5366 * @return The time of the previous transition, or null if not found. 5367 */ getImmediatePreviousZoneTransition(long base)5368 private Long getImmediatePreviousZoneTransition(long base) { 5369 Long transitionTime = null; 5370 5371 if (zone instanceof BasicTimeZone) { 5372 TimeZoneTransition transition = ((BasicTimeZone) zone).getPreviousTransition(base, true); 5373 if (transition != null) { 5374 transitionTime = transition.getTime(); 5375 } 5376 } else { 5377 // Usually, it is enough to check past one hour because such transition is most 5378 // likely +1 hour shift. However, there is an example jumped +24 hour in the tz database. 5379 transitionTime = getPreviousZoneTransitionTime(zone, base, 2 * 60 * 60 * 1000); // check last 2 hours 5380 if (transitionTime == null) { 5381 transitionTime = getPreviousZoneTransitionTime(zone, base, 30 * 60 * 60 * 1000); // try last 30 hours 5382 } 5383 } 5384 return transitionTime; 5385 } 5386 5387 /** 5388 * Find the previous zone transition within the specified duration. 5389 * Note: This method is only used when TimeZone is NOT a BasicTimeZone. 5390 * @param tz The time zone. 5391 * @param base The base time, inclusive. 5392 * @param duration The range of time evaluated. 5393 * @return The time of the previous zone transition, or null if not available. 5394 */ getPreviousZoneTransitionTime(TimeZone tz, long base, long duration)5395 private static Long getPreviousZoneTransitionTime(TimeZone tz, long base, long duration) { 5396 assert duration > 0; 5397 5398 long upper = base; 5399 long lower = base - duration - 1; 5400 int offsetU = tz.getOffset(upper); 5401 int offsetL = tz.getOffset(lower); 5402 if (offsetU == offsetL) { 5403 return null; 5404 } 5405 return findPreviousZoneTransitionTime(tz, offsetU, upper, lower); 5406 } 5407 5408 /** 5409 * The time units used by {@link #findPreviousZoneTransitionTime(TimeZone, int, long, long)} 5410 * for optimizing transition time binary search. 5411 */ 5412 private static final int[] FIND_ZONE_TRANSITION_TIME_UNITS = { 5413 60*60*1000, // 1 hour 5414 30*60*1000, // 30 minutes 5415 60*1000, // 1 minute 5416 1000, // 1 second 5417 }; 5418 5419 /** 5420 * Implementing binary search for zone transtion detection, used by {@link #getPreviousZoneTransitionTime(TimeZone, long, long)} 5421 * @param tz The time zone. 5422 * @param upperOffset The zone offset at <code>upper</code> 5423 * @param upper The upper bound, inclusive. 5424 * @param lower The lower bound, exclusive. 5425 * @return The time of the previous zone transition, or null if not available. 5426 */ findPreviousZoneTransitionTime(TimeZone tz, int upperOffset, long upper, long lower)5427 private static Long findPreviousZoneTransitionTime(TimeZone tz, int upperOffset, long upper, long lower) { 5428 boolean onUnitTime = false; 5429 long mid = 0; 5430 5431 for (int unit : FIND_ZONE_TRANSITION_TIME_UNITS) { 5432 long lunits = lower/unit; 5433 long uunits = upper/unit; 5434 if (uunits > lunits) { 5435 mid = ((lunits + uunits + 1) >>> 1) * unit; 5436 onUnitTime = true; 5437 break; 5438 } 5439 } 5440 5441 int midOffset; 5442 if (!onUnitTime) { 5443 mid = (upper + lower) >>> 1; 5444 } 5445 5446 if (onUnitTime) { 5447 if (mid != upper) { 5448 midOffset = tz.getOffset(mid); 5449 if (midOffset != upperOffset) { 5450 return findPreviousZoneTransitionTime(tz, upperOffset, upper, mid); 5451 } 5452 upper = mid; 5453 } 5454 // check mid-1 5455 mid--; 5456 } else { 5457 mid = (upper + lower) >>> 1; 5458 } 5459 5460 if (mid == lower) { 5461 return Long.valueOf(upper); 5462 } 5463 midOffset = tz.getOffset(mid); 5464 if (midOffset != upperOffset) { 5465 if (onUnitTime) { 5466 return Long.valueOf(upper); 5467 } 5468 return findPreviousZoneTransitionTime(tz, upperOffset, upper, mid); 5469 } 5470 return findPreviousZoneTransitionTime(tz, upperOffset, mid, lower); 5471 } 5472 5473 /** 5474 * Compute the milliseconds in the day from the fields. This is a 5475 * value from 0 to 23:59:59.999 inclusive, unless fields are out of 5476 * range, in which case it can be an arbitrary value. This value 5477 * reflects local zone wall time. 5478 * @deprecated This method suffers from a potential integer overflow and may be removed or 5479 * changed in a future release. See <a href="http://bugs.icu-project.org/trac/ticket/11632"> 5480 * ICU ticket #11632</a> for details. 5481 */ computeMillisInDay()5482 protected int computeMillisInDay() { 5483 // Do the time portion of the conversion. 5484 5485 int millisInDay = 0; 5486 5487 // Find the best set of fields specifying the time of day. There 5488 // are only two possibilities here; the HOUR_OF_DAY or the 5489 // AM_PM and the HOUR. 5490 int hourOfDayStamp = stamp[HOUR_OF_DAY]; 5491 int hourStamp = Math.max(stamp[HOUR], stamp[AM_PM]); 5492 int bestStamp = (hourStamp > hourOfDayStamp) ? hourStamp : hourOfDayStamp; 5493 5494 // Hours 5495 if (bestStamp != UNSET) { 5496 if (bestStamp == hourOfDayStamp) { 5497 // Don't normalize here; let overflow bump into the next period. 5498 // This is consistent with how we handle other fields. 5499 millisInDay += internalGet(HOUR_OF_DAY); 5500 } else { 5501 // Don't normalize here; let overflow bump into the next period. 5502 // This is consistent with how we handle other fields. 5503 millisInDay += internalGet(HOUR); 5504 millisInDay += 12 * internalGet(AM_PM); // Default works for unset AM_PM 5505 } 5506 } 5507 5508 // We use the fact that unset == 0; we start with millisInDay 5509 // == HOUR_OF_DAY. 5510 millisInDay *= 60; 5511 millisInDay += internalGet(MINUTE); // now have minutes 5512 millisInDay *= 60; 5513 millisInDay += internalGet(SECOND); // now have seconds 5514 millisInDay *= 1000; 5515 millisInDay += internalGet(MILLISECOND); // now have millis 5516 5517 return millisInDay; 5518 } 5519 5520 /** 5521 * This method can assume EXTENDED_YEAR has been set. 5522 * @param millis milliseconds of the date fields (local midnight millis) 5523 * @param millisInDay milliseconds of the time fields; may be out 5524 * or range. 5525 * @return total zone offset (raw + DST) for the given moment 5526 * @deprecated This method suffers from a potential integer overflow and may be removed or 5527 * changed in a future release. See <a href="http://bugs.icu-project.org/trac/ticket/11632"> 5528 * ICU ticket #11632</a> for details. 5529 */ computeZoneOffset(long millis, int millisInDay)5530 protected int computeZoneOffset(long millis, int millisInDay) { 5531 int[] offsets = new int[2]; 5532 long wall = millis + millisInDay; 5533 if (zone instanceof BasicTimeZone) { 5534 int duplicatedTimeOpt = (repeatedWallTime == WALLTIME_FIRST) ? BasicTimeZone.LOCAL_FORMER : BasicTimeZone.LOCAL_LATTER; 5535 int nonExistingTimeOpt = (skippedWallTime == WALLTIME_FIRST) ? BasicTimeZone.LOCAL_LATTER : BasicTimeZone.LOCAL_FORMER; 5536 ((BasicTimeZone)zone).getOffsetFromLocal(wall, nonExistingTimeOpt, duplicatedTimeOpt, offsets); 5537 } else { 5538 // By default, TimeZone#getOffset behaves WALLTIME_LAST for both. 5539 zone.getOffset(wall, true, offsets); 5540 5541 boolean sawRecentNegativeShift = false; 5542 if (repeatedWallTime == WALLTIME_FIRST) { 5543 // Check if the given wall time falls into repeated time range 5544 long tgmt = wall - (offsets[0] + offsets[1]); 5545 5546 // Any negative zone transition within last 6 hours? 5547 // Note: The maximum historic negative zone transition is -3 hours in the tz database. 5548 // 6 hour window would be sufficient for this purpose. 5549 int offsetBefore6 = zone.getOffset(tgmt - 6*60*60*1000); 5550 int offsetDelta = (offsets[0] + offsets[1]) - offsetBefore6; 5551 5552 assert offsetDelta > -6*60*60*1000 : offsetDelta; 5553 if (offsetDelta < 0) { 5554 sawRecentNegativeShift = true; 5555 // Negative shift within last 6 hours. When WALLTIME_FIRST is used and the given wall time falls 5556 // into the repeated time range, use offsets before the transition. 5557 // Note: If it does not fall into the repeated time range, offsets remain unchanged below. 5558 zone.getOffset(wall + offsetDelta, true, offsets); 5559 } 5560 } 5561 if (!sawRecentNegativeShift && skippedWallTime == WALLTIME_FIRST) { 5562 // When skipped wall time option is WALLTIME_FIRST, 5563 // recalculate offsets from the resolved time (non-wall). 5564 // When the given wall time falls into skipped wall time, 5565 // the offsets will be based on the zone offsets AFTER 5566 // the transition (which means, earliest possibe interpretation). 5567 long tgmt = wall - (offsets[0] + offsets[1]); 5568 zone.getOffset(tgmt, false, offsets); 5569 } 5570 } 5571 return offsets[0] + offsets[1]; 5572 } 5573 5574 /** 5575 * Compute the Julian day number as specified by this calendar's fields. 5576 */ computeJulianDay()5577 protected int computeJulianDay() { 5578 5579 // We want to see if any of the date fields is newer than the 5580 // JULIAN_DAY. If not, then we use JULIAN_DAY. If so, then we do 5581 // the normal resolution. We only use JULIAN_DAY if it has been 5582 // set by the user. This makes it possible for the caller to set 5583 // the calendar to a time and call clear(MONTH) to reset the MONTH 5584 // to January. This is legacy behavior. Without this, 5585 // clear(MONTH) has no effect, since the internally set JULIAN_DAY 5586 // is used. 5587 if (stamp[JULIAN_DAY] >= MINIMUM_USER_STAMP) { 5588 int bestStamp = newestStamp(ERA, DAY_OF_WEEK_IN_MONTH, UNSET); 5589 bestStamp = newestStamp(YEAR_WOY, EXTENDED_YEAR, bestStamp); 5590 if (bestStamp <= stamp[JULIAN_DAY]) { 5591 return internalGet(JULIAN_DAY); 5592 } 5593 } 5594 5595 int bestField = resolveFields(getFieldResolutionTable()); 5596 if (bestField < 0) { 5597 bestField = DAY_OF_MONTH; 5598 } 5599 5600 return handleComputeJulianDay(bestField); 5601 } 5602 5603 /** 5604 * Returns the field resolution array for this calendar. Calendars that 5605 * define additional fields or change the semantics of existing fields 5606 * should override this method to adjust the field resolution semantics 5607 * accordingly. Other subclasses should not override this method. 5608 * @see #resolveFields 5609 */ getFieldResolutionTable()5610 protected int[][][] getFieldResolutionTable() { 5611 return DATE_PRECEDENCE; 5612 } 5613 5614 /** 5615 * Returns the Julian day number of day before the first day of the 5616 * given month in the given extended year. Subclasses should override 5617 * this method to implement their calendar system. 5618 * @param eyear the extended year 5619 * @param month the zero-based month, or 0 if useMonth is false 5620 * @param useMonth if false, compute the day before the first day of 5621 * the given year, otherwise, compute the day before the first day of 5622 * the given month 5623 * @return the Julian day number of the day before the first 5624 * day of the given month and year 5625 */ handleComputeMonthStart(int eyear, int month, boolean useMonth)5626 abstract protected int handleComputeMonthStart(int eyear, int month, 5627 boolean useMonth); 5628 5629 /** 5630 * Returns the extended year defined by the current fields. This will 5631 * use the EXTENDED_YEAR field or the YEAR and supra-year fields (such 5632 * as ERA) specific to the calendar system, depending on which set of 5633 * fields is newer. 5634 * @return the extended year 5635 */ handleGetExtendedYear()5636 abstract protected int handleGetExtendedYear(); 5637 5638 // (The following method is not called because all existing subclasses 5639 // override it. 2003-06-11 ICU 2.6 Alan) 5640 ///CLOVER:OFF 5641 /** 5642 * Returns the number of days in the given month of the given extended 5643 * year of this calendar system. Subclasses should override this 5644 * method if they can provide a more correct or more efficient 5645 * implementation than the default implementation in Calendar. 5646 */ handleGetMonthLength(int extendedYear, int month)5647 protected int handleGetMonthLength(int extendedYear, int month) { 5648 return handleComputeMonthStart(extendedYear, month+1, true) - 5649 handleComputeMonthStart(extendedYear, month, true); 5650 } 5651 ///CLOVER:ON 5652 5653 /** 5654 * Returns the number of days in the given extended year of this 5655 * calendar system. Subclasses should override this method if they can 5656 * provide a more correct or more efficient implementation than the 5657 * default implementation in Calendar. 5658 */ handleGetYearLength(int eyear)5659 protected int handleGetYearLength(int eyear) { 5660 return handleComputeMonthStart(eyear+1, 0, false) - 5661 handleComputeMonthStart(eyear, 0, false); 5662 } 5663 5664 /** 5665 * Subclasses that use additional fields beyond those defined in 5666 * <code>Calendar</code> should override this method to return an 5667 * <code>int[]</code> array of the appropriate length. The length 5668 * must be at least <code>BASE_FIELD_COUNT</code> and no more than 5669 * <code>MAX_FIELD_COUNT</code>. 5670 */ handleCreateFields()5671 protected int[] handleCreateFields() { 5672 return new int[BASE_FIELD_COUNT]; 5673 } 5674 5675 /** 5676 * Subclasses may override this. 5677 * Called by handleComputeJulianDay. Returns the default month (0-based) for the year, 5678 * taking year and era into account. Defaults to 0 (JANUARY) for Gregorian. 5679 * @param extendedYear the extendedYear, as returned by handleGetExtendedYear 5680 * @return the default month 5681 * @see #MONTH 5682 * @hide draft / provisional / internal are hidden on Android 5683 */ getDefaultMonthInYear(int extendedYear)5684 protected int getDefaultMonthInYear(int extendedYear) { 5685 return Calendar.JANUARY; 5686 } 5687 5688 /** 5689 * Subclasses may override this. 5690 * Called by handleComputeJulianDay. Returns the default day (1-based) for the month, 5691 * taking currently-set year and era into account. Defaults to 1 for Gregorian. 5692 * @param extendedYear the extendedYear, as returned by handleGetExtendedYear 5693 * @param month the month, as returned by getDefaultMonthInYear 5694 * @return the default day of the month 5695 * @see #DAY_OF_MONTH 5696 * @hide draft / provisional / internal are hidden on Android 5697 */ getDefaultDayInMonth(int extendedYear, int month)5698 protected int getDefaultDayInMonth(int extendedYear, int month) { 5699 return 1; 5700 } 5701 5702 5703 /** 5704 * Subclasses may override this. This method calls 5705 * handleGetMonthLength() to obtain the calendar-specific month 5706 * length. 5707 */ handleComputeJulianDay(int bestField)5708 protected int handleComputeJulianDay(int bestField) { 5709 5710 boolean useMonth = (bestField == DAY_OF_MONTH || 5711 bestField == WEEK_OF_MONTH || 5712 bestField == DAY_OF_WEEK_IN_MONTH); 5713 5714 int year; 5715 5716 if (bestField == WEEK_OF_YEAR) { 5717 // Nota Bene! It is critical that YEAR_WOY be used as the year here, if it is 5718 // set. Otherwise, when WOY is the best field, the year may be wrong at the 5719 // extreme limits of the year. If YEAR_WOY is not set then it will fall back. 5720 // TODO: Should resolveField(YEAR_PRECEDENCE) be brought to bear? 5721 year = internalGet(YEAR_WOY, handleGetExtendedYear()); 5722 } else { 5723 year = handleGetExtendedYear(); 5724 } 5725 5726 internalSet(EXTENDED_YEAR, year); 5727 5728 int month = useMonth ? internalGet(MONTH, getDefaultMonthInYear(year)) : 0; 5729 5730 // Get the Julian day of the day BEFORE the start of this year. 5731 // If useMonth is true, get the day before the start of the month. 5732 int julianDay = handleComputeMonthStart(year, month, useMonth); 5733 5734 if (bestField == DAY_OF_MONTH) { 5735 if(isSet(DAY_OF_MONTH)) { 5736 return julianDay + internalGet(DAY_OF_MONTH, getDefaultDayInMonth(year, month)); 5737 } else { 5738 return julianDay + getDefaultDayInMonth(year, month); 5739 } 5740 } 5741 5742 if (bestField == DAY_OF_YEAR) { 5743 return julianDay + internalGet(DAY_OF_YEAR); 5744 } 5745 5746 int firstDOW = getFirstDayOfWeek(); // Localized fdw 5747 5748 // At this point julianDay is the 0-based day BEFORE the first day of 5749 // January 1, year 1 of the given calendar. If julianDay == 0, it 5750 // specifies (Jan. 1, 1) - 1, in whatever calendar we are using (Julian 5751 // or Gregorian). 5752 5753 // At this point we need to process the WEEK_OF_MONTH or 5754 // WEEK_OF_YEAR, which are similar, or the DAY_OF_WEEK_IN_MONTH. 5755 // First, perform initial shared computations. These locate the 5756 // first week of the period. 5757 5758 // Get the 0-based localized DOW of day one of the month or year. 5759 // Valid range 0..6. 5760 int first = julianDayToDayOfWeek(julianDay + 1) - firstDOW; 5761 if (first < 0) { 5762 first += 7; 5763 } 5764 5765 // Get zero-based localized DOW, valid range 0..6. This is the DOW 5766 // we are looking for. 5767 int dowLocal = 0; 5768 switch (resolveFields(DOW_PRECEDENCE)) { 5769 case DAY_OF_WEEK: 5770 dowLocal = internalGet(DAY_OF_WEEK) - firstDOW; 5771 break; 5772 case DOW_LOCAL: 5773 dowLocal = internalGet(DOW_LOCAL) - 1; 5774 break; 5775 } 5776 dowLocal = dowLocal % 7; 5777 if (dowLocal < 0) { 5778 dowLocal += 7; 5779 } 5780 5781 // Find the first target DOW (dowLocal) in the month or year. 5782 // Actually, it may be just before the first of the month or year. 5783 // It will be an integer from -5..7. 5784 int date = 1 - first + dowLocal; 5785 5786 if (bestField == DAY_OF_WEEK_IN_MONTH) { 5787 5788 // Adjust the target DOW to be in the month or year. 5789 if (date < 1) { 5790 date += 7; 5791 } 5792 5793 // The only trickiness occurs if the day-of-week-in-month is 5794 // negative. 5795 int dim = internalGet(DAY_OF_WEEK_IN_MONTH, 1); 5796 if (dim >= 0) { 5797 date += 7*(dim - 1); 5798 5799 } else { 5800 // Move date to the last of this day-of-week in this month, 5801 // then back up as needed. If dim==-1, we don't back up at 5802 // all. If dim==-2, we back up once, etc. Don't back up 5803 // past the first of the given day-of-week in this month. 5804 // Note that we handle -2, -3, etc. correctly, even though 5805 // values < -1 are technically disallowed. 5806 int m = internalGet(MONTH, JANUARY); 5807 int monthLength = handleGetMonthLength(year, m); 5808 date += ((monthLength - date) / 7 + dim + 1) * 7; 5809 } 5810 } else { 5811 // assert(bestField == WEEK_OF_MONTH || bestField == WEEK_OF_YEAR) 5812 5813 // Adjust for minimal days in first week 5814 if ((7 - first) < getMinimalDaysInFirstWeek()) { 5815 date += 7; 5816 } 5817 5818 // Now adjust for the week number. 5819 date += 7 * (internalGet(bestField) - 1); 5820 } 5821 5822 return julianDay + date; 5823 } 5824 5825 /** 5826 * Compute the Julian day of a month of the Gregorian calendar. 5827 * Subclasses may call this method to perform a Gregorian calendar 5828 * fields->millis computation. To perform a Gregorian calendar 5829 * millis->fields computation, call computeGregorianFields(). 5830 * @param year extended Gregorian year 5831 * @param month zero-based Gregorian month 5832 * @return the Julian day number of the day before the first 5833 * day of the given month in the given extended year 5834 * @see #computeGregorianFields 5835 */ computeGregorianMonthStart(int year, int month)5836 protected int computeGregorianMonthStart(int year, int month) { 5837 5838 // If the month is out of range, adjust it into range, and 5839 // modify the extended year value accordingly. 5840 if (month < 0 || month > 11) { 5841 int[] rem = new int[1]; 5842 year += floorDivide(month, 12, rem); 5843 month = rem[0]; 5844 } 5845 5846 boolean isLeap = (year%4 == 0) && ((year%100 != 0) || (year%400 == 0)); 5847 int y = year - 1; 5848 // This computation is actually ... + (JAN_1_1_JULIAN_DAY - 3) + 2. 5849 // Add 2 because Gregorian calendar starts 2 days after Julian 5850 // calendar. 5851 int julianDay = 365*y + floorDivide(y, 4) - floorDivide(y, 100) + 5852 floorDivide(y, 400) + JAN_1_1_JULIAN_DAY - 1; 5853 5854 // At this point julianDay indicates the day BEFORE the first day 5855 // of January 1, <eyear> of the Gregorian calendar. 5856 if (month != 0) { 5857 julianDay += GREGORIAN_MONTH_COUNT[month][isLeap?3:2]; 5858 } 5859 5860 return julianDay; 5861 } 5862 5863 //---------------------------------------------------------------------- 5864 // Subclass API 5865 // For subclasses to override 5866 //---------------------------------------------------------------------- 5867 5868 // (The following method is not called because all existing subclasses 5869 // override it. 2003-06-11 ICU 2.6 Alan) 5870 ///CLOVER:OFF 5871 /** 5872 * Subclasses may override this method to compute several fields 5873 * specific to each calendar system. These are: 5874 * 5875 * <ul><li>ERA 5876 * <li>YEAR 5877 * <li>MONTH 5878 * <li>DAY_OF_MONTH 5879 * <li>DAY_OF_YEAR 5880 * <li>EXTENDED_YEAR</ul> 5881 * 5882 * Subclasses can refer to the DAY_OF_WEEK and DOW_LOCAL fields, which 5883 * will be set when this method is called. Subclasses can also call 5884 * the getGregorianXxx() methods to obtain Gregorian calendar 5885 * equivalents for the given Julian day. 5886 * 5887 * <p>In addition, subclasses should compute any subclass-specific 5888 * fields, that is, fields from BASE_FIELD_COUNT to 5889 * getFieldCount() - 1. 5890 * 5891 * <p>The default implementation in <code>Calendar</code> implements 5892 * a pure proleptic Gregorian calendar. 5893 */ handleComputeFields(int julianDay)5894 protected void handleComputeFields(int julianDay) { 5895 internalSet(MONTH, getGregorianMonth()); 5896 internalSet(DAY_OF_MONTH, getGregorianDayOfMonth()); 5897 internalSet(DAY_OF_YEAR, getGregorianDayOfYear()); 5898 int eyear = getGregorianYear(); 5899 internalSet(EXTENDED_YEAR, eyear); 5900 int era = GregorianCalendar.AD; 5901 if (eyear < 1) { 5902 era = GregorianCalendar.BC; 5903 eyear = 1 - eyear; 5904 } 5905 internalSet(ERA, era); 5906 internalSet(YEAR, eyear); 5907 } 5908 ///CLOVER:ON 5909 5910 //---------------------------------------------------------------------- 5911 // Subclass API 5912 // For subclasses to call 5913 //---------------------------------------------------------------------- 5914 5915 /** 5916 * Returns the extended year on the Gregorian calendar as computed by 5917 * <code>computeGregorianFields()</code>. 5918 * @see #computeGregorianFields 5919 */ getGregorianYear()5920 protected final int getGregorianYear() { 5921 return gregorianYear; 5922 } 5923 5924 /** 5925 * Returns the month (0-based) on the Gregorian calendar as computed by 5926 * <code>computeGregorianFields()</code>. 5927 * @see #computeGregorianFields 5928 */ getGregorianMonth()5929 protected final int getGregorianMonth() { 5930 return gregorianMonth; 5931 } 5932 5933 /** 5934 * Returns the day of year (1-based) on the Gregorian calendar as 5935 * computed by <code>computeGregorianFields()</code>. 5936 * @see #computeGregorianFields 5937 */ getGregorianDayOfYear()5938 protected final int getGregorianDayOfYear() { 5939 return gregorianDayOfYear; 5940 } 5941 5942 /** 5943 * Returns the day of month (1-based) on the Gregorian calendar as 5944 * computed by <code>computeGregorianFields()</code>. 5945 * @see #computeGregorianFields 5946 */ getGregorianDayOfMonth()5947 protected final int getGregorianDayOfMonth() { 5948 return gregorianDayOfMonth; 5949 } 5950 5951 /** 5952 * <strong>[icu]</strong> Returns the number of fields defined by this calendar. Valid field 5953 * arguments to <code>set()</code> and <code>get()</code> are 5954 * <code>0..getFieldCount()-1</code>. 5955 */ getFieldCount()5956 public final int getFieldCount() { 5957 return fields.length; 5958 } 5959 5960 /** 5961 * Set a field to a value. Subclasses should use this method when 5962 * computing fields. It sets the time stamp in the 5963 * <code>stamp[]</code> array to <code>INTERNALLY_SET</code>. If a 5964 * field that may not be set by subclasses is passed in, an 5965 * <code>IllegalArgumentException</code> is thrown. This prevents 5966 * subclasses from modifying fields that are intended to be 5967 * calendar-system invariant. 5968 */ internalSet(int field, int value)5969 protected final void internalSet(int field, int value) { 5970 if (((1 << field) & internalSetMask) == 0) { 5971 throw new IllegalStateException("Subclass cannot set " + 5972 fieldName(field)); 5973 } 5974 fields[field] = value; 5975 stamp[field] = INTERNALLY_SET; 5976 } 5977 5978 private static final int[][] GREGORIAN_MONTH_COUNT = { 5979 //len len2 st st2 5980 { 31, 31, 0, 0 }, // Jan 5981 { 28, 29, 31, 31 }, // Feb 5982 { 31, 31, 59, 60 }, // Mar 5983 { 30, 30, 90, 91 }, // Apr 5984 { 31, 31, 120, 121 }, // May 5985 { 30, 30, 151, 152 }, // Jun 5986 { 31, 31, 181, 182 }, // Jul 5987 { 31, 31, 212, 213 }, // Aug 5988 { 30, 30, 243, 244 }, // Sep 5989 { 31, 31, 273, 274 }, // Oct 5990 { 30, 30, 304, 305 }, // Nov 5991 { 31, 31, 334, 335 } // Dec 5992 // len length of month 5993 // len2 length of month in a leap year 5994 // st days in year before start of month 5995 // st2 days in year before month in leap year 5996 }; 5997 5998 /** 5999 * Determines if the given year is a leap year. Returns true if the 6000 * given year is a leap year. 6001 * @param year the given year. 6002 * @return true if the given year is a leap year; false otherwise. 6003 */ isGregorianLeapYear(int year)6004 protected static final boolean isGregorianLeapYear(int year) { 6005 return (year%4 == 0) && ((year%100 != 0) || (year%400 == 0)); 6006 } 6007 6008 /** 6009 * Returns the length of a month of the Gregorian calendar. 6010 * @param y the extended year 6011 * @param m the 0-based month number 6012 * @return the number of days in the given month 6013 */ gregorianMonthLength(int y, int m)6014 protected static final int gregorianMonthLength(int y, int m) { 6015 return GREGORIAN_MONTH_COUNT[m][isGregorianLeapYear(y)?1:0]; 6016 } 6017 6018 /** 6019 * Returns the length of a previous month of the Gregorian calendar. 6020 * @param y the extended year 6021 * @param m the 0-based month number 6022 * @return the number of days in the month previous to the given month 6023 */ gregorianPreviousMonthLength(int y, int m)6024 protected static final int gregorianPreviousMonthLength(int y, int m) { 6025 return (m > 0) ? gregorianMonthLength(y, m-1) : 31; 6026 } 6027 6028 /** 6029 * Divide two long integers, returning the floor of the quotient. 6030 * <p> 6031 * Unlike the built-in division, this is mathematically well-behaved. 6032 * E.g., <code>-1/4</code> => 0 6033 * but <code>floorDivide(-1,4)</code> => -1. 6034 * @param numerator the numerator 6035 * @param denominator a divisor which must be > 0 6036 * @return the floor of the quotient. 6037 */ floorDivide(long numerator, long denominator)6038 protected static final long floorDivide(long numerator, long denominator) { 6039 // We do this computation in order to handle 6040 // a numerator of Long.MIN_VALUE correctly 6041 return (numerator >= 0) ? 6042 numerator / denominator : 6043 ((numerator + 1) / denominator) - 1; 6044 } 6045 6046 /** 6047 * Divide two integers, returning the floor of the quotient. 6048 * <p> 6049 * Unlike the built-in division, this is mathematically well-behaved. 6050 * E.g., <code>-1/4</code> => 0 6051 * but <code>floorDivide(-1,4)</code> => -1. 6052 * @param numerator the numerator 6053 * @param denominator a divisor which must be > 0 6054 * @return the floor of the quotient. 6055 */ floorDivide(int numerator, int denominator)6056 protected static final int floorDivide(int numerator, int denominator) { 6057 // We do this computation in order to handle 6058 // a numerator of Integer.MIN_VALUE correctly 6059 return (numerator >= 0) ? 6060 numerator / denominator : 6061 ((numerator + 1) / denominator) - 1; 6062 } 6063 6064 /** 6065 * Divide two integers, returning the floor of the quotient, and 6066 * the modulus remainder. 6067 * <p> 6068 * Unlike the built-in division, this is mathematically well-behaved. 6069 * E.g., <code>-1/4</code> => 0 and <code>-1%4</code> => -1, 6070 * but <code>floorDivide(-1,4)</code> => -1 with <code>remainder[0]</code> => 3. 6071 * @param numerator the numerator 6072 * @param denominator a divisor which must be > 0 6073 * @param remainder an array of at least one element in which the value 6074 * <code>numerator mod denominator</code> is returned. Unlike <code>numerator 6075 * % denominator</code>, this will always be non-negative. 6076 * @return the floor of the quotient. 6077 */ floorDivide(int numerator, int denominator, int[] remainder)6078 protected static final int floorDivide(int numerator, int denominator, int[] remainder) { 6079 if (numerator >= 0) { 6080 remainder[0] = numerator % denominator; 6081 return numerator / denominator; 6082 } 6083 int quotient = ((numerator + 1) / denominator) - 1; 6084 remainder[0] = numerator - (quotient * denominator); 6085 return quotient; 6086 } 6087 6088 /** 6089 * Divide two integers, returning the floor of the quotient, and 6090 * the modulus remainder. 6091 * <p> 6092 * Unlike the built-in division, this is mathematically well-behaved. 6093 * E.g., <code>-1/4</code> => 0 and <code>-1%4</code> => -1, 6094 * but <code>floorDivide(-1,4)</code> => -1 with <code>remainder[0]</code> => 3. 6095 * @param numerator the numerator 6096 * @param denominator a divisor which must be > 0 6097 * @param remainder an array of at least one element in which the value 6098 * <code>numerator mod denominator</code> is returned. Unlike <code>numerator 6099 * % denominator</code>, this will always be non-negative. 6100 * @return the floor of the quotient. 6101 */ floorDivide(long numerator, int denominator, int[] remainder)6102 protected static final int floorDivide(long numerator, int denominator, int[] remainder) { 6103 if (numerator >= 0) { 6104 remainder[0] = (int)(numerator % denominator); 6105 return (int)(numerator / denominator); 6106 } 6107 int quotient = (int)(((numerator + 1) / denominator) - 1); 6108 remainder[0] = (int)(numerator - ((long)quotient * denominator)); 6109 return quotient; 6110 } 6111 6112 private static final String[] FIELD_NAME = { 6113 "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", 6114 "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK", 6115 "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR", "HOUR_OF_DAY", 6116 "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET", 6117 "DST_OFFSET", "YEAR_WOY", "DOW_LOCAL", "EXTENDED_YEAR", 6118 "JULIAN_DAY", "MILLISECONDS_IN_DAY", 6119 }; 6120 6121 /** 6122 * Returns a string name for a field, for debugging and exceptions. 6123 */ fieldName(int field)6124 protected String fieldName(int field) { 6125 try { 6126 return FIELD_NAME[field]; 6127 } catch (ArrayIndexOutOfBoundsException e) { 6128 return "Field " + field; 6129 } 6130 } 6131 6132 /** 6133 * Converts time as milliseconds to Julian day. 6134 * @param millis the given milliseconds. 6135 * @return the Julian day number. 6136 */ millisToJulianDay(long millis)6137 protected static final int millisToJulianDay(long millis) { 6138 return (int) (EPOCH_JULIAN_DAY + floorDivide(millis, ONE_DAY)); 6139 } 6140 6141 /** 6142 * Converts Julian day to time as milliseconds. 6143 * @param julian the given Julian day number. 6144 * @return time as milliseconds. 6145 */ julianDayToMillis(int julian)6146 protected static final long julianDayToMillis(int julian) { 6147 return (julian - EPOCH_JULIAN_DAY) * ONE_DAY; 6148 } 6149 6150 /** 6151 * Returns the day of week, from SUNDAY to SATURDAY, given a Julian day. 6152 */ julianDayToDayOfWeek(int julian)6153 protected static final int julianDayToDayOfWeek(int julian) { 6154 // If julian is negative, then julian%7 will be negative, so we adjust 6155 // accordingly. Julian day 0 is Monday. 6156 int dayOfWeek = (julian + MONDAY) % 7; 6157 if (dayOfWeek < SUNDAY) { 6158 dayOfWeek += 7; 6159 } 6160 return dayOfWeek; 6161 } 6162 6163 /** 6164 * Returns the current milliseconds without recomputing. 6165 */ internalGetTimeInMillis()6166 protected final long internalGetTimeInMillis() { 6167 return time; 6168 } 6169 6170 /** 6171 * <strong>[icu]</strong> Returns the calendar type name string for this Calendar object. 6172 * The returned string is the legacy ICU calendar attribute value, 6173 * for example, "gregorian" or "japanese". 6174 * 6175 * <p>See type="old type name" for the calendar attribute of locale IDs 6176 * at http://www.unicode.org/reports/tr35/#Key_Type_Definitions 6177 * 6178 * @return legacy calendar type name string 6179 */ getType()6180 public String getType() { 6181 return "unknown"; 6182 } 6183 6184 /** 6185 * Returns if two digit representation of year in this calendar type 6186 * customarily implies a default century (i.e. 03 -> 2003). 6187 * The default implementation returns <code>true</code>. A subclass may 6188 * return <code>false</code> if such practice is not applicable (for example, 6189 * Chinese calendar and Japanese calendar). 6190 * 6191 * @return <code>true</code> if this calendar has a default century. 6192 * @deprecated This API is ICU internal only. 6193 * @hide original deprecated declaration 6194 * @hide draft / provisional / internal are hidden on Android 6195 */ 6196 @Deprecated haveDefaultCentury()6197 public boolean haveDefaultCentury() { 6198 return true; 6199 } 6200 6201 // -------- BEGIN ULocale boilerplate -------- 6202 6203 /** 6204 * <strong>[icu]</strong> Returns the locale that was used to create this object, or null. 6205 * This may may differ from the locale requested at the time of 6206 * this object's creation. For example, if an object is created 6207 * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be 6208 * drawn from <tt>en</tt> (the <i>actual</i> locale), and 6209 * <tt>en_US</tt> may be the most specific locale that exists (the 6210 * <i>valid</i> locale). 6211 * 6212 * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8 6213 * contains a partial preview implementation. The * <i>actual</i> 6214 * locale is returned correctly, but the <i>valid</i> locale is 6215 * not, in most cases. 6216 * @param type type of information requested, either {@link 6217 * android.icu.util.ULocale#VALID_LOCALE} or {@link 6218 * android.icu.util.ULocale#ACTUAL_LOCALE}. 6219 * @return the information specified by <i>type</i>, or null if 6220 * this object was not constructed from locale data. 6221 * @see android.icu.util.ULocale 6222 * @see android.icu.util.ULocale#VALID_LOCALE 6223 * @see android.icu.util.ULocale#ACTUAL_LOCALE 6224 * @hide draft / provisional / internal are hidden on Android 6225 */ getLocale(ULocale.Type type)6226 public final ULocale getLocale(ULocale.Type type) { 6227 return type == ULocale.ACTUAL_LOCALE ? 6228 this.actualLocale : this.validLocale; 6229 } 6230 6231 /** 6232 * Set information about the locales that were used to create this 6233 * object. If the object was not constructed from locale data, 6234 * both arguments should be set to null. Otherwise, neither 6235 * should be null. The actual locale must be at the same level or 6236 * less specific than the valid locale. This method is intended 6237 * for use by factories or other entities that create objects of 6238 * this class. 6239 * @param valid the most specific locale containing any resource 6240 * data, or null 6241 * @param actual the locale containing data used to construct this 6242 * object, or null 6243 * @see android.icu.util.ULocale 6244 * @see android.icu.util.ULocale#VALID_LOCALE 6245 * @see android.icu.util.ULocale#ACTUAL_LOCALE 6246 */ setLocale(ULocale valid, ULocale actual)6247 final void setLocale(ULocale valid, ULocale actual) { 6248 // Change the following to an assertion later 6249 if ((valid == null) != (actual == null)) { 6250 ///CLOVER:OFF 6251 throw new IllegalArgumentException(); 6252 ///CLOVER:ON 6253 } 6254 // Another check we could do is that the actual locale is at 6255 // the same level or less specific than the valid locale. 6256 this.validLocale = valid; 6257 this.actualLocale = actual; 6258 } 6259 6260 /** 6261 * The most specific locale containing any resource data, or null. 6262 * @see android.icu.util.ULocale 6263 */ 6264 private ULocale validLocale; 6265 6266 /** 6267 * The locale containing data used to construct this object, or 6268 * null. 6269 * @see android.icu.util.ULocale 6270 */ 6271 private ULocale actualLocale; 6272 6273 // -------- END ULocale boilerplate -------- 6274 } 6275