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