1 /*
2 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.util;
27
28 import java.io.IOException;
29 import java.io.ObjectInputStream;
30 import sun.util.locale.provider.CalendarDataUtility;
31 import sun.util.calendar.BaseCalendar;
32 import sun.util.calendar.CalendarDate;
33 import sun.util.calendar.CalendarSystem;
34 import sun.util.calendar.CalendarUtils;
35 import sun.util.calendar.Era;
36 import sun.util.calendar.Gregorian;
37 import sun.util.calendar.LocalGregorianCalendar;
38 import sun.util.calendar.ZoneInfo;
39
40 /**
41 * <code>JapaneseImperialCalendar</code> implements a Japanese
42 * calendar system in which the imperial era-based year numbering is
43 * supported from the Meiji era. The following are the eras supported
44 * by this calendar system.
45 * <pre><tt>
46 * ERA value Era name Since (in Gregorian)
47 * ------------------------------------------------------
48 * 0 N/A N/A
49 * 1 Meiji 1868-01-01 midnight local time
50 * 2 Taisho 1912-07-30 midnight local time
51 * 3 Showa 1926-12-25 midnight local time
52 * 4 Heisei 1989-01-08 midnight local time
53 * ------------------------------------------------------
54 * </tt></pre>
55 *
56 * <p><code>ERA</code> value 0 specifies the years before Meiji and
57 * the Gregorian year values are used. Unlike {@link
58 * GregorianCalendar}, the Julian to Gregorian transition is not
59 * supported because it doesn't make any sense to the Japanese
60 * calendar systems used before Meiji. To represent the years before
61 * Gregorian year 1, 0 and negative values are used. The Japanese
62 * Imperial rescripts and government decrees don't specify how to deal
63 * with time differences for applying the era transitions. This
64 * calendar implementation assumes local time for all transitions.
65 *
66 * @author Masayoshi Okutsu
67 * @since 1.6
68 */
69 class JapaneseImperialCalendar extends Calendar {
70 /*
71 * Implementation Notes
72 *
73 * This implementation uses
74 * sun.util.calendar.LocalGregorianCalendar to perform most of the
75 * calendar calculations. LocalGregorianCalendar is configurable
76 * and reads <JRE_HOME>/lib/calendars.properties at the start-up.
77 */
78
79 /**
80 * The ERA constant designating the era before Meiji.
81 */
82 public static final int BEFORE_MEIJI = 0;
83
84 /**
85 * The ERA constant designating the Meiji era.
86 */
87 public static final int MEIJI = 1;
88
89 /**
90 * The ERA constant designating the Taisho era.
91 */
92 public static final int TAISHO = 2;
93
94 /**
95 * The ERA constant designating the Showa era.
96 */
97 public static final int SHOWA = 3;
98
99 /**
100 * The ERA constant designating the Heisei era.
101 */
102 public static final int HEISEI = 4;
103
104 private static final int EPOCH_OFFSET = 719163; // Fixed date of January 1, 1970 (Gregorian)
105 private static final int EPOCH_YEAR = 1970;
106
107 // Useful millisecond constants. Although ONE_DAY and ONE_WEEK can fit
108 // into ints, they must be longs in order to prevent arithmetic overflow
109 // when performing (bug 4173516).
110 private static final int ONE_SECOND = 1000;
111 private static final int ONE_MINUTE = 60*ONE_SECOND;
112 private static final int ONE_HOUR = 60*ONE_MINUTE;
113 private static final long ONE_DAY = 24*ONE_HOUR;
114 private static final long ONE_WEEK = 7*ONE_DAY;
115
116 // Reference to the sun.util.calendar.LocalGregorianCalendar instance (singleton).
117 private static final LocalGregorianCalendar jcal
118 = (LocalGregorianCalendar) CalendarSystem.forName("japanese");
119
120 // Gregorian calendar instance. This is required because era
121 // transition dates are given in Gregorian dates.
122 private static final Gregorian gcal = CalendarSystem.getGregorianCalendar();
123
124 // The Era instance representing "before Meiji".
125 private static final Era BEFORE_MEIJI_ERA = new Era("BeforeMeiji", "BM", Long.MIN_VALUE, false);
126
127 // Imperial eras. The sun.util.calendar.LocalGregorianCalendar
128 // doesn't have an Era representing before Meiji, which is
129 // inconvenient for a Calendar. So, era[0] is a reference to
130 // BEFORE_MEIJI_ERA.
131 private static final Era[] eras;
132
133 // Fixed date of the first date of each era.
134 private static final long[] sinceFixedDates;
200 0, // ERA
201 292278994, // YEAR
202 DECEMBER, // MONTH
203 53, // WEEK_OF_YEAR
204 6, // WEEK_OF_MONTH
205 31, // DAY_OF_MONTH
206 366, // DAY_OF_YEAR
207 SATURDAY, // DAY_OF_WEEK
208 6, // DAY_OF_WEEK_IN
209 PM, // AM_PM
210 11, // HOUR
211 23, // HOUR_OF_DAY
212 59, // MINUTE
213 59, // SECOND
214 999, // MILLISECOND
215 14*ONE_HOUR, // ZONE_OFFSET
216 2*ONE_HOUR // DST_OFFSET (double summer time)
217 };
218
219 // Proclaim serialization compatibility with JDK 1.6
220 private static final long serialVersionUID = -3364572813905467929L;
221
222 static {
223 Era[] es = jcal.getEras();
224 int length = es.length + 1;
225 eras = new Era[length];
226 sinceFixedDates = new long[length];
227
228 // eras[BEFORE_MEIJI] and sinceFixedDate[BEFORE_MEIJI] are the
229 // same as Gregorian.
230 int index = BEFORE_MEIJI;
231 sinceFixedDates[index] = gcal.getFixedDate(BEFORE_MEIJI_ERA.getSinceDate());
232 eras[index++] = BEFORE_MEIJI_ERA;
233 for (Era e : es) {
234 CalendarDate d = e.getSinceDate();
235 sinceFixedDates[index] = gcal.getFixedDate(d);
236 eras[index++] = e;
237 }
238
239 LEAST_MAX_VALUES[ERA] = MAX_VALUES[ERA] = eras.length - 1;
323 * @return {@code "japanese"}
324 */
325 @Override
326 public String getCalendarType() {
327 return "japanese";
328 }
329
330 /**
331 * Compares this <code>JapaneseImperialCalendar</code> to the specified
332 * <code>Object</code>. The result is <code>true</code> if and
333 * only if the argument is a <code>JapaneseImperialCalendar</code> object
334 * that represents the same time value (millisecond offset from
335 * the <a href="Calendar.html#Epoch">Epoch</a>) under the same
336 * <code>Calendar</code> parameters.
337 *
338 * @param obj the object to compare with.
339 * @return <code>true</code> if this object is equal to <code>obj</code>;
340 * <code>false</code> otherwise.
341 * @see Calendar#compareTo(Calendar)
342 */
343 public boolean equals(Object obj) {
344 return obj instanceof JapaneseImperialCalendar &&
345 super.equals(obj);
346 }
347
348 /**
349 * Generates the hash code for this
350 * <code>JapaneseImperialCalendar</code> object.
351 */
352 public int hashCode() {
353 return super.hashCode() ^ jdate.hashCode();
354 }
355
356 /**
357 * Adds the specified (signed) amount of time to the given calendar field,
358 * based on the calendar's rules.
359 *
360 * <p><em>Add rule 1</em>. The value of <code>field</code>
361 * after the call minus the value of <code>field</code> before the
362 * call is <code>amount</code>, modulo any overflow that has occurred in
363 * <code>field</code>. Overflow occurs when a field value exceeds its
364 * range and, as a result, the next larger field is incremented or
365 * decremented and the field value is adjusted back into its range.</p>
366 *
367 * <p><em>Add rule 2</em>. If a smaller field is expected to be
368 * invariant, but it is impossible for it to be equal to its
369 * prior value because of changes in its minimum or maximum after
370 * <code>field</code> is changed, then its value is adjusted to be as close
371 * as possible to its expected value. A smaller field represents a
372 * smaller unit of time. <code>HOUR</code> is a smaller field than
373 * <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields
374 * that are not expected to be invariant. The calendar system
375 * determines what fields are expected to be invariant.</p>
376 *
377 * @param field the calendar field.
378 * @param amount the amount of date or time to be added to the field.
379 * @exception IllegalArgumentException if <code>field</code> is
380 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
381 * or if any calendar fields have out-of-range values in
382 * non-lenient mode.
383 */
384 public void add(int field, int amount) {
385 // If amount == 0, do nothing even the given field is out of
386 // range. This is tested by JCK.
387 if (amount == 0) {
388 return; // Do nothing!
389 }
390
391 if (field < 0 || field >= ZONE_OFFSET) {
392 throw new IllegalArgumentException();
393 }
394
395 // Sync the time and calendar fields.
396 complete();
397
398 if (field == YEAR) {
399 LocalGregorianCalendar.Date d = (LocalGregorianCalendar.Date) jdate.clone();
400 d.addYear(amount);
401 pinDayOfMonth(d);
402 set(ERA, getEraIndex(d));
403 set(YEAR, d.getYear());
492 timeOfDay += ONE_DAY;
493 }
494
495 fd += delta; // fd is the expected fixed date after the calculation
496 int zoneOffset = internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET);
497 setTimeInMillis((fd - EPOCH_OFFSET) * ONE_DAY + timeOfDay - zoneOffset);
498 zoneOffset -= internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET);
499 // If the time zone offset has changed, then adjust the difference.
500 if (zoneOffset != 0) {
501 setTimeInMillis(time + zoneOffset);
502 long fd2 = cachedFixedDate;
503 // If the adjustment has changed the date, then take
504 // the previous one.
505 if (fd2 != fd) {
506 setTimeInMillis(time - zoneOffset);
507 }
508 }
509 }
510 }
511
512 public void roll(int field, boolean up) {
513 roll(field, up ? +1 : -1);
514 }
515
516 /**
517 * Adds a signed amount to the specified calendar field without changing larger fields.
518 * A negative roll amount means to subtract from field without changing
519 * larger fields. If the specified amount is 0, this method performs nothing.
520 *
521 * <p>This method calls {@link #complete()} before adding the
522 * amount so that all the calendar fields are normalized. If there
523 * is any calendar field having an out-of-range value in non-lenient mode, then an
524 * <code>IllegalArgumentException</code> is thrown.
525 *
526 * @param field the calendar field.
527 * @param amount the signed amount to add to <code>field</code>.
528 * @exception IllegalArgumentException if <code>field</code> is
529 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
530 * or if any calendar fields have out-of-range values in
531 * non-lenient mode.
532 * @see #roll(int,boolean)
533 * @see #add(int,int)
534 * @see #set(int,int)
535 */
536 public void roll(int field, int amount) {
537 // If amount == 0, do nothing even the given field is out of
538 // range. This is tested by JCK.
539 if (amount == 0) {
540 return;
541 }
542
543 if (field < 0 || field >= ZONE_OFFSET) {
544 throw new IllegalArgumentException();
545 }
546
547 // Sync the time and calendar fields.
548 complete();
549
550 int min = getMinimum(field);
551 int max = getMaximum(field);
552
553 switch (field) {
554 case ERA:
555 case AM_PM:
|
1 /*
2 * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.util;
27
28 import java.io.IOException;
29 import java.io.ObjectInputStream;
30 import sun.util.locale.provider.CalendarDataUtility;
31 import sun.util.calendar.BaseCalendar;
32 import sun.util.calendar.CalendarDate;
33 import sun.util.calendar.CalendarSystem;
34 import sun.util.calendar.CalendarUtils;
35 import sun.util.calendar.Era;
36 import sun.util.calendar.Gregorian;
37 import sun.util.calendar.LocalGregorianCalendar;
38 import sun.util.calendar.ZoneInfo;
39
40 /**
41 * {@code JapaneseImperialCalendar} implements a Japanese
42 * calendar system in which the imperial era-based year numbering is
43 * supported from the Meiji era. The following are the eras supported
44 * by this calendar system.
45 * <pre><code>
46 * ERA value Era name Since (in Gregorian)
47 * ------------------------------------------------------
48 * 0 N/A N/A
49 * 1 Meiji 1868-01-01T00:00:00 local time
50 * 2 Taisho 1912-07-30T00:00:00 local time
51 * 3 Showa 1926-12-25T00:00:00 local time
52 * 4 Heisei 1989-01-08T00:00:00 local time
53 * ------------------------------------------------------
54 * </code></pre>
55 *
56 * <p><code>ERA</code> value 0 specifies the years before Meiji and
57 * the Gregorian year values are used. Unlike {@link
58 * GregorianCalendar}, the Julian to Gregorian transition is not
59 * supported because it doesn't make any sense to the Japanese
60 * calendar systems used before Meiji. To represent the years before
61 * Gregorian year 1, 0 and negative values are used. The Japanese
62 * Imperial rescripts and government decrees don't specify how to deal
63 * with time differences for applying the era transitions. This
64 * calendar implementation assumes local time for all transitions.
65 *
66 * <p>A new era can be specified using property
67 * jdk.calendar.japanese.supplemental.era. The new era is added to the
68 * predefined eras. The syntax of the property is as follows.
69 * <p><pre>
70 * {@code name=<name>,abbr=<abbr>,since=<time['u']>}
71 * </pre>
72 * where
73 * <dl>
74 * <dt>{@code <name>:}<dd>the full name of the new era (non-ASCII characters allowed)
75 * <dt>{@code <abbr>:}<dd>the abbreviation of the new era (non-ASCII characters allowed)
76 * <dt>{@code <time['u']>:}<dd>the start time of the new era represented by
77 * milliseconds from 1970-01-01T00:00:00 local time or UTC if {@code 'u'} is
78 * appended to the milliseconds value. (ASCII digits only)
79 * </dl>
80 *
81 * <p>If the given era is invalid, such as the since value before the
82 * beginning of the last predefined era, the given era will be
83 * ignored.
84 *
85 * <p>The following is an example of the property usage.
86 * <p><pre>
87 * java -Djdk.calendar.japanese.supplemental.era="name=NewEra,abbr=N,since=253374307200000"
88 * </pre>
89 * The property specifies an era change to NewEra at 9999-02-11T00:00:00 local time.
90 *
91 * @author Masayoshi Okutsu
92 * @since 1.6
93 */
94 class JapaneseImperialCalendar extends Calendar {
95 /*
96 * Implementation Notes
97 *
98 * This implementation uses
99 * sun.util.calendar.LocalGregorianCalendar to perform most of the
100 * calendar calculations. LocalGregorianCalendar is configurable
101 * and reads <JRE_HOME>/lib/calendars.properties at the start-up.
102 */
103
104 /**
105 * The ERA constant designating the era before Meiji.
106 */
107 public static final int BEFORE_MEIJI = 0;
108
109 /**
110 * The ERA constant designating the Meiji era.
111 */
112 public static final int MEIJI = 1;
113
114 /**
115 * The ERA constant designating the Taisho era.
116 */
117 public static final int TAISHO = 2;
118
119 /**
120 * The ERA constant designating the Showa era.
121 */
122 public static final int SHOWA = 3;
123
124 /**
125 * The ERA constant designating the Heisei era.
126 */
127 public static final int HEISEI = 4;
128
129 private static final int EPOCH_OFFSET = 719163; // Fixed date of January 1, 1970 (Gregorian)
130
131 // Useful millisecond constants. Although ONE_DAY and ONE_WEEK can fit
132 // into ints, they must be longs in order to prevent arithmetic overflow
133 // when performing (bug 4173516).
134 private static final int ONE_SECOND = 1000;
135 private static final int ONE_MINUTE = 60*ONE_SECOND;
136 private static final int ONE_HOUR = 60*ONE_MINUTE;
137 private static final long ONE_DAY = 24*ONE_HOUR;
138
139 // Reference to the sun.util.calendar.LocalGregorianCalendar instance (singleton).
140 private static final LocalGregorianCalendar jcal
141 = (LocalGregorianCalendar) CalendarSystem.forName("japanese");
142
143 // Gregorian calendar instance. This is required because era
144 // transition dates are given in Gregorian dates.
145 private static final Gregorian gcal = CalendarSystem.getGregorianCalendar();
146
147 // The Era instance representing "before Meiji".
148 private static final Era BEFORE_MEIJI_ERA = new Era("BeforeMeiji", "BM", Long.MIN_VALUE, false);
149
150 // Imperial eras. The sun.util.calendar.LocalGregorianCalendar
151 // doesn't have an Era representing before Meiji, which is
152 // inconvenient for a Calendar. So, era[0] is a reference to
153 // BEFORE_MEIJI_ERA.
154 private static final Era[] eras;
155
156 // Fixed date of the first date of each era.
157 private static final long[] sinceFixedDates;
223 0, // ERA
224 292278994, // YEAR
225 DECEMBER, // MONTH
226 53, // WEEK_OF_YEAR
227 6, // WEEK_OF_MONTH
228 31, // DAY_OF_MONTH
229 366, // DAY_OF_YEAR
230 SATURDAY, // DAY_OF_WEEK
231 6, // DAY_OF_WEEK_IN
232 PM, // AM_PM
233 11, // HOUR
234 23, // HOUR_OF_DAY
235 59, // MINUTE
236 59, // SECOND
237 999, // MILLISECOND
238 14*ONE_HOUR, // ZONE_OFFSET
239 2*ONE_HOUR // DST_OFFSET (double summer time)
240 };
241
242 // Proclaim serialization compatibility with JDK 1.6
243 @SuppressWarnings("FieldNameHidesFieldInSuperclass")
244 private static final long serialVersionUID = -3364572813905467929L;
245
246 static {
247 Era[] es = jcal.getEras();
248 int length = es.length + 1;
249 eras = new Era[length];
250 sinceFixedDates = new long[length];
251
252 // eras[BEFORE_MEIJI] and sinceFixedDate[BEFORE_MEIJI] are the
253 // same as Gregorian.
254 int index = BEFORE_MEIJI;
255 sinceFixedDates[index] = gcal.getFixedDate(BEFORE_MEIJI_ERA.getSinceDate());
256 eras[index++] = BEFORE_MEIJI_ERA;
257 for (Era e : es) {
258 CalendarDate d = e.getSinceDate();
259 sinceFixedDates[index] = gcal.getFixedDate(d);
260 eras[index++] = e;
261 }
262
263 LEAST_MAX_VALUES[ERA] = MAX_VALUES[ERA] = eras.length - 1;
347 * @return {@code "japanese"}
348 */
349 @Override
350 public String getCalendarType() {
351 return "japanese";
352 }
353
354 /**
355 * Compares this <code>JapaneseImperialCalendar</code> to the specified
356 * <code>Object</code>. The result is <code>true</code> if and
357 * only if the argument is a <code>JapaneseImperialCalendar</code> object
358 * that represents the same time value (millisecond offset from
359 * the <a href="Calendar.html#Epoch">Epoch</a>) under the same
360 * <code>Calendar</code> parameters.
361 *
362 * @param obj the object to compare with.
363 * @return <code>true</code> if this object is equal to <code>obj</code>;
364 * <code>false</code> otherwise.
365 * @see Calendar#compareTo(Calendar)
366 */
367 @Override
368 public boolean equals(Object obj) {
369 return obj instanceof JapaneseImperialCalendar &&
370 super.equals(obj);
371 }
372
373 /**
374 * Generates the hash code for this
375 * <code>JapaneseImperialCalendar</code> object.
376 */
377 @Override
378 public int hashCode() {
379 return super.hashCode() ^ jdate.hashCode();
380 }
381
382 /**
383 * Adds the specified (signed) amount of time to the given calendar field,
384 * based on the calendar's rules.
385 *
386 * <p><em>Add rule 1</em>. The value of <code>field</code>
387 * after the call minus the value of <code>field</code> before the
388 * call is <code>amount</code>, modulo any overflow that has occurred in
389 * <code>field</code>. Overflow occurs when a field value exceeds its
390 * range and, as a result, the next larger field is incremented or
391 * decremented and the field value is adjusted back into its range.</p>
392 *
393 * <p><em>Add rule 2</em>. If a smaller field is expected to be
394 * invariant, but it is impossible for it to be equal to its
395 * prior value because of changes in its minimum or maximum after
396 * <code>field</code> is changed, then its value is adjusted to be as close
397 * as possible to its expected value. A smaller field represents a
398 * smaller unit of time. <code>HOUR</code> is a smaller field than
399 * <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields
400 * that are not expected to be invariant. The calendar system
401 * determines what fields are expected to be invariant.</p>
402 *
403 * @param field the calendar field.
404 * @param amount the amount of date or time to be added to the field.
405 * @exception IllegalArgumentException if <code>field</code> is
406 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
407 * or if any calendar fields have out-of-range values in
408 * non-lenient mode.
409 */
410 @Override
411 public void add(int field, int amount) {
412 // If amount == 0, do nothing even the given field is out of
413 // range. This is tested by JCK.
414 if (amount == 0) {
415 return; // Do nothing!
416 }
417
418 if (field < 0 || field >= ZONE_OFFSET) {
419 throw new IllegalArgumentException();
420 }
421
422 // Sync the time and calendar fields.
423 complete();
424
425 if (field == YEAR) {
426 LocalGregorianCalendar.Date d = (LocalGregorianCalendar.Date) jdate.clone();
427 d.addYear(amount);
428 pinDayOfMonth(d);
429 set(ERA, getEraIndex(d));
430 set(YEAR, d.getYear());
519 timeOfDay += ONE_DAY;
520 }
521
522 fd += delta; // fd is the expected fixed date after the calculation
523 int zoneOffset = internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET);
524 setTimeInMillis((fd - EPOCH_OFFSET) * ONE_DAY + timeOfDay - zoneOffset);
525 zoneOffset -= internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET);
526 // If the time zone offset has changed, then adjust the difference.
527 if (zoneOffset != 0) {
528 setTimeInMillis(time + zoneOffset);
529 long fd2 = cachedFixedDate;
530 // If the adjustment has changed the date, then take
531 // the previous one.
532 if (fd2 != fd) {
533 setTimeInMillis(time - zoneOffset);
534 }
535 }
536 }
537 }
538
539 @Override
540 public void roll(int field, boolean up) {
541 roll(field, up ? +1 : -1);
542 }
543
544 /**
545 * Adds a signed amount to the specified calendar field without changing larger fields.
546 * A negative roll amount means to subtract from field without changing
547 * larger fields. If the specified amount is 0, this method performs nothing.
548 *
549 * <p>This method calls {@link #complete()} before adding the
550 * amount so that all the calendar fields are normalized. If there
551 * is any calendar field having an out-of-range value in non-lenient mode, then an
552 * <code>IllegalArgumentException</code> is thrown.
553 *
554 * @param field the calendar field.
555 * @param amount the signed amount to add to <code>field</code>.
556 * @exception IllegalArgumentException if <code>field</code> is
557 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
558 * or if any calendar fields have out-of-range values in
559 * non-lenient mode.
560 * @see #roll(int,boolean)
561 * @see #add(int,int)
562 * @see #set(int,int)
563 */
564 @Override
565 public void roll(int field, int amount) {
566 // If amount == 0, do nothing even the given field is out of
567 // range. This is tested by JCK.
568 if (amount == 0) {
569 return;
570 }
571
572 if (field < 0 || field >= ZONE_OFFSET) {
573 throw new IllegalArgumentException();
574 }
575
576 // Sync the time and calendar fields.
577 complete();
578
579 int min = getMinimum(field);
580 int max = getMaximum(field);
581
582 switch (field) {
583 case ERA:
584 case AM_PM:
|