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 * 5 NewEra 2019-05-01 midnight local time 54 * ------------------------------------------------------ 55 * </tt></pre> 56 * 57 * <p><code>ERA</code> value 0 specifies the years before Meiji and 58 * the Gregorian year values are used. Unlike {@link 59 * GregorianCalendar}, the Julian to Gregorian transition is not 60 * supported because it doesn't make any sense to the Japanese 61 * calendar systems used before Meiji. To represent the years before 62 * Gregorian year 1, 0 and negative values are used. The Japanese 63 * Imperial rescripts and government decrees don't specify how to deal 64 * with time differences for applying the era transitions. This 65 * calendar implementation assumes local time for all transitions. 66 * 67 * @author Masayoshi Okutsu 68 * @since 1.6 69 */ 70 class JapaneseImperialCalendar extends Calendar { 71 /* 72 * Implementation Notes 73 * 74 * This implementation uses 75 * sun.util.calendar.LocalGregorianCalendar to perform most of the 86 * The ERA constant designating the Meiji era. 87 */ 88 public static final int MEIJI = 1; 89 90 /** 91 * The ERA constant designating the Taisho era. 92 */ 93 public static final int TAISHO = 2; 94 95 /** 96 * The ERA constant designating the Showa era. 97 */ 98 public static final int SHOWA = 3; 99 100 /** 101 * The ERA constant designating the Heisei era. 102 */ 103 public static final int HEISEI = 4; 104 105 /** 106 * The ERA constant designating the NewEra era. 107 */ 108 private static final int NEWERA = 5; 109 110 private static final int EPOCH_OFFSET = 719163; // Fixed date of January 1, 1970 (Gregorian) 111 private static final int EPOCH_YEAR = 1970; 112 113 // Useful millisecond constants. Although ONE_DAY and ONE_WEEK can fit 114 // into ints, they must be longs in order to prevent arithmetic overflow 115 // when performing (bug 4173516). 116 private static final int ONE_SECOND = 1000; 117 private static final int ONE_MINUTE = 60*ONE_SECOND; 118 private static final int ONE_HOUR = 60*ONE_MINUTE; 119 private static final long ONE_DAY = 24*ONE_HOUR; 120 private static final long ONE_WEEK = 7*ONE_DAY; 121 122 // Reference to the sun.util.calendar.LocalGregorianCalendar instance (singleton). 123 private static final LocalGregorianCalendar jcal 124 = (LocalGregorianCalendar) CalendarSystem.forName("japanese"); 125 126 // Gregorian calendar instance. This is required because era 127 // transition dates are given in Gregorian dates. 128 private static final Gregorian gcal = CalendarSystem.getGregorianCalendar(); 129 130 // The Era instance representing "before Meiji". 131 private static final Era BEFORE_MEIJI_ERA = new Era("BeforeMeiji", "BM", Long.MIN_VALUE, false); 337 * @return {@code "japanese"} 338 */ 339 @Override 340 public String getCalendarType() { 341 return "japanese"; 342 } 343 344 /** 345 * Compares this <code>JapaneseImperialCalendar</code> to the specified 346 * <code>Object</code>. The result is <code>true</code> if and 347 * only if the argument is a <code>JapaneseImperialCalendar</code> object 348 * that represents the same time value (millisecond offset from 349 * the <a href="Calendar.html#Epoch">Epoch</a>) under the same 350 * <code>Calendar</code> parameters. 351 * 352 * @param obj the object to compare with. 353 * @return <code>true</code> if this object is equal to <code>obj</code>; 354 * <code>false</code> otherwise. 355 * @see Calendar#compareTo(Calendar) 356 */ 357 public boolean equals(Object obj) { 358 return obj instanceof JapaneseImperialCalendar && 359 super.equals(obj); 360 } 361 362 /** 363 * Generates the hash code for this 364 * <code>JapaneseImperialCalendar</code> object. 365 */ 366 public int hashCode() { 367 return super.hashCode() ^ jdate.hashCode(); 368 } 369 370 /** 371 * Adds the specified (signed) amount of time to the given calendar field, 372 * based on the calendar's rules. 373 * 374 * <p><em>Add rule 1</em>. The value of <code>field</code> 375 * after the call minus the value of <code>field</code> before the 376 * call is <code>amount</code>, modulo any overflow that has occurred in 377 * <code>field</code>. Overflow occurs when a field value exceeds its 378 * range and, as a result, the next larger field is incremented or 379 * decremented and the field value is adjusted back into its range.</p> 380 * 381 * <p><em>Add rule 2</em>. If a smaller field is expected to be 382 * invariant, but it is impossible for it to be equal to its 383 * prior value because of changes in its minimum or maximum after 384 * <code>field</code> is changed, then its value is adjusted to be as close 385 * as possible to its expected value. A smaller field represents a 386 * smaller unit of time. <code>HOUR</code> is a smaller field than 387 * <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields 388 * that are not expected to be invariant. The calendar system 389 * determines what fields are expected to be invariant.</p> 390 * 391 * @param field the calendar field. 392 * @param amount the amount of date or time to be added to the field. 393 * @exception IllegalArgumentException if <code>field</code> is 394 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown, 395 * or if any calendar fields have out-of-range values in 396 * non-lenient mode. 397 */ 398 public void add(int field, int amount) { 399 // If amount == 0, do nothing even the given field is out of 400 // range. This is tested by JCK. 401 if (amount == 0) { 402 return; // Do nothing! 403 } 404 405 if (field < 0 || field >= ZONE_OFFSET) { 406 throw new IllegalArgumentException(); 407 } 408 409 // Sync the time and calendar fields. 410 complete(); 411 412 if (field == YEAR) { 413 LocalGregorianCalendar.Date d = (LocalGregorianCalendar.Date) jdate.clone(); 414 d.addYear(amount); 415 pinDayOfMonth(d); 416 set(ERA, getEraIndex(d)); 417 set(YEAR, d.getYear()); 506 timeOfDay += ONE_DAY; 507 } 508 509 fd += delta; // fd is the expected fixed date after the calculation 510 int zoneOffset = internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET); 511 setTimeInMillis((fd - EPOCH_OFFSET) * ONE_DAY + timeOfDay - zoneOffset); 512 zoneOffset -= internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET); 513 // If the time zone offset has changed, then adjust the difference. 514 if (zoneOffset != 0) { 515 setTimeInMillis(time + zoneOffset); 516 long fd2 = cachedFixedDate; 517 // If the adjustment has changed the date, then take 518 // the previous one. 519 if (fd2 != fd) { 520 setTimeInMillis(time - zoneOffset); 521 } 522 } 523 } 524 } 525 526 public void roll(int field, boolean up) { 527 roll(field, up ? +1 : -1); 528 } 529 530 /** 531 * Adds a signed amount to the specified calendar field without changing larger fields. 532 * A negative roll amount means to subtract from field without changing 533 * larger fields. If the specified amount is 0, this method performs nothing. 534 * 535 * <p>This method calls {@link #complete()} before adding the 536 * amount so that all the calendar fields are normalized. If there 537 * is any calendar field having an out-of-range value in non-lenient mode, then an 538 * <code>IllegalArgumentException</code> is thrown. 539 * 540 * @param field the calendar field. 541 * @param amount the signed amount to add to <code>field</code>. 542 * @exception IllegalArgumentException if <code>field</code> is 543 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown, 544 * or if any calendar fields have out-of-range values in 545 * non-lenient mode. 546 * @see #roll(int,boolean) 547 * @see #add(int,int) 548 * @see #set(int,int) 549 */ 550 public void roll(int field, int amount) { 551 // If amount == 0, do nothing even the given field is out of 552 // range. This is tested by JCK. 553 if (amount == 0) { 554 return; 555 } 556 557 if (field < 0 || field >= ZONE_OFFSET) { 558 throw new IllegalArgumentException(); 559 } 560 561 // Sync the time and calendar fields. 562 complete(); 563 564 int min = getMinimum(field); 565 int max = getMaximum(field); 566 567 switch (field) { 568 case ERA: 569 case AM_PM: 1712 // The spec is to calculate WEEK_OF_YEAR in the 1713 // ISO8601-style. This creates problems, though. 1714 if (weekOfYear == 0) { 1715 // If the date belongs to the last week of the 1716 // previous year, use the week number of "12/31" of 1717 // the "previous" year. Again, if the previous year is 1718 // a transition year, we need to take care of it. 1719 // Usually the previous day of the first day of a year 1720 // is December 31, which is not always true in the 1721 // Japanese imperial calendar system. 1722 long fixedDec31 = fixedDateJan1 - 1; 1723 long prevJan1; 1724 LocalGregorianCalendar.Date d = getCalendarDate(fixedDec31); 1725 if (!(transitionYear || isTransitionYear(d.getNormalizedYear()))) { 1726 prevJan1 = fixedDateJan1 - 365; 1727 if (d.isLeapYear()) { 1728 --prevJan1; 1729 } 1730 } else if (transitionYear) { 1731 if (jdate.getYear() == 1) { 1732 // As of NewEra (since Meiji) there's no case 1733 // that there are multiple transitions in a 1734 // year. Historically there was such 1735 // case. There might be such case again in the 1736 // future. 1737 if (era > NEWERA) { 1738 CalendarDate pd = eras[era - 1].getSinceDate(); 1739 if (normalizedYear == pd.getYear()) { 1740 d.setMonth(pd.getMonth()).setDayOfMonth(pd.getDayOfMonth()); 1741 } 1742 } else { 1743 d.setMonth(LocalGregorianCalendar.JANUARY).setDayOfMonth(1); 1744 } 1745 jcal.normalize(d); 1746 prevJan1 = jcal.getFixedDate(d); 1747 } else { 1748 prevJan1 = fixedDateJan1 - 365; 1749 if (d.isLeapYear()) { 1750 --prevJan1; 1751 } 1752 } 1753 } else { 1754 CalendarDate cd = eras[getEraIndex(jdate)].getSinceDate(); 1755 d.setMonth(cd.getMonth()).setDayOfMonth(cd.getDayOfMonth()); 1756 jcal.normalize(d); 1757 prevJan1 = jcal.getFixedDate(d); | 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 * 5 Reiwa 2019-05-01T00:00:00 local time 54 * ------------------------------------------------------ 55 * }</pre> 56 * 57 * <p><code>ERA</code> value 0 specifies the years before Meiji and 58 * the Gregorian year values are used. Unlike {@link 59 * GregorianCalendar}, the Julian to Gregorian transition is not 60 * supported because it doesn't make any sense to the Japanese 61 * calendar systems used before Meiji. To represent the years before 62 * Gregorian year 1, 0 and negative values are used. The Japanese 63 * Imperial rescripts and government decrees don't specify how to deal 64 * with time differences for applying the era transitions. This 65 * calendar implementation assumes local time for all transitions. 66 * 67 * @author Masayoshi Okutsu 68 * @since 1.6 69 */ 70 class JapaneseImperialCalendar extends Calendar { 71 /* 72 * Implementation Notes 73 * 74 * This implementation uses 75 * sun.util.calendar.LocalGregorianCalendar to perform most of the 86 * The ERA constant designating the Meiji era. 87 */ 88 public static final int MEIJI = 1; 89 90 /** 91 * The ERA constant designating the Taisho era. 92 */ 93 public static final int TAISHO = 2; 94 95 /** 96 * The ERA constant designating the Showa era. 97 */ 98 public static final int SHOWA = 3; 99 100 /** 101 * The ERA constant designating the Heisei era. 102 */ 103 public static final int HEISEI = 4; 104 105 /** 106 * The ERA constant designating the Reiwa era. 107 */ 108 private static final int REIWA = 5; 109 110 private static final int EPOCH_OFFSET = 719163; // Fixed date of January 1, 1970 (Gregorian) 111 112 // Useful millisecond constants. Although ONE_DAY and ONE_WEEK can fit 113 // into ints, they must be longs in order to prevent arithmetic overflow 114 // when performing (bug 4173516). 115 private static final int ONE_SECOND = 1000; 116 private static final int ONE_MINUTE = 60*ONE_SECOND; 117 private static final int ONE_HOUR = 60*ONE_MINUTE; 118 private static final long ONE_DAY = 24*ONE_HOUR; 119 private static final long ONE_WEEK = 7*ONE_DAY; 120 121 // Reference to the sun.util.calendar.LocalGregorianCalendar instance (singleton). 122 private static final LocalGregorianCalendar jcal 123 = (LocalGregorianCalendar) CalendarSystem.forName("japanese"); 124 125 // Gregorian calendar instance. This is required because era 126 // transition dates are given in Gregorian dates. 127 private static final Gregorian gcal = CalendarSystem.getGregorianCalendar(); 128 129 // The Era instance representing "before Meiji". 130 private static final Era BEFORE_MEIJI_ERA = new Era("BeforeMeiji", "BM", Long.MIN_VALUE, false); 336 * @return {@code "japanese"} 337 */ 338 @Override 339 public String getCalendarType() { 340 return "japanese"; 341 } 342 343 /** 344 * Compares this <code>JapaneseImperialCalendar</code> to the specified 345 * <code>Object</code>. The result is <code>true</code> if and 346 * only if the argument is a <code>JapaneseImperialCalendar</code> object 347 * that represents the same time value (millisecond offset from 348 * the <a href="Calendar.html#Epoch">Epoch</a>) under the same 349 * <code>Calendar</code> parameters. 350 * 351 * @param obj the object to compare with. 352 * @return <code>true</code> if this object is equal to <code>obj</code>; 353 * <code>false</code> otherwise. 354 * @see Calendar#compareTo(Calendar) 355 */ 356 @Override 357 public boolean equals(Object obj) { 358 return obj instanceof JapaneseImperialCalendar && 359 super.equals(obj); 360 } 361 362 /** 363 * Generates the hash code for this 364 * <code>JapaneseImperialCalendar</code> object. 365 */ 366 @Override 367 public int hashCode() { 368 return super.hashCode() ^ jdate.hashCode(); 369 } 370 371 /** 372 * Adds the specified (signed) amount of time to the given calendar field, 373 * based on the calendar's rules. 374 * 375 * <p><em>Add rule 1</em>. The value of <code>field</code> 376 * after the call minus the value of <code>field</code> before the 377 * call is <code>amount</code>, modulo any overflow that has occurred in 378 * <code>field</code>. Overflow occurs when a field value exceeds its 379 * range and, as a result, the next larger field is incremented or 380 * decremented and the field value is adjusted back into its range.</p> 381 * 382 * <p><em>Add rule 2</em>. If a smaller field is expected to be 383 * invariant, but it is impossible for it to be equal to its 384 * prior value because of changes in its minimum or maximum after 385 * <code>field</code> is changed, then its value is adjusted to be as close 386 * as possible to its expected value. A smaller field represents a 387 * smaller unit of time. <code>HOUR</code> is a smaller field than 388 * <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields 389 * that are not expected to be invariant. The calendar system 390 * determines what fields are expected to be invariant.</p> 391 * 392 * @param field the calendar field. 393 * @param amount the amount of date or time to be added to the field. 394 * @exception IllegalArgumentException if <code>field</code> is 395 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown, 396 * or if any calendar fields have out-of-range values in 397 * non-lenient mode. 398 */ 399 @Override 400 public void add(int field, int amount) { 401 // If amount == 0, do nothing even the given field is out of 402 // range. This is tested by JCK. 403 if (amount == 0) { 404 return; // Do nothing! 405 } 406 407 if (field < 0 || field >= ZONE_OFFSET) { 408 throw new IllegalArgumentException(); 409 } 410 411 // Sync the time and calendar fields. 412 complete(); 413 414 if (field == YEAR) { 415 LocalGregorianCalendar.Date d = (LocalGregorianCalendar.Date) jdate.clone(); 416 d.addYear(amount); 417 pinDayOfMonth(d); 418 set(ERA, getEraIndex(d)); 419 set(YEAR, d.getYear()); 508 timeOfDay += ONE_DAY; 509 } 510 511 fd += delta; // fd is the expected fixed date after the calculation 512 int zoneOffset = internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET); 513 setTimeInMillis((fd - EPOCH_OFFSET) * ONE_DAY + timeOfDay - zoneOffset); 514 zoneOffset -= internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET); 515 // If the time zone offset has changed, then adjust the difference. 516 if (zoneOffset != 0) { 517 setTimeInMillis(time + zoneOffset); 518 long fd2 = cachedFixedDate; 519 // If the adjustment has changed the date, then take 520 // the previous one. 521 if (fd2 != fd) { 522 setTimeInMillis(time - zoneOffset); 523 } 524 } 525 } 526 } 527 528 @Override 529 public void roll(int field, boolean up) { 530 roll(field, up ? +1 : -1); 531 } 532 533 /** 534 * Adds a signed amount to the specified calendar field without changing larger fields. 535 * A negative roll amount means to subtract from field without changing 536 * larger fields. If the specified amount is 0, this method performs nothing. 537 * 538 * <p>This method calls {@link #complete()} before adding the 539 * amount so that all the calendar fields are normalized. If there 540 * is any calendar field having an out-of-range value in non-lenient mode, then an 541 * <code>IllegalArgumentException</code> is thrown. 542 * 543 * @param field the calendar field. 544 * @param amount the signed amount to add to <code>field</code>. 545 * @exception IllegalArgumentException if <code>field</code> is 546 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown, 547 * or if any calendar fields have out-of-range values in 548 * non-lenient mode. 549 * @see #roll(int,boolean) 550 * @see #add(int,int) 551 * @see #set(int,int) 552 */ 553 @Override 554 public void roll(int field, int amount) { 555 // If amount == 0, do nothing even the given field is out of 556 // range. This is tested by JCK. 557 if (amount == 0) { 558 return; 559 } 560 561 if (field < 0 || field >= ZONE_OFFSET) { 562 throw new IllegalArgumentException(); 563 } 564 565 // Sync the time and calendar fields. 566 complete(); 567 568 int min = getMinimum(field); 569 int max = getMaximum(field); 570 571 switch (field) { 572 case ERA: 573 case AM_PM: 1716 // The spec is to calculate WEEK_OF_YEAR in the 1717 // ISO8601-style. This creates problems, though. 1718 if (weekOfYear == 0) { 1719 // If the date belongs to the last week of the 1720 // previous year, use the week number of "12/31" of 1721 // the "previous" year. Again, if the previous year is 1722 // a transition year, we need to take care of it. 1723 // Usually the previous day of the first day of a year 1724 // is December 31, which is not always true in the 1725 // Japanese imperial calendar system. 1726 long fixedDec31 = fixedDateJan1 - 1; 1727 long prevJan1; 1728 LocalGregorianCalendar.Date d = getCalendarDate(fixedDec31); 1729 if (!(transitionYear || isTransitionYear(d.getNormalizedYear()))) { 1730 prevJan1 = fixedDateJan1 - 365; 1731 if (d.isLeapYear()) { 1732 --prevJan1; 1733 } 1734 } else if (transitionYear) { 1735 if (jdate.getYear() == 1) { 1736 // As of Reiwa (since Meiji) there's no case 1737 // that there are multiple transitions in a 1738 // year. Historically there was such 1739 // case. There might be such case again in the 1740 // future. 1741 if (era > REIWA) { 1742 CalendarDate pd = eras[era - 1].getSinceDate(); 1743 if (normalizedYear == pd.getYear()) { 1744 d.setMonth(pd.getMonth()).setDayOfMonth(pd.getDayOfMonth()); 1745 } 1746 } else { 1747 d.setMonth(LocalGregorianCalendar.JANUARY).setDayOfMonth(1); 1748 } 1749 jcal.normalize(d); 1750 prevJan1 = jcal.getFixedDate(d); 1751 } else { 1752 prevJan1 = fixedDateJan1 - 365; 1753 if (d.isLeapYear()) { 1754 --prevJan1; 1755 } 1756 } 1757 } else { 1758 CalendarDate cd = eras[getEraIndex(jdate)].getSinceDate(); 1759 d.setMonth(cd.getMonth()).setDayOfMonth(cd.getDayOfMonth()); 1760 jcal.normalize(d); 1761 prevJan1 = jcal.getFixedDate(d); |