1 7 8 package java.util; 9 10 import java.io.IOException ; 11 import java.io.ObjectInputStream ; 12 import sun.util.calendar.BaseCalendar; 13 import sun.util.calendar.CalendarDate; 14 import sun.util.calendar.CalendarSystem; 15 import sun.util.calendar.CalendarUtils; 16 import sun.util.calendar.Era; 17 import sun.util.calendar.Gregorian; 18 import sun.util.calendar.LocalGregorianCalendar; 19 import sun.util.calendar.ZoneInfo; 20 import sun.util.resources.LocaleData; 21 22 51 class JapaneseImperialCalendar extends Calendar { 52 60 61 64 public static final int BEFORE_MEIJI = 0; 65 66 69 public static final int MEIJI = 1; 70 71 74 public static final int TAISHO = 2; 75 76 79 public static final int SHOWA = 3; 80 81 84 public static final int HEISEI = 4; 85 86 private static final int EPOCH_OFFSET = 719163; private static final int EPOCH_YEAR = 1970; 88 89 private static final int ONE_SECOND = 1000; 93 private static final int ONE_MINUTE = 60*ONE_SECOND; 94 private static final int ONE_HOUR = 60*ONE_MINUTE; 95 private static final long ONE_DAY = 24*ONE_HOUR; 96 private static final long ONE_WEEK = 7*ONE_DAY; 97 98 private static final LocalGregorianCalendar jcal 100 = (LocalGregorianCalendar) CalendarSystem.forName("japanese"); 101 102 private static final Gregorian gcal = CalendarSystem.getGregorianCalendar(); 105 106 private static final Era BEFORE_MEIJI_ERA = new Era("BeforeMeiji", "BM", Long.MIN_VALUE, false); 108 109 private static final Era[] eras; 114 115 private static final long[] sinceFixedDates; 117 118 143 static final int MIN_VALUES[] = { 144 0, -292275055, JANUARY, 1, 0, 1, 1, SUNDAY, 1, AM, 0, 0, 0, 0, 0, -13*ONE_HOUR, 0 }; 162 static final int LEAST_MAX_VALUES[] = { 163 0, 0, JANUARY, 0, 4, 28, 0, SATURDAY, 4, PM, 11, 23, 59, 59, 999, 14*ONE_HOUR, 20*ONE_MINUTE }; 181 static final int MAX_VALUES[] = { 182 0, 292278994, DECEMBER, 53, 6, 31, 366, SATURDAY, 6, PM, 11, 23, 59, 59, 999, 14*ONE_HOUR, 2*ONE_HOUR }; 200 201 private static final long serialVersionUID = -3364572813905467929L; 203 204 static { 205 Era[] es = jcal.getEras(); 206 int length = es.length + 1; 207 eras = new Era[length]; 208 sinceFixedDates = new long[length]; 209 210 int index = BEFORE_MEIJI; 213 sinceFixedDates[index] = gcal.getFixedDate(BEFORE_MEIJI_ERA.getSinceDate()); 214 eras[index++] = BEFORE_MEIJI_ERA; 215 for (Era e : es) { 216 CalendarDate d = e.getSinceDate(); 217 sinceFixedDates[index] = gcal.getFixedDate(d); 218 eras[index++] = e; 219 } 220 221 LEAST_MAX_VALUES[ERA] = MAX_VALUES[ERA] = eras.length - 1; 222 223 int year = Integer.MAX_VALUE; 227 int dayOfYear = Integer.MAX_VALUE; 228 CalendarDate date = gcal.newCalendarDate(TimeZone.NO_TIMEZONE); 229 for (int i = 1; i < eras.length; i++) { 230 long fd = sinceFixedDates[i]; 231 CalendarDate transitionDate = eras[i].getSinceDate(); 232 date.setDate(transitionDate.getYear(), BaseCalendar.JANUARY, 1); 233 long fdd = gcal.getFixedDate(date); 234 dayOfYear = Math.min((int)(fdd - fd), dayOfYear); 235 date.setDate(transitionDate.getYear(), BaseCalendar.DECEMBER, 31); 236 fdd = gcal.getFixedDate(date) + 1; 237 dayOfYear = Math.min((int)(fd - fdd), dayOfYear); 238 239 LocalGregorianCalendar.Date lgd = getCalendarDate(fd - 1); 240 int y = lgd.getYear(); 241 if (!(lgd.getMonth() == BaseCalendar.JANUARY && lgd.getDayOfMonth() == 1)) 246 y--; 247 year = Math.min(y, year); 248 } 249 LEAST_MAX_VALUES[YEAR] = year; LEAST_MAX_VALUES[DAY_OF_YEAR] = dayOfYear; 251 } 252 253 257 private transient LocalGregorianCalendar.Date jdate; 258 259 264 private transient int[] zoneOffsets; 265 266 270 private transient int[] originalFields; 271 272 279 public JapaneseImperialCalendar(TimeZone zone, Locale aLocale) { 280 super(zone, aLocale); 281 jdate = jcal.newCalendarDate(zone); 282 setTimeInMillis(System.currentTimeMillis()); 283 } 284 285 298 public boolean equals(Object obj) { 299 return obj instanceof JapaneseImperialCalendar && 300 super.equals(obj); 301 } 302 303 307 public int hashCode() { 308 return super.hashCode() ^ jdate.hashCode(); 309 } 310 311 339 public void add(int field, int amount) { 340 if (amount == 0) { 343 return; } 345 346 if (field < 0 || field >= ZONE_OFFSET) { 347 throw new IllegalArgumentException (); 348 } 349 350 complete(); 352 353 if (field == YEAR) { 354 LocalGregorianCalendar.Date d = (LocalGregorianCalendar.Date) jdate.clone(); 355 d.addYear(amount); 356 pinDayOfMonth(d); 357 set(ERA, getEraIndex(d)); 358 set(YEAR, d.getYear()); 359 set(MONTH, d.getMonth() - 1); 360 set(DAY_OF_MONTH, d.getDayOfMonth()); 361 } else if (field == MONTH) { 362 LocalGregorianCalendar.Date d = (LocalGregorianCalendar.Date) jdate.clone(); 363 d.addMonth(amount); 364 pinDayOfMonth(d); 365 set(ERA, getEraIndex(d)); 366 set(YEAR, d.getYear()); 367 set(MONTH, d.getMonth() - 1); 368 set(DAY_OF_MONTH, d.getDayOfMonth()); 369 } else if (field == ERA) { 370 int era = internalGet(ERA) + amount; 371 if (era < 0) { 372 era = 0; 373 } else if (era > eras.length - 1) { 374 era = eras.length - 1; 375 } 376 set(ERA, era); 377 } else { 378 long delta = amount; 379 long timeOfDay = 0; 380 switch (field) { 381 case HOUR: 384 case HOUR_OF_DAY: 385 delta *= 60 * 60 * 1000; break; 387 388 case MINUTE: 389 delta *= 60 * 1000; break; 391 392 case SECOND: 393 delta *= 1000; break; 395 396 case MILLISECOND: 397 break; 398 399 case WEEK_OF_YEAR: 403 case WEEK_OF_MONTH: 404 case DAY_OF_WEEK_IN_MONTH: 405 delta *= 7; 406 break; 407 408 case DAY_OF_MONTH: case DAY_OF_YEAR: 410 case DAY_OF_WEEK: 411 break; 412 413 case AM_PM: 414 delta = amount / 2; 417 timeOfDay = 12 * (amount % 2); 418 break; 419 } 420 421 if (field >= HOUR) { 424 setTimeInMillis(time + delta); 425 return; 426 } 427 428 432 long fd = cachedFixedDate; 435 timeOfDay += internalGet(HOUR_OF_DAY); 436 timeOfDay *= 60; 437 timeOfDay += internalGet(MINUTE); 438 timeOfDay *= 60; 439 timeOfDay += internalGet(SECOND); 440 timeOfDay *= 1000; 441 timeOfDay += internalGet(MILLISECOND); 442 if (timeOfDay >= ONE_DAY) { 443 fd++; 444 timeOfDay -= ONE_DAY; 445 } else if (timeOfDay < 0) { 446 fd--; 447 timeOfDay += ONE_DAY; 448 } 449 450 fd += delta; int zoneOffset = internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET); 452 setTimeInMillis((fd - EPOCH_OFFSET) * ONE_DAY + timeOfDay - zoneOffset); 453 zoneOffset -= internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET); 454 if (zoneOffset != 0) { 456 setTimeInMillis(time + zoneOffset); 457 long fd2 = cachedFixedDate; 458 if (fd2 != fd) { 461 setTimeInMillis(time - zoneOffset); 462 } 463 } 464 } 465 } 466 467 public void roll(int field, boolean up) { 468 roll(field, up ? +1 : -1); 469 } 470 471 491 public void roll(int field, int amount) { 492 if (amount == 0) { 495 return; 496 } 497 498 if (field < 0 || field >= ZONE_OFFSET) { 499 throw new IllegalArgumentException (); 500 } 501 502 complete(); 504 505 int min = getMinimum(field); 506 int max = getMaximum(field); 507 508 switch (field) { 509 case ERA: 510 case AM_PM: 511 case MINUTE: 512 case SECOND: 513 case MILLISECOND: 514 break; 519 520 case HOUR: 521 case HOUR_OF_DAY: 522 { 523 int unit = max + 1; int h = internalGet(field); 525 int nh = (h + amount) % unit; 526 if (nh < 0) { 527 nh += unit; 528 } 529 time += ONE_HOUR * (nh - h); 530 531 CalendarDate d = jcal.getCalendarDate(time, getZone()); 536 if (internalGet(DAY_OF_MONTH) != d.getDayOfMonth()) { 537 d.setEra(jdate.getEra()); 538 d.setDate(internalGet(YEAR), 539 internalGet(MONTH) + 1, 540 internalGet(DAY_OF_MONTH)); 541 if (field == HOUR) { 542 assert (internalGet(AM_PM) == PM); 543 d.addHours(+12); } 545 time = jcal.getTime(d); 546 } 547 int hourOfDay = d.getHours(); 548 internalSet(field, hourOfDay % unit); 549 if (field == HOUR) { 550 internalSet(HOUR_OF_DAY, hourOfDay); 551 } else { 552 internalSet(AM_PM, hourOfDay / 12); 553 internalSet(HOUR, hourOfDay % 12); 554 } 555 556 int zoneOffset = d.getZoneOffset(); 558 int saving = d.getDaylightSaving(); 559 internalSet(ZONE_OFFSET, zoneOffset - saving); 560 internalSet(DST_OFFSET, saving); 561 return; 562 } 563 564 case YEAR: 565 min = getActualMinimum(field); 566 max = getActualMaximum(field); 567 break; 568 569 case MONTH: 570 { 575 if (!isTransitionYear(jdate.getNormalizedYear())) { 576 int year = jdate.getYear(); 577 if (year == getMaximum(YEAR)) { 578 CalendarDate jd = jcal.getCalendarDate(time, getZone()); 579 CalendarDate d = jcal.getCalendarDate(Long.MAX_VALUE, getZone()); 580 max = d.getMonth() - 1; 581 int n = getRolledValue(internalGet(field), amount, min, max); 582 if (n == max) { 583 jd.addYear(-400); 585 jd.setMonth(n + 1); 586 if (jd.getDayOfMonth() > d.getDayOfMonth()) { 587 jd.setDayOfMonth(d.getDayOfMonth()); 588 jcal.normalize(jd); 589 } 590 if (jd.getDayOfMonth() == d.getDayOfMonth() 591 && jd.getTimeOfDay() > d.getTimeOfDay()) { 592 jd.setMonth(n + 1); 593 jd.setDayOfMonth(d.getDayOfMonth() - 1); 594 jcal.normalize(jd); 595 n = jd.getMonth() - 1; 597 } 598 set(DAY_OF_MONTH, jd.getDayOfMonth()); 599 } 600 set(MONTH, n); 601 } else if (year == getMinimum(YEAR)) { 602 CalendarDate jd = jcal.getCalendarDate(time, getZone()); 603 CalendarDate d = jcal.getCalendarDate(Long.MIN_VALUE, getZone()); 604 min = d.getMonth() - 1; 605 int n = getRolledValue(internalGet(field), amount, min, max); 606 if (n == min) { 607 jd.addYear(+400); 609 jd.setMonth(n + 1); 610 if (jd.getDayOfMonth() < d.getDayOfMonth()) { 611 jd.setDayOfMonth(d.getDayOfMonth()); 612 jcal.normalize(jd); 613 } 614 if (jd.getDayOfMonth() == d.getDayOfMonth() 615 && jd.getTimeOfDay() < d.getTimeOfDay()) { 616 jd.setMonth(n + 1); 617 jd.setDayOfMonth(d.getDayOfMonth() + 1); 618 jcal.normalize(jd); 619 n = jd.getMonth() - 1; 621 } 622 set(DAY_OF_MONTH, jd.getDayOfMonth()); 623 } 624 set(MONTH, n); 625 } else { 626 int mon = (internalGet(MONTH) + amount) % 12; 627 if (mon < 0) { 628 mon += 12; 629 } 630 set(MONTH, mon); 631 632 int monthLen = monthLength(mon); 637 if (internalGet(DAY_OF_MONTH) > monthLen) { 638 set(DAY_OF_MONTH, monthLen); 639 } 640 } 641 } else { 642 int eraIndex = getEraIndex(jdate); 643 CalendarDate transition = null; 644 if (jdate.getYear() == 1) { 645 transition = eras[eraIndex].getSinceDate(); 646 min = transition.getMonth() - 1; 647 } else { 648 if (eraIndex < eras.length - 1) { 649 transition = eras[eraIndex + 1].getSinceDate(); 650 if (transition.getYear() == jdate.getNormalizedYear()) { 651 max = transition.getMonth() - 1; 652 if (transition.getDayOfMonth() == 1) { 653 max--; 654 } 655 } 656 } 657 } 658 659 if (min == max) { 660 return; 664 } 665 int n = getRolledValue(internalGet(field), amount, min, max); 666 set(MONTH, n); 667 if (n == min) { 668 if (!(transition.getMonth() == BaseCalendar.JANUARY 669 && transition.getDayOfMonth() == 1)) { 670 if (jdate.getDayOfMonth() < transition.getDayOfMonth()) { 671 set(DAY_OF_MONTH, transition.getDayOfMonth()); 672 } 673 } 674 } else if (n == max && (transition.getMonth() - 1 == n)) { 675 int dom = transition.getDayOfMonth(); 676 if (jdate.getDayOfMonth() >= dom) { 677 set(DAY_OF_MONTH, dom - 1); 678 } 679 } 680 } 681 return; 682 } 683 684 case WEEK_OF_YEAR: 685 { 686 int y = jdate.getNormalizedYear(); 687 max = getActualMaximum(WEEK_OF_YEAR); 688 set(DAY_OF_WEEK, internalGet(DAY_OF_WEEK)); int woy = internalGet(WEEK_OF_YEAR); 690 int value = woy + amount; 691 if (!isTransitionYear(jdate.getNormalizedYear())) { 692 int year = jdate.getYear(); 693 if (year == getMaximum(YEAR)) { 694 max = getActualMaximum(WEEK_OF_YEAR); 695 } else if (year == getMinimum(YEAR)) { 696 min = getActualMinimum(WEEK_OF_YEAR); 697 max = getActualMaximum(WEEK_OF_YEAR); 698 if (value > min && value < max) { 699 set(WEEK_OF_YEAR, value); 700 return; 701 } 702 703 } 704 if (value > min && value < max) { 707 set(WEEK_OF_YEAR, value); 708 return; 709 } 710 long fd = cachedFixedDate; 711 long day1 = fd - (7 * (woy - min)); 713 if (year != getMinimum(YEAR)) { 714 if (gcal.getYearFromFixedDate(day1) != y) { 715 min++; 716 } 717 } else { 718 CalendarDate d = jcal.getCalendarDate(Long.MIN_VALUE, getZone()); 719 if (day1 < jcal.getFixedDate(d)) { 720 min++; 721 } 722 } 723 724 fd += 7 * (max - internalGet(WEEK_OF_YEAR)); 726 if (gcal.getYearFromFixedDate(fd) != y) { 727 max--; 728 } 729 break; 730 } 731 732 long fd = cachedFixedDate; 734 long day1 = fd - (7 * (woy - min)); 735 LocalGregorianCalendar.Date d = getCalendarDate(day1); 737 if (!(d.getEra() == jdate.getEra() && d.getYear() == jdate.getYear())) { 738 min++; 739 } 740 741 fd += 7 * (max - woy); 743 jcal.getCalendarDateFromFixedDate(d, fd); 744 if (!(d.getEra() == jdate.getEra() && d.getYear() == jdate.getYear())) { 745 max--; 746 } 747 value = getRolledValue(woy, amount, min, max) - 1; 750 d = getCalendarDate(day1 + value * 7); 751 set(MONTH, d.getMonth() - 1); 752 set(DAY_OF_MONTH, d.getDayOfMonth()); 753 return; 754 } 755 756 case WEEK_OF_MONTH: 757 { 758 boolean isTransitionYear = isTransitionYear(jdate.getNormalizedYear()); 759 int dow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek(); 761 if (dow < 0) { 762 dow += 7; 763 } 764 765 long fd = cachedFixedDate; 766 long month1; int monthLength; if (isTransitionYear) { 769 month1 = getFixedDateMonth1(jdate, fd); 770 monthLength = actualMonthLength(); 771 } else { 772 month1 = fd - internalGet(DAY_OF_MONTH) + 1; 773 monthLength = jcal.getMonthLength(jdate); 774 } 775 776 long monthDay1st = jcal.getDayOfWeekDateOnOrBefore(month1 + 6, 778 getFirstDayOfWeek()); 779 if ((int)(monthDay1st - month1) >= getMinimalDaysInFirstWeek()) { 782 monthDay1st -= 7; 783 } 784 max = getActualMaximum(field); 785 786 int value = getRolledValue(internalGet(field), amount, 1, max) - 1; 788 789 long nfd = monthDay1st + value * 7 + dow; 791 792 if (nfd < month1) { 795 nfd = month1; 796 } else if (nfd >= (month1 + monthLength)) { 797 nfd = month1 + monthLength - 1; 798 } 799 set(DAY_OF_MONTH, (int)(nfd - month1) + 1); 800 return; 801 } 802 803 case DAY_OF_MONTH: 804 { 805 if (!isTransitionYear(jdate.getNormalizedYear())) { 806 max = jcal.getMonthLength(jdate); 807 break; 808 } 809 810 812 long month1 = getFixedDateMonth1(jdate, cachedFixedDate); 815 816 int value = getRolledValue((int)(cachedFixedDate - month1), amount, 820 0, actualMonthLength() - 1); 821 LocalGregorianCalendar.Date d = getCalendarDate(month1 + value); 822 assert getEraIndex(d) == internalGetEra() 823 && d.getYear() == internalGet(YEAR) && d.getMonth()-1 == internalGet(MONTH); 824 set(DAY_OF_MONTH, d.getDayOfMonth()); 825 return; 826 } 827 828 case DAY_OF_YEAR: 829 { 830 max = getActualMaximum(field); 831 if (!isTransitionYear(jdate.getNormalizedYear())) { 832 break; 833 } 834 835 int value = getRolledValue(internalGet(DAY_OF_YEAR), amount, min, max); 838 long jan0 = cachedFixedDate - internalGet(DAY_OF_YEAR); 839 LocalGregorianCalendar.Date d = getCalendarDate(jan0 + value); 840 assert getEraIndex(d) == internalGetEra() && d.getYear() == internalGet(YEAR); 841 set(MONTH, d.getMonth() - 1); 842 set(DAY_OF_MONTH, d.getDayOfMonth()); 843 return; 844 } 845 846 case DAY_OF_WEEK: 847 { 848 int normalizedYear = jdate.getNormalizedYear(); 849 if (!isTransitionYear(normalizedYear) && !isTransitionYear(normalizedYear - 1)) { 850 int weekOfYear = internalGet(WEEK_OF_YEAR); 853 if (weekOfYear > 1 && weekOfYear < 52) { 854 set(WEEK_OF_YEAR, internalGet(WEEK_OF_YEAR)); 855 max = SATURDAY; 856 break; 857 } 858 } 859 860 amount %= 7; 865 if (amount == 0) { 866 return; 867 } 868 long fd = cachedFixedDate; 869 long dowFirst = jcal.getDayOfWeekDateOnOrBefore(fd, getFirstDayOfWeek()); 870 fd += amount; 871 if (fd < dowFirst) { 872 fd += 7; 873 } else if (fd >= dowFirst + 7) { 874 fd -= 7; 875 } 876 LocalGregorianCalendar.Date d = getCalendarDate(fd); 877 set(ERA, getEraIndex(d)); 878 set(d.getYear(), d.getMonth() - 1, d.getDayOfMonth()); 879 return; 880 } 881 882 case DAY_OF_WEEK_IN_MONTH: 883 { 884 min = 1; if (!isTransitionYear(jdate.getNormalizedYear())) { 886 int dom = internalGet(DAY_OF_MONTH); 887 int monthLength = jcal.getMonthLength(jdate); 888 int lastDays = monthLength % 7; 889 max = monthLength / 7; 890 int x = (dom - 1) % 7; 891 if (x < lastDays) { 892 max++; 893 } 894 set(DAY_OF_WEEK, internalGet(DAY_OF_WEEK)); 895 break; 896 } 897 898 long fd = cachedFixedDate; 900 long month1 = getFixedDateMonth1(jdate, fd); 901 int monthLength = actualMonthLength(); 902 int lastDays = monthLength % 7; 903 max = monthLength / 7; 904 int x = (int)(fd - month1) % 7; 905 if (x < lastDays) { 906 max++; 907 } 908 int value = getRolledValue(internalGet(field), amount, min, max) - 1; 909 fd = month1 + value * 7 + x; 910 LocalGregorianCalendar.Date d = getCalendarDate(fd); 911 set(DAY_OF_MONTH, d.getDayOfMonth()); 912 return; 913 } 914 } 915 916 set(field, getRolledValue(internalGet(field), amount, min, max)); 917 } 918 919 public String getDisplayName(int field, int style, Locale locale) { 920 if (!checkDisplayNameParams(field, style, SHORT, LONG, locale, 921 ERA_MASK|YEAR_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) { 922 return null; 923 } 924 925 if (field == YEAR 927 && (style == SHORT || get(YEAR) != 1 || get(ERA) == 0)) { 928 return null; 929 } 930 931 ResourceBundle rb = LocaleData.getDateFormatData(locale); 932 String name = null; 933 String key = getKey(field, style); 934 if (key != null) { 935 String [] strings = rb.getStringArray(key); 936 if (field == YEAR) { 937 if (strings.length > 0) { 938 name = strings[0]; 939 } 940 } else { 941 int index = get(field); 942 if (field == ERA && index >= strings.length && index < eras.length) { 945 Era era = eras[index]; 946 name = (style == SHORT) ? era.getAbbreviation() : era.getName(); 947 } else { 948 if (field == DAY_OF_WEEK) 949 --index; 950 name = strings[index]; 951 } 952 } 953 } 954 return name; 955 } 956 957 public Map <String ,Integer > getDisplayNames(int field, int style, Locale locale) { 958 if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale, 959 ERA_MASK|YEAR_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) { 960 return null; 961 } 962 963 if (style == ALL_STYLES) { 964 Map <String ,Integer > shortNames = getDisplayNamesImpl(field, SHORT, locale); 965 if (field == AM_PM) { 966 return shortNames; 967 } 968 Map <String ,Integer > longNames = getDisplayNamesImpl(field, LONG, locale); 969 if (shortNames == null) { 970 return longNames; 971 } 972 if (longNames != null) { 973 shortNames.putAll(longNames); 974 } 975 return shortNames; 976 } 977 978 return getDisplayNamesImpl(field, style, locale); 980 } 981 982 private Map <String ,Integer > getDisplayNamesImpl(int field, int style, Locale locale) { 983 ResourceBundle rb = LocaleData.getDateFormatData(locale); 984 String key = getKey(field, style); 985 Map <String ,Integer > map = new HashMap <String ,Integer >(); 986 if (key != null) { 987 String [] strings = rb.getStringArray(key); 988 if (field == YEAR) { 989 if (strings.length > 0) { 990 map.put(strings[0], 1); 991 } 992 } else { 993 int base = (field == DAY_OF_WEEK) ? 1 : 0; 994 for (int i = 0; i < strings.length; i++) { 995 map.put(strings[i], base + i); 996 } 997 if (field == ERA && strings.length < eras.length) { 999 for (int i = strings.length; i < eras.length; i++) { 1000 Era era = eras[i]; 1001 String name = (style == SHORT) ? era.getAbbreviation() : era.getName(); 1002 map.put(name, i); 1003 } 1004 } 1005 } 1006 } 1007 return map.size() > 0 ? map : null; 1008 } 1009 1010 private String getKey(int field, int style) { 1011 String className = JapaneseImperialCalendar .class.getName(); 1012 StringBuilder key = new StringBuilder (); 1013 switch (field) { 1014 case ERA: 1015 key.append(className); 1016 if (style == SHORT) { 1017 key.append(".short"); 1018 } 1019 key.append(".Eras"); 1020 break; 1021 1022 case YEAR: 1023 key.append(className).append(".FirstYear"); 1024 break; 1025 1026 case MONTH: 1027 key.append(style == SHORT ? "MonthAbbreviations" : "MonthNames"); 1028 break; 1029 1030 case DAY_OF_WEEK: 1031 key.append(style == SHORT ? "DayAbbreviations" : "DayNames"); 1032 break; 1033 1034 case AM_PM: 1035 key.append("AmPmMarkers"); 1036 break; 1037 } 1038 return key.length() > 0 ? key.toString() : null; 1039 } 1040 1041 1059 public int getMinimum(int field) { 1060 return MIN_VALUES[field]; 1061 } 1062 1063 1081 public int getMaximum(int field) { 1082 switch (field) { 1083 case YEAR: 1084 { 1085 LocalGregorianCalendar.Date d = jcal.getCalendarDate(Long.MAX_VALUE, 1087 getZone()); 1088 return Math.max(LEAST_MAX_VALUES[YEAR], d.getYear()); 1089 } 1090 } 1091 return MAX_VALUES[field]; 1092 } 1093 1094 1112 public int getGreatestMinimum(int field) { 1113 return field == YEAR ? 1 : MIN_VALUES[field]; 1114 } 1115 1116 1134 public int getLeastMaximum(int field) { 1135 switch (field) { 1136 case YEAR: 1137 { 1138 return Math.min(LEAST_MAX_VALUES[YEAR], getMaximum(YEAR)); 1139 } 1140 } 1141 return LEAST_MAX_VALUES[field]; 1142 } 1143 1144 1161 public int getActualMinimum(int field) { 1162 if (!isFieldSet(YEAR_MASK|MONTH_MASK|WEEK_OF_YEAR_MASK, field)) { 1163 return getMinimum(field); 1164 } 1165 1166 int value = 0; 1167 JapaneseImperialCalendar jc = getNormalizedCalendar(); 1168 LocalGregorianCalendar.Date jd = jcal.getCalendarDate(jc.getTimeInMillis(), 1171 getZone()); 1172 int eraIndex = getEraIndex(jd); 1173 switch (field) { 1174 case YEAR: 1175 { 1176 if (eraIndex > BEFORE_MEIJI) { 1177 value = 1; 1178 long since = eras[eraIndex].getSince(getZone()); 1179 CalendarDate d = jcal.getCalendarDate(since, getZone()); 1180 jd.setYear(d.getYear()); 1184 jcal.normalize(jd); 1185 assert jd.isLeapYear() == d.isLeapYear(); 1186 if (getYearOffsetInMillis(jd) < getYearOffsetInMillis(d)) { 1187 value++; 1188 } 1189 } else { 1190 value = getMinimum(field); 1191 CalendarDate d = jcal.getCalendarDate(Long.MIN_VALUE, getZone()); 1192 int y = d.getYear(); 1196 if (y > 400) { 1197 y -= 400; 1198 } 1199 jd.setYear(y); 1200 jcal.normalize(jd); 1201 if (getYearOffsetInMillis(jd) < getYearOffsetInMillis(d)) { 1202 value++; 1203 } 1204 } 1205 } 1206 break; 1207 1208 case MONTH: 1209 { 1210 if (eraIndex > MEIJI && jd.getYear() == 1) { 1212 long since = eras[eraIndex].getSince(getZone()); 1213 CalendarDate d = jcal.getCalendarDate(since, getZone()); 1214 value = d.getMonth() - 1; 1215 if (jd.getDayOfMonth() < d.getDayOfMonth()) { 1216 value++; 1217 } 1218 } 1219 } 1220 break; 1221 1222 case WEEK_OF_YEAR: 1223 { 1224 value = 1; 1225 CalendarDate d = jcal.getCalendarDate(Long.MIN_VALUE, getZone()); 1226 d.addYear(+400); 1228 jcal.normalize(d); 1229 jd.setEra(d.getEra()); 1230 jd.setYear(d.getYear()); 1231 jcal.normalize(jd); 1232 1233 long jan1 = jcal.getFixedDate(d); 1234 long fd = jcal.getFixedDate(jd); 1235 int woy = getWeekNumber(jan1, fd); 1236 long day1 = fd - (7 * (woy - 1)); 1237 if ((day1 < jan1) || 1238 (day1 == jan1 && 1239 jd.getTimeOfDay() < d.getTimeOfDay())) { 1240 value++; 1241 } 1242 } 1243 break; 1244 } 1245 return value; 1246 } 1247 1248 1270 public int getActualMaximum(int field) { 1271 final int fieldsForFixedMax = ERA_MASK|DAY_OF_WEEK_MASK|HOUR_MASK|AM_PM_MASK| 1272 HOUR_OF_DAY_MASK|MINUTE_MASK|SECOND_MASK|MILLISECOND_MASK| 1273 ZONE_OFFSET_MASK|DST_OFFSET_MASK; 1274 if ((fieldsForFixedMax & (1<<field)) != 0) { 1275 return getMaximum(field); 1276 } 1277 1278 JapaneseImperialCalendar jc = getNormalizedCalendar(); 1279 LocalGregorianCalendar.Date date = jc.jdate; 1280 int normalizedYear = date.getNormalizedYear(); 1281 1282 int value = -1; 1283 switch (field) { 1284 case MONTH: 1285 { 1286 value = DECEMBER; 1287 if (isTransitionYear(date.getNormalizedYear())) { 1288 int eraIndex = getEraIndex(date); 1290 if (date.getYear() != 1) { 1291 eraIndex++; 1292 assert eraIndex < eras.length; 1293 } 1294 long transition = sinceFixedDates[eraIndex]; 1295 long fd = jc.cachedFixedDate; 1296 if (fd < transition) { 1297 LocalGregorianCalendar.Date ldate 1298 = (LocalGregorianCalendar.Date) date.clone(); 1299 jcal.getCalendarDateFromFixedDate(ldate, transition - 1); 1300 value = ldate.getMonth() - 1; 1301 } 1302 } else { 1303 LocalGregorianCalendar.Date d = jcal.getCalendarDate(Long.MAX_VALUE, 1304 getZone()); 1305 if (date.getEra() == d.getEra() && date.getYear() == d.getYear()) { 1306 value = d.getMonth() - 1; 1307 } 1308 } 1309 } 1310 break; 1311 1312 case DAY_OF_MONTH: 1313 value = jcal.getMonthLength(date); 1314 break; 1315 1316 case DAY_OF_YEAR: 1317 { 1318 if (isTransitionYear(date.getNormalizedYear())) { 1319 int eraIndex = getEraIndex(date); 1322 if (date.getYear() != 1) { 1323 eraIndex++; 1324 assert eraIndex < eras.length; 1325 } 1326 long transition = sinceFixedDates[eraIndex]; 1327 long fd = jc.cachedFixedDate; 1328 CalendarDate d = gcal.newCalendarDate(TimeZone.NO_TIMEZONE); 1329 d.setDate(date.getNormalizedYear(), BaseCalendar.JANUARY, 1); 1330 if (fd < transition) { 1331 value = (int)(transition - gcal.getFixedDate(d)); 1332 } else { 1333 d.addYear(+1); 1334 value = (int)(gcal.getFixedDate(d) - transition); 1335 } 1336 } else { 1337 LocalGregorianCalendar.Date d = jcal.getCalendarDate(Long.MAX_VALUE, 1338 getZone()); 1339 if (date.getEra() == d.getEra() && date.getYear() == d.getYear()) { 1340 long fd = jcal.getFixedDate(d); 1341 long jan1 = getFixedDateJan1(d, fd); 1342 value = (int)(fd - jan1) + 1; 1343 } else if (date.getYear() == getMinimum(YEAR)) { 1344 CalendarDate d1 = jcal.getCalendarDate(Long.MIN_VALUE, getZone()); 1345 long fd1 = jcal.getFixedDate(d1); 1346 d1.addYear(1); 1347 d1.setMonth(BaseCalendar.JANUARY).setDayOfMonth(1); 1348 jcal.normalize(d1); 1349 long fd2 = jcal.getFixedDate(d1); 1350 value = (int)(fd2 - fd1); 1351 } else { 1352 value = jcal.getYearLength(date); 1353 } 1354 } 1355 } 1356 break; 1357 1358 case WEEK_OF_YEAR: 1359 { 1360 if (!isTransitionYear(date.getNormalizedYear())) { 1361 LocalGregorianCalendar.Date jd = jcal.getCalendarDate(Long.MAX_VALUE, 1362 getZone()); 1363 if (date.getEra() == jd.getEra() && date.getYear() == jd.getYear()) { 1364 long fd = jcal.getFixedDate(jd); 1365 long jan1 = getFixedDateJan1(jd, fd); 1366 value = getWeekNumber(jan1, fd); 1367 } else if (date.getEra() == null && date.getYear() == getMinimum(YEAR)) { 1368 CalendarDate d = jcal.getCalendarDate(Long.MIN_VALUE, getZone()); 1369 d.addYear(+400); 1371 jcal.normalize(d); 1372 jd.setEra(d.getEra()); 1373 jd.setDate(d.getYear() + 1, BaseCalendar.JANUARY, 1); 1374 jcal.normalize(jd); 1375 long jan1 = jcal.getFixedDate(d); 1376 long nextJan1 = jcal.getFixedDate(jd); 1377 long nextJan1st = jcal.getDayOfWeekDateOnOrBefore(nextJan1 + 6, 1378 getFirstDayOfWeek()); 1379 int ndays = (int)(nextJan1st - nextJan1); 1380 if (ndays >= getMinimalDaysInFirstWeek()) { 1381 nextJan1st -= 7; 1382 } 1383 value = getWeekNumber(jan1, nextJan1st); 1384 } else { 1385 CalendarDate d = gcal.newCalendarDate(TimeZone.NO_TIMEZONE); 1387 d.setDate(date.getNormalizedYear(), BaseCalendar.JANUARY, 1); 1388 int dayOfWeek = gcal.getDayOfWeek(d); 1389 dayOfWeek -= getFirstDayOfWeek(); 1391 if (dayOfWeek < 0) { 1392 dayOfWeek += 7; 1393 } 1394 value = 52; 1395 int magic = dayOfWeek + getMinimalDaysInFirstWeek() - 1; 1396 if ((magic == 6) || 1397 (date.isLeapYear() && (magic == 5 || magic == 12))) { 1398 value++; 1399 } 1400 } 1401 break; 1402 } 1403 1404 if (jc == this) { 1405 jc = (JapaneseImperialCalendar ) jc.clone(); 1406 } 1407 int max = getActualMaximum(DAY_OF_YEAR); 1408 jc.set(DAY_OF_YEAR, max); 1409 value = jc.get(WEEK_OF_YEAR); 1410 if (value == 1 && max > 7) { 1411 jc.add(WEEK_OF_YEAR, -1); 1412 value = jc.get(WEEK_OF_YEAR); 1413 } 1414 } 1415 break; 1416 1417 case WEEK_OF_MONTH: 1418 { 1419 LocalGregorianCalendar.Date jd = jcal.getCalendarDate(Long.MAX_VALUE, 1420 getZone()); 1421 if (!(date.getEra() == jd.getEra() && date.getYear() == jd.getYear())) { 1422 CalendarDate d = gcal.newCalendarDate(TimeZone.NO_TIMEZONE); 1423 d.setDate(date.getNormalizedYear(), date.getMonth(), 1); 1424 int dayOfWeek = gcal.getDayOfWeek(d); 1425 int monthLength = gcal.getMonthLength(d); 1426 dayOfWeek -= getFirstDayOfWeek(); 1427 if (dayOfWeek < 0) { 1428 dayOfWeek += 7; 1429 } 1430 int nDaysFirstWeek = 7 - dayOfWeek; value = 3; 1432 if (nDaysFirstWeek >= getMinimalDaysInFirstWeek()) { 1433 value++; 1434 } 1435 monthLength -= nDaysFirstWeek + 7 * 3; 1436 if (monthLength > 0) { 1437 value++; 1438 if (monthLength > 7) { 1439 value++; 1440 } 1441 } 1442 } else { 1443 long fd = jcal.getFixedDate(jd); 1444 long month1 = fd - jd.getDayOfMonth() + 1; 1445 value = getWeekNumber(month1, fd); 1446 } 1447 } 1448 break; 1449 1450 case DAY_OF_WEEK_IN_MONTH: 1451 { 1452 int ndays, dow1; 1453 int dow = date.getDayOfWeek(); 1454 BaseCalendar.Date d = (BaseCalendar.Date) date.clone(); 1455 ndays = jcal.getMonthLength(d); 1456 d.setDayOfMonth(1); 1457 jcal.normalize(d); 1458 dow1 = d.getDayOfWeek(); 1459 int x = dow - dow1; 1460 if (x < 0) { 1461 x += 7; 1462 } 1463 ndays -= x; 1464 value = (ndays + 6) / 7; 1465 } 1466 break; 1467 1468 case YEAR: 1469 { 1470 CalendarDate jd = jcal.getCalendarDate(jc.getTimeInMillis(), getZone()); 1471 CalendarDate d; 1472 int eraIndex = getEraIndex(date); 1473 if (eraIndex == eras.length - 1) { 1474 d = jcal.getCalendarDate(Long.MAX_VALUE, getZone()); 1475 value = d.getYear(); 1476 if (value > 400) { 1479 jd.setYear(value - 400); 1480 } 1481 } else { 1482 d = jcal.getCalendarDate(eras[eraIndex + 1].getSince(getZone()) - 1, 1483 getZone()); 1484 value = d.getYear(); 1485 jd.setYear(value); 1488 } 1489 jcal.normalize(jd); 1490 if (getYearOffsetInMillis(jd) > getYearOffsetInMillis(d)) { 1491 value--; 1492 } 1493 } 1494 break; 1495 1496 default: 1497 throw new ArrayIndexOutOfBoundsException (field); 1498 } 1499 return value; 1500 } 1501 1502 1508 private final long getYearOffsetInMillis(CalendarDate date) { 1509 long t = (jcal.getDayOfYear(date) - 1) * ONE_DAY; 1510 return t + date.getTimeOfDay() - date.getZoneOffset(); 1511 } 1512 1513 public Object clone() { 1514 JapaneseImperialCalendar other = (JapaneseImperialCalendar ) super.clone(); 1515 1516 other.jdate = (LocalGregorianCalendar.Date) jdate.clone(); 1517 other.originalFields = null; 1518 other.zoneOffsets = null; 1519 return other; 1520 } 1521 1522 public TimeZone getTimeZone() { 1523 TimeZone zone = super.getTimeZone(); 1524 jdate.setZone(zone); 1526 return zone; 1527 } 1528 1529 public void setTimeZone(TimeZone zone) { 1530 super.setTimeZone(zone); 1531 jdate.setZone(zone); 1533 } 1534 1535 1539 transient private long cachedFixedDate = Long.MIN_VALUE; 1540 1541 1550 protected void computeFields() { 1551 int mask = 0; 1552 if (isPartiallyNormalized()) { 1553 mask = getSetStateFields(); 1555 int fieldMask = ~mask & ALL_FIELDS; 1556 if (fieldMask != 0 || cachedFixedDate == Long.MIN_VALUE) { 1557 mask |= computeFields(fieldMask, 1558 mask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK)); 1559 assert mask == ALL_FIELDS; 1560 } 1561 } else { 1562 mask = ALL_FIELDS; 1564 computeFields(mask, 0); 1565 } 1566 setFieldsComputed(mask); 1568 } 1569 1570 1584 private int computeFields(int fieldMask, int tzMask) { 1585 int zoneOffset = 0; 1586 TimeZone tz = getZone(); 1587 if (zoneOffsets == null) { 1588 zoneOffsets = new int[2]; 1589 } 1590 if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) { 1591 if (tz instanceof ZoneInfo) { 1592 zoneOffset = ((ZoneInfo)tz).getOffsets(time, zoneOffsets); 1593 } else { 1594 zoneOffset = tz.getOffset(time); 1595 zoneOffsets[0] = tz.getRawOffset(); 1596 zoneOffsets[1] = zoneOffset - zoneOffsets[0]; 1597 } 1598 } 1599 if (tzMask != 0) { 1600 if (isFieldSet(tzMask, ZONE_OFFSET)) { 1601 zoneOffsets[0] = internalGet(ZONE_OFFSET); 1602 } 1603 if (isFieldSet(tzMask, DST_OFFSET)) { 1604 zoneOffsets[1] = internalGet(DST_OFFSET); 1605 } 1606 zoneOffset = zoneOffsets[0] + zoneOffsets[1]; 1607 } 1608 1609 long fixedDate = zoneOffset / ONE_DAY; 1613 int timeOfDay = zoneOffset % (int)ONE_DAY; 1614 fixedDate += time / ONE_DAY; 1615 timeOfDay += (int) (time % ONE_DAY); 1616 if (timeOfDay >= ONE_DAY) { 1617 timeOfDay -= ONE_DAY; 1618 ++fixedDate; 1619 } else { 1620 while (timeOfDay < 0) { 1621 timeOfDay += ONE_DAY; 1622 --fixedDate; 1623 } 1624 } 1625 fixedDate += EPOCH_OFFSET; 1626 1627 if (fixedDate != cachedFixedDate || fixedDate < 0) { 1629 jcal.getCalendarDateFromFixedDate(jdate, fixedDate); 1630 cachedFixedDate = fixedDate; 1631 } 1632 int era = getEraIndex(jdate); 1633 int year = jdate.getYear(); 1634 1635 internalSet(ERA, era); 1637 internalSet(YEAR, year); 1638 int mask = fieldMask | (ERA_MASK|YEAR_MASK); 1639 1640 int month = jdate.getMonth() - 1; int dayOfMonth = jdate.getDayOfMonth(); 1642 1643 if ((fieldMask & (MONTH_MASK|DAY_OF_MONTH_MASK|DAY_OF_WEEK_MASK)) 1645 != 0) { 1646 internalSet(MONTH, month); 1647 internalSet(DAY_OF_MONTH, dayOfMonth); 1648 internalSet(DAY_OF_WEEK, jdate.getDayOfWeek()); 1649 mask |= MONTH_MASK|DAY_OF_MONTH_MASK|DAY_OF_WEEK_MASK; 1650 } 1651 1652 if ((fieldMask & (HOUR_OF_DAY_MASK|AM_PM_MASK|HOUR_MASK 1653 |MINUTE_MASK|SECOND_MASK|MILLISECOND_MASK)) != 0) { 1654 if (timeOfDay != 0) { 1655 int hours = timeOfDay / ONE_HOUR; 1656 internalSet(HOUR_OF_DAY, hours); 1657 internalSet(AM_PM, hours / 12); internalSet(HOUR, hours % 12); 1659 int r = timeOfDay % ONE_HOUR; 1660 internalSet(MINUTE, r / ONE_MINUTE); 1661 r %= ONE_MINUTE; 1662 internalSet(SECOND, r / ONE_SECOND); 1663 internalSet(MILLISECOND, r % ONE_SECOND); 1664 } else { 1665 internalSet(HOUR_OF_DAY, 0); 1666 internalSet(AM_PM, AM); 1667 internalSet(HOUR, 0); 1668 internalSet(MINUTE, 0); 1669 internalSet(SECOND, 0); 1670 internalSet(MILLISECOND, 0); 1671 } 1672 mask |= (HOUR_OF_DAY_MASK|AM_PM_MASK|HOUR_MASK 1673 |MINUTE_MASK|SECOND_MASK|MILLISECOND_MASK); 1674 } 1675 1676 if ((fieldMask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) != 0) { 1677 internalSet(ZONE_OFFSET, zoneOffsets[0]); 1678 internalSet(DST_OFFSET, zoneOffsets[1]); 1679 mask |= (ZONE_OFFSET_MASK|DST_OFFSET_MASK); 1680 } 1681 1682 if ((fieldMask & (DAY_OF_YEAR_MASK|WEEK_OF_YEAR_MASK 1683 |WEEK_OF_MONTH_MASK|DAY_OF_WEEK_IN_MONTH_MASK)) != 0) { 1684 int normalizedYear = jdate.getNormalizedYear(); 1685 boolean transitionYear = isTransitionYear(jdate.getNormalizedYear()); 1688 int dayOfYear; 1689 long fixedDateJan1; 1690 if (transitionYear) { 1691 fixedDateJan1 = getFixedDateJan1(jdate, fixedDate); 1692 dayOfYear = (int)(fixedDate - fixedDateJan1) + 1; 1693 } else if (normalizedYear == MIN_VALUES[YEAR]) { 1694 CalendarDate dx = jcal.getCalendarDate(Long.MIN_VALUE, getZone()); 1695 fixedDateJan1 = jcal.getFixedDate(dx); 1696 dayOfYear = (int)(fixedDate - fixedDateJan1) + 1; 1697 } else { 1698 dayOfYear = (int) jcal.getDayOfYear(jdate); 1699 fixedDateJan1 = fixedDate - dayOfYear + 1; 1700 } 1701 long fixedDateMonth1 = transitionYear ? 1702 getFixedDateMonth1(jdate, fixedDate) : fixedDate - dayOfMonth + 1; 1703 1704 internalSet(DAY_OF_YEAR, dayOfYear); 1705 internalSet(DAY_OF_WEEK_IN_MONTH, (dayOfMonth - 1) / 7 + 1); 1706 1707 int weekOfYear = getWeekNumber(fixedDateJan1, fixedDate); 1708 1709 if (weekOfYear == 0) { 1712 long fixedDec31 = fixedDateJan1 - 1; 1720 long prevJan1; 1721 LocalGregorianCalendar.Date d = getCalendarDate(fixedDec31); 1722 if (!(transitionYear || isTransitionYear(d.getNormalizedYear()))) { 1723 prevJan1 = fixedDateJan1 - 365; 1724 if (d.isLeapYear()) { 1725 --prevJan1; 1726 } 1727 } else if (transitionYear) { 1728 if (jdate.getYear() == 1) { 1729 if (era > HEISEI) { 1735 CalendarDate pd = eras[era - 1].getSinceDate(); 1736 if (normalizedYear == pd.getYear()) { 1737 d.setMonth(pd.getMonth()).setDayOfMonth(pd.getDayOfMonth()); 1738 } 1739 } else { 1740 d.setMonth(jcal.JANUARY).setDayOfMonth(1); 1741 } 1742 jcal.normalize(d); 1743 prevJan1 = jcal.getFixedDate(d); 1744 } else { 1745 prevJan1 = fixedDateJan1 - 365; 1746 if (d.isLeapYear()) { 1747 --prevJan1; 1748 } 1749 } 1750 } else { 1751 CalendarDate cd = eras[getEraIndex(jdate)].getSinceDate(); 1752 d.setMonth(cd.getMonth()).setDayOfMonth(cd.getDayOfMonth()); 1753 jcal.normalize(d); 1754 prevJan1 = jcal.getFixedDate(d); 1755 } 1756 weekOfYear = getWeekNumber(prevJan1, fixedDec31); 1757 } else { 1758 if (!transitionYear) { 1759 if (weekOfYear >= 52) { 1761 long nextJan1 = fixedDateJan1 + 365; 1762 if (jdate.isLeapYear()) { 1763 nextJan1++; 1764 } 1765 long nextJan1st = jcal.getDayOfWeekDateOnOrBefore(nextJan1 + 6, 1766 getFirstDayOfWeek()); 1767 int ndays = (int)(nextJan1st - nextJan1); 1768 if (ndays >= getMinimalDaysInFirstWeek() && fixedDate >= (nextJan1st - 7)) { 1769 weekOfYear = 1; 1771 } 1772 } 1773 } else { 1774 LocalGregorianCalendar.Date d = (LocalGregorianCalendar.Date) jdate.clone(); 1775 long nextJan1; 1776 if (jdate.getYear() == 1) { 1777 d.addYear(+1); 1778 d.setMonth(jcal.JANUARY).setDayOfMonth(1); 1779 nextJan1 = jcal.getFixedDate(d); 1780 } else { 1781 int nextEraIndex = getEraIndex(d) + 1; 1782 CalendarDate cd = eras[nextEraIndex].getSinceDate(); 1783 d.setEra(eras[nextEraIndex]); 1784 d.setDate(1, cd.getMonth(), cd.getDayOfMonth()); 1785 jcal.normalize(d); 1786 nextJan1 = jcal.getFixedDate(d); 1787 } 1788 long nextJan1st = jcal.getDayOfWeekDateOnOrBefore(nextJan1 + 6, 1789 getFirstDayOfWeek()); 1790 int ndays = (int)(nextJan1st - nextJan1); 1791 if (ndays >= getMinimalDaysInFirstWeek() && fixedDate >= (nextJan1st - 7)) { 1792 weekOfYear = 1; 1794 } 1795 } 1796 } 1797 internalSet(WEEK_OF_YEAR, weekOfYear); 1798 internalSet(WEEK_OF_MONTH, getWeekNumber(fixedDateMonth1, fixedDate)); 1799 mask |= (DAY_OF_YEAR_MASK|WEEK_OF_YEAR_MASK|WEEK_OF_MONTH_MASK|DAY_OF_WEEK_IN_MONTH_MASK); 1800 } 1801 return mask; 1802 } 1803 1804 1813 private final int getWeekNumber(long fixedDay1, long fixedDate) { 1814 long fixedDay1st = jcal.getDayOfWeekDateOnOrBefore(fixedDay1 + 6, 1817 getFirstDayOfWeek()); 1818 int ndays = (int)(fixedDay1st - fixedDay1); 1819 assert ndays <= 7; 1820 if (ndays >= getMinimalDaysInFirstWeek()) { 1821 fixedDay1st -= 7; 1822 } 1823 int normalizedDayOfPeriod = (int)(fixedDate - fixedDay1st); 1824 if (normalizedDayOfPeriod >= 0) { 1825 return normalizedDayOfPeriod / 7 + 1; 1826 } 1827 return CalendarUtils.floorDivide(normalizedDayOfPeriod, 7) + 1; 1828 } 1829 1830 1836 protected void computeTime() { 1837 if (!isLenient()) { 1842 if (originalFields == null) { 1843 originalFields = new int[FIELD_COUNT]; 1844 } 1845 for (int field = 0; field < FIELD_COUNT; field++) { 1846 int value = internalGet(field); 1847 if (isExternallySet(field)) { 1848 if (value < getMinimum(field) || value > getMaximum(field)) { 1850 throw new IllegalArgumentException (getFieldName(field)); 1851 } 1852 } 1853 originalFields[field] = value; 1854 } 1855 } 1856 1857 int fieldMask = selectFields(); 1860 1861 int year; 1862 int era; 1863 1864 if (isSet(ERA)) { 1865 era = internalGet(ERA); 1866 year = isSet(YEAR) ? internalGet(YEAR) : 1; 1867 } else { 1868 if (isSet(YEAR)) { 1869 era = eras.length - 1; 1870 year = internalGet(YEAR); 1871 } else { 1872 era = SHOWA; 1874 year = 45; 1875 } 1876 } 1877 1878 long timeOfDay = 0; 1881 if (isFieldSet(fieldMask, HOUR_OF_DAY)) { 1882 timeOfDay += (long) internalGet(HOUR_OF_DAY); 1883 } else { 1884 timeOfDay += internalGet(HOUR); 1885 if (isFieldSet(fieldMask, AM_PM)) { 1887 timeOfDay += 12 * internalGet(AM_PM); 1888 } 1889 } 1890 timeOfDay *= 60; 1891 timeOfDay += internalGet(MINUTE); 1892 timeOfDay *= 60; 1893 timeOfDay += internalGet(SECOND); 1894 timeOfDay *= 1000; 1895 timeOfDay += internalGet(MILLISECOND); 1896 1897 long fixedDate = timeOfDay / ONE_DAY; 1900 timeOfDay %= ONE_DAY; 1901 while (timeOfDay < 0) { 1902 timeOfDay += ONE_DAY; 1903 --fixedDate; 1904 } 1905 1906 fixedDate += getFixedDate(era, year, fieldMask); 1908 1909 long millis = (fixedDate - EPOCH_OFFSET) * ONE_DAY + timeOfDay; 1911 1912 TimeZone zone = getZone(); 1926 if (zoneOffsets == null) { 1927 zoneOffsets = new int[2]; 1928 } 1929 int tzMask = fieldMask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK); 1930 if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) { 1931 if (zone instanceof ZoneInfo) { 1932 ((ZoneInfo)zone).getOffsetsByWall(millis, zoneOffsets); 1933 } else { 1934 zone.getOffsets(millis - zone.getRawOffset(), zoneOffsets); 1935 } 1936 } 1937 if (tzMask != 0) { 1938 if (isFieldSet(tzMask, ZONE_OFFSET)) { 1939 zoneOffsets[0] = internalGet(ZONE_OFFSET); 1940 } 1941 if (isFieldSet(tzMask, DST_OFFSET)) { 1942 zoneOffsets[1] = internalGet(DST_OFFSET); 1943 } 1944 } 1945 1946 millis -= zoneOffsets[0] + zoneOffsets[1]; 1948 1949 time = millis; 1951 1952 int mask = computeFields(fieldMask | getSetStateFields(), tzMask); 1953 1954 if (!isLenient()) { 1955 for (int field = 0; field < FIELD_COUNT; field++) { 1956 if (!isExternallySet(field)) { 1957 continue; 1958 } 1959 if (originalFields[field] != internalGet(field)) { 1960 int wrongValue = internalGet(field); 1961 System.arraycopy(originalFields, 0, fields, 0, fields.length); 1963 throw new IllegalArgumentException (getFieldName(field) + "=" + wrongValue 1964 + ", expected " + originalFields[field]); 1965 } 1966 } 1967 } 1968 setFieldsNormalized(mask); 1969 } 1970 1971 1982 private long getFixedDate(int era, int year, int fieldMask) { 1983 int month = JANUARY; 1984 int firstDayOfMonth = 1; 1985 if (isFieldSet(fieldMask, MONTH)) { 1986 month = internalGet(MONTH); 1989 1990 if (month > DECEMBER) { 1992 year += month / 12; 1993 month %= 12; 1994 } else if (month < JANUARY) { 1995 int[] rem = new int[1]; 1996 year += CalendarUtils.floorDivide(month, 12, rem); 1997 month = rem[0]; 1998 } 1999 } else { 2000 if (year == 1 && era != 0) { 2001 CalendarDate d = eras[era].getSinceDate(); 2002 month = d.getMonth() - 1; 2003 firstDayOfMonth = d.getDayOfMonth(); 2004 } 2005 } 2006 2007 if (year == MIN_VALUES[YEAR]) { 2009 CalendarDate dx = jcal.getCalendarDate(Long.MIN_VALUE, getZone()); 2010 int m = dx.getMonth() - 1; 2011 if (month < m) 2012 month = m; 2013 if (month == m) 2014 firstDayOfMonth = dx.getDayOfMonth(); 2015 } 2016 2017 LocalGregorianCalendar.Date date = jcal.newCalendarDate(TimeZone.NO_TIMEZONE); 2018 date.setEra(era > 0 ? eras[era] : null); 2019 date.setDate(year, month + 1, firstDayOfMonth); 2020 jcal.normalize(date); 2021 2022 long fixedDate = jcal.getFixedDate(date); 2025 2026 if (isFieldSet(fieldMask, MONTH)) { 2027 if (isFieldSet(fieldMask, DAY_OF_MONTH)) { 2029 if (isSet(DAY_OF_MONTH)) { 2036 fixedDate += internalGet(DAY_OF_MONTH); 2039 fixedDate -= firstDayOfMonth; 2040 } 2041 } else { 2042 if (isFieldSet(fieldMask, WEEK_OF_MONTH)) { 2043 long firstDayOfWeek = jcal.getDayOfWeekDateOnOrBefore(fixedDate + 6, 2044 getFirstDayOfWeek()); 2045 if ((firstDayOfWeek - fixedDate) >= getMinimalDaysInFirstWeek()) { 2048 firstDayOfWeek -= 7; 2049 } 2050 if (isFieldSet(fieldMask, DAY_OF_WEEK)) { 2051 firstDayOfWeek = jcal.getDayOfWeekDateOnOrBefore(firstDayOfWeek + 6, 2052 internalGet(DAY_OF_WEEK)); 2053 } 2054 fixedDate = firstDayOfWeek + 7 * (internalGet(WEEK_OF_MONTH) - 1); 2058 } else { 2059 int dayOfWeek; 2060 if (isFieldSet(fieldMask, DAY_OF_WEEK)) { 2061 dayOfWeek = internalGet(DAY_OF_WEEK); 2062 } else { 2063 dayOfWeek = getFirstDayOfWeek(); 2064 } 2065 int dowim; 2069 if (isFieldSet(fieldMask, DAY_OF_WEEK_IN_MONTH)) { 2070 dowim = internalGet(DAY_OF_WEEK_IN_MONTH); 2071 } else { 2072 dowim = 1; 2073 } 2074 if (dowim >= 0) { 2075 fixedDate = jcal.getDayOfWeekDateOnOrBefore(fixedDate + (7 * dowim) - 1, 2076 dayOfWeek); 2077 } else { 2078 int lastDate = monthLength(month, year) + (7 * (dowim + 1)); 2081 fixedDate = jcal.getDayOfWeekDateOnOrBefore(fixedDate + lastDate - 1, 2083 dayOfWeek); 2084 } 2085 } 2086 } 2087 } else { 2088 if (isFieldSet(fieldMask, DAY_OF_YEAR)) { 2090 if (isTransitionYear(date.getNormalizedYear())) { 2091 fixedDate = getFixedDateJan1(date, fixedDate); 2092 } 2093 fixedDate += internalGet(DAY_OF_YEAR); 2095 fixedDate--; 2096 } else { 2097 long firstDayOfWeek = jcal.getDayOfWeekDateOnOrBefore(fixedDate + 6, 2098 getFirstDayOfWeek()); 2099 if ((firstDayOfWeek - fixedDate) >= getMinimalDaysInFirstWeek()) { 2102 firstDayOfWeek -= 7; 2103 } 2104 if (isFieldSet(fieldMask, DAY_OF_WEEK)) { 2105 int dayOfWeek = internalGet(DAY_OF_WEEK); 2106 if (dayOfWeek != getFirstDayOfWeek()) { 2107 firstDayOfWeek = jcal.getDayOfWeekDateOnOrBefore(firstDayOfWeek + 6, 2108 dayOfWeek); 2109 } 2110 } 2111 fixedDate = firstDayOfWeek + 7 * ((long)internalGet(WEEK_OF_YEAR) - 1); 2112 } 2113 } 2114 return fixedDate; 2115 } 2116 2117 2125 private final long getFixedDateJan1(LocalGregorianCalendar.Date date, long fixedDate) { 2126 Era era = date.getEra(); 2127 if (date.getEra() != null && date.getYear() == 1) { 2128 for (int eraIndex = getEraIndex(date); eraIndex > 0; eraIndex--) { 2129 CalendarDate d = eras[eraIndex].getSinceDate(); 2130 long fd = gcal.getFixedDate(d); 2131 if (fd > fixedDate) { 2133 continue; 2134 } 2135 return fd; 2136 } 2137 } 2138 CalendarDate d = gcal.newCalendarDate(TimeZone.NO_TIMEZONE); 2139 d.setDate(date.getNormalizedYear(), gcal.JANUARY, 1); 2140 return gcal.getFixedDate(d); 2141 } 2142 2143 2151 private final long getFixedDateMonth1(LocalGregorianCalendar.Date date, 2152 long fixedDate) { 2153 int eraIndex = getTransitionEraIndex(date); 2154 if (eraIndex != -1) { 2155 long transition = sinceFixedDates[eraIndex]; 2156 if (transition <= fixedDate) { 2159 return transition; 2160 } 2161 } 2162 2163 return fixedDate - date.getDayOfMonth() + 1; 2165 } 2166 2167 2172 private static final LocalGregorianCalendar.Date getCalendarDate(long fd) { 2173 LocalGregorianCalendar.Date d = jcal.newCalendarDate(TimeZone.NO_TIMEZONE); 2174 jcal.getCalendarDateFromFixedDate(d, fd); 2175 return d; 2176 } 2177 2178 2184 private final int monthLength(int month, int gregorianYear) { 2185 return CalendarUtils.isGregorianLeapYear(gregorianYear) ? 2186 GregorianCalendar.LEAP_MONTH_LENGTH[month] : GregorianCalendar.MONTH_LENGTH[month]; 2187 } 2188 2189 2195 private final int monthLength(int month) { 2196 assert jdate.isNormalized(); 2197 return jdate.isLeapYear() ? 2198 GregorianCalendar.LEAP_MONTH_LENGTH[month] : GregorianCalendar.MONTH_LENGTH[month]; 2199 } 2200 2201 private final int actualMonthLength() { 2202 int length = jcal.getMonthLength(jdate); 2203 int eraIndex = getTransitionEraIndex(jdate); 2204 if (eraIndex == -1) { 2205 long transitionFixedDate = sinceFixedDates[eraIndex]; 2206 CalendarDate d = eras[eraIndex].getSinceDate(); 2207 if (transitionFixedDate <= cachedFixedDate) { 2208 length -= d.getDayOfMonth() - 1; 2209 } else { 2210 length = d.getDayOfMonth() - 1; 2211 } 2212 } 2213 return length; 2214 } 2215 2216 2224 private static final int getTransitionEraIndex(LocalGregorianCalendar.Date date) { 2225 int eraIndex = getEraIndex(date); 2226 CalendarDate transitionDate = eras[eraIndex].getSinceDate(); 2227 if (transitionDate.getYear() == date.getNormalizedYear() && 2228 transitionDate.getMonth() == date.getMonth()) { 2229 return eraIndex; 2230 } 2231 if (eraIndex < eras.length - 1) { 2232 transitionDate = eras[++eraIndex].getSinceDate(); 2233 if (transitionDate.getYear() == date.getNormalizedYear() && 2234 transitionDate.getMonth() == date.getMonth()) { 2235 return eraIndex; 2236 } 2237 } 2238 return -1; 2239 } 2240 2241 private final boolean isTransitionYear(int normalizedYear) { 2242 for (int i = eras.length - 1; i > 0; i--) { 2243 int transitionYear = eras[i].getSinceDate().getYear(); 2244 if (normalizedYear == transitionYear) { 2245 return true; 2246 } 2247 if (normalizedYear > transitionYear) { 2248 break; 2249 } 2250 } 2251 return false; 2252 } 2253 2254 private static final int getEraIndex(LocalGregorianCalendar.Date date) { 2255 Era era = date.getEra(); 2256 for (int i = eras.length - 1; i > 0; i--) { 2257 if (eras[i] == era) { 2258 return i; 2259 } 2260 } 2261 return 0; 2262 } 2263 2264 2269 private final JapaneseImperialCalendar getNormalizedCalendar() { 2270 JapaneseImperialCalendar jc; 2271 if (isFullyNormalized()) { 2272 jc = this; 2273 } else { 2274 jc = (JapaneseImperialCalendar ) this.clone(); 2276 jc.setLenient(true); 2277 jc.complete(); 2278 } 2279 return jc; 2280 } 2281 2282 2288 private final void pinDayOfMonth(LocalGregorianCalendar.Date date) { 2289 int year = date.getYear(); 2290 int dom = date.getDayOfMonth(); 2291 if (year != getMinimum(YEAR)) { 2292 date.setDayOfMonth(1); 2293 jcal.normalize(date); 2294 int monthLength = jcal.getMonthLength(date); 2295 if (dom > monthLength) { 2296 date.setDayOfMonth(monthLength); 2297 } else { 2298 date.setDayOfMonth(dom); 2299 } 2300 jcal.normalize(date); 2301 } else { 2302 LocalGregorianCalendar.Date d = jcal.getCalendarDate(Long.MIN_VALUE, getZone()); 2303 LocalGregorianCalendar.Date realDate = jcal.getCalendarDate(time, getZone()); 2304 long tod = realDate.getTimeOfDay(); 2305 realDate.addYear(+400); 2307 realDate.setMonth(date.getMonth()); 2308 realDate.setDayOfMonth(1); 2309 jcal.normalize(realDate); 2310 int monthLength = jcal.getMonthLength(realDate); 2311 if (dom > monthLength) { 2312 realDate.setDayOfMonth(monthLength); 2313 } else { 2314 if (dom < d.getDayOfMonth()) { 2315 realDate.setDayOfMonth(d.getDayOfMonth()); 2316 } else { 2317 realDate.setDayOfMonth(dom); 2318 } 2319 } 2320 if (realDate.getDayOfMonth() == d.getDayOfMonth() && tod < d.getTimeOfDay()) { 2321 realDate.setDayOfMonth(Math.min(dom + 1, monthLength)); 2322 } 2323 date.setDate(year, realDate.getMonth(), realDate.getDayOfMonth()); 2325 } 2327 } 2328 2329 2332 private static final int getRolledValue(int value, int amount, int min, int max) { 2333 assert value >= min && value <= max; 2334 int range = max - min + 1; 2335 amount %= range; 2336 int n = value + amount; 2337 if (n > max) { 2338 n -= range; 2339 } else if (n < min) { 2340 n += range; 2341 } 2342 assert n >= min && n <= max; 2343 return n; 2344 } 2345 2346 2350 private final int internalGetEra() { 2351 return isSet(ERA) ? internalGet(ERA) : eras.length - 1; 2352 } 2353 2354 2357 private void readObject(ObjectInputStream stream) 2358 throws IOException , ClassNotFoundException { 2359 stream.defaultReadObject(); 2360 if (jdate == null) { 2361 jdate = jcal.newCalendarDate(getZone()); 2362 cachedFixedDate = Long.MIN_VALUE; 2363 } 2364 } 2365} 2366 | Popular Tags |