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