1 7 8 20 21 package java.util; 22 23 import java.io.IOException ; 24 import java.io.ObjectInputStream ; 25 import sun.util.calendar.BaseCalendar; 26 import sun.util.calendar.CalendarDate; 27 import sun.util.calendar.CalendarSystem; 28 import sun.util.calendar.CalendarUtils; 29 import sun.util.calendar.Era; 30 import sun.util.calendar.Gregorian; 31 import sun.util.calendar.JulianCalendar; 32 import sun.util.calendar.ZoneInfo; 33 34 282 public class GregorianCalendar extends Calendar { 283 308 309 313 321 public static final int BC = 0; 322 323 329 static final int BCE = 0; 330 331 339 public static final int AD = 1; 340 341 347 static final int CE = 1; 348 349 private static final int EPOCH_OFFSET = 719163; private static final int EPOCH_YEAR = 1970; 351 352 static final int MONTH_LENGTH[] 353 = {31,28,31,30,31,30,31,31,30,31,30,31}; static final int LEAP_MONTH_LENGTH[] 355 = {31,29,31,30,31,30,31,31,30,31,30,31}; 357 private static final int ONE_SECOND = 1000; 361 private static final int ONE_MINUTE = 60*ONE_SECOND; 362 private static final int ONE_HOUR = 60*ONE_MINUTE; 363 private static final long ONE_DAY = 24*ONE_HOUR; 364 private static final long ONE_WEEK = 7*ONE_DAY; 365 366 391 static final int MIN_VALUES[] = { 392 BCE, 1, JANUARY, 1, 0, 1, 1, SUNDAY, 1, AM, 0, 0, 0, 0, 0, -13*ONE_HOUR, 0 }; 410 static final int LEAST_MAX_VALUES[] = { 411 CE, 292269054, DECEMBER, 52, 4, 28, 365, SATURDAY, 4, PM, 11, 23, 59, 59, 999, 14*ONE_HOUR, 20*ONE_MINUTE }; 429 static final int MAX_VALUES[] = { 430 CE, 292278994, DECEMBER, 53, 6, 31, 366, SATURDAY, 6, PM, 11, 23, 59, 59, 999, 14*ONE_HOUR, 2*ONE_HOUR }; 448 449 static final long serialVersionUID = -8125100834729963327L; 451 452 private static final Gregorian gcal = 454 CalendarSystem.getGregorianCalendar(); 455 456 private static JulianCalendar jcal; 459 460 private static Era[] jeras; 462 463 static final long DEFAULT_GREGORIAN_CUTOVER = -12219292800000L; 465 466 470 478 private long gregorianCutover = DEFAULT_GREGORIAN_CUTOVER; 479 480 483 private transient long gregorianCutoverDate = 484 (((DEFAULT_GREGORIAN_CUTOVER + 1)/ONE_DAY) - 1) + EPOCH_OFFSET; 486 490 private transient int gregorianCutoverYear = 1582; 491 492 496 private transient int gregorianCutoverYearJulian = 1582; 497 498 503 private transient BaseCalendar.Date gdate; 504 505 510 private transient BaseCalendar.Date cdate; 511 512 517 private transient BaseCalendar calsys; 518 519 524 private transient int[] zoneOffsets; 525 526 530 private transient int[] originalFields; 531 532 536 540 public GregorianCalendar() { 541 this(TimeZone.getDefaultRef(), Locale.getDefault()); 542 setZoneShared(true); 543 } 544 545 551 public GregorianCalendar(TimeZone zone) { 552 this(zone, Locale.getDefault()); 553 } 554 555 561 public GregorianCalendar(Locale aLocale) { 562 this(TimeZone.getDefaultRef(), aLocale); 563 setZoneShared(true); 564 } 565 566 573 public GregorianCalendar(TimeZone zone, Locale aLocale) { 574 super(zone, aLocale); 575 gdate = (BaseCalendar.Date) gcal.newCalendarDate(zone); 576 setTimeInMillis(System.currentTimeMillis()); 577 } 578 579 588 public GregorianCalendar(int year, int month, int dayOfMonth) { 589 this(year, month, dayOfMonth, 0, 0, 0, 0); 590 } 591 592 605 public GregorianCalendar(int year, int month, int dayOfMonth, int hourOfDay, 606 int minute) { 607 this(year, month, dayOfMonth, hourOfDay, minute, 0, 0); 608 } 609 610 625 public GregorianCalendar(int year, int month, int dayOfMonth, int hourOfDay, 626 int minute, int second) { 627 this(year, month, dayOfMonth, hourOfDay, minute, second, 0); 628 } 629 630 646 GregorianCalendar(int year, int month, int dayOfMonth, 647 int hourOfDay, int minute, int second, int millis) { 648 super(); 649 gdate = (BaseCalendar.Date) gcal.newCalendarDate(getZone()); 650 this.set(YEAR, year); 651 this.set(MONTH, month); 652 this.set(DAY_OF_MONTH, dayOfMonth); 653 654 if (hourOfDay >= 12 && hourOfDay <= 23) { 657 this.internalSet(AM_PM, PM); 661 this.internalSet(HOUR, hourOfDay - 12); 662 } else { 663 this.internalSet(HOUR, hourOfDay); 666 } 667 setFieldsComputed(HOUR_MASK|AM_PM_MASK); 669 670 this.set(HOUR_OF_DAY, hourOfDay); 671 this.set(MINUTE, minute); 672 this.set(SECOND, second); 673 this.internalSet(MILLISECOND, millis); 676 } 677 678 682 693 public void setGregorianChange(Date date) { 694 long cutoverTime = date.getTime(); 695 if (cutoverTime == gregorianCutover) { 696 return; 697 } 698 complete(); 701 setGregorianChange(cutoverTime); 702 } 703 704 private void setGregorianChange(long cutoverTime) { 705 gregorianCutover = cutoverTime; 706 gregorianCutoverDate = CalendarUtils.floorDivide(cutoverTime, ONE_DAY) 707 + EPOCH_OFFSET; 708 709 if (cutoverTime == Long.MAX_VALUE) { 715 gregorianCutoverDate++; 716 } 717 718 BaseCalendar.Date d = getGregorianCutoverDate(); 719 720 gregorianCutoverYear = d.getYear(); 722 723 BaseCalendar jcal = getJulianCalendarSystem(); 724 d = (BaseCalendar.Date) jcal.newCalendarDate(TimeZone.NO_TIMEZONE); 725 jcal.getCalendarDateFromFixedDate(d, gregorianCutoverDate - 1); 726 gregorianCutoverYearJulian = d.getNormalizedYear(); 727 728 if (time < gregorianCutover) { 729 setUnnormalized(); 732 } 733 } 734 735 743 public final Date getGregorianChange() { 744 return new Date (gregorianCutover); 745 } 746 747 756 public boolean isLeapYear(int year) { 757 if ((year & 3) != 0) { 758 return false; 759 } 760 761 if (year > gregorianCutoverYear) { 762 return (year%100 != 0) || (year%400 == 0); } 764 if (year < gregorianCutoverYearJulian) { 765 return true; } 767 boolean gregorian; 768 if (gregorianCutoverYear == gregorianCutoverYearJulian) { 771 BaseCalendar.Date d = getCalendarDate(gregorianCutoverDate); gregorian = d.getMonth() < BaseCalendar.MARCH; 773 } else { 774 gregorian = year == gregorianCutoverYear; 775 } 776 return gregorian ? (year%100 != 0) || (year%400 == 0) : true; 777 } 778 779 793 public boolean equals(Object obj) { 794 return obj instanceof GregorianCalendar && 795 super.equals(obj) && 796 gregorianCutover == ((GregorianCalendar )obj).gregorianCutover; 797 } 798 799 802 public int hashCode() { 803 return super.hashCode() ^ (int)gregorianCutoverDate; 804 } 805 806 834 public void add(int field, int amount) { 835 if (amount == 0) { 838 return; } 840 841 if (field < 0 || field >= ZONE_OFFSET) { 842 throw new IllegalArgumentException (); 843 } 844 845 complete(); 847 848 if (field == YEAR) { 849 int year = internalGet(YEAR); 850 if (internalGetEra() == CE) { 851 year += amount; 852 if (year > 0) { 853 set(YEAR, year); 854 } else { set(YEAR, 1 - year); 856 set(ERA, BCE); 858 } 859 } 860 else { year -= amount; 862 if (year > 0) { 863 set(YEAR, year); 864 } else { set(YEAR, 1 - year); 866 set(ERA, CE); 868 } 869 } 870 pinDayOfMonth(); 871 } else if (field == MONTH) { 872 int month = internalGet(MONTH) + amount; 873 int year = internalGet(YEAR); 874 int y_amount; 875 876 if (month >= 0) { 877 y_amount = month/12; 878 } else { 879 y_amount = (month+1)/12 - 1; 880 } 881 if (y_amount != 0) { 882 if (internalGetEra() == CE) { 883 year += y_amount; 884 if (year > 0) { 885 set(YEAR, year); 886 } else { set(YEAR, 1 - year); 888 set(ERA, BCE); 890 } 891 } 892 else { year -= y_amount; 894 if (year > 0) { 895 set(YEAR, year); 896 } else { set(YEAR, 1 - year); 898 set(ERA, CE); 900 } 901 } 902 } 903 904 if (month >= 0) { 905 set(MONTH, (int) (month % 12)); 906 } else { 907 month %= 12; 909 if (month < 0) { 910 month += 12; 911 } 912 set(MONTH, JANUARY + month); 913 } 914 pinDayOfMonth(); 915 } else if (field == ERA) { 916 int era = internalGet(ERA) + amount; 917 if (era < 0) { 918 era = 0; 919 } 920 if (era > 1) { 921 era = 1; 922 } 923 set(ERA, era); 924 } else { 925 long delta = amount; 926 long timeOfDay = 0; 927 switch (field) { 928 case HOUR: 931 case HOUR_OF_DAY: 932 delta *= 60 * 60 * 1000; break; 934 935 case MINUTE: 936 delta *= 60 * 1000; break; 938 939 case SECOND: 940 delta *= 1000; break; 942 943 case MILLISECOND: 944 break; 945 946 case WEEK_OF_YEAR: 950 case WEEK_OF_MONTH: 951 case DAY_OF_WEEK_IN_MONTH: 952 delta *= 7; 953 break; 954 955 case DAY_OF_MONTH: case DAY_OF_YEAR: 957 case DAY_OF_WEEK: 958 break; 959 960 case AM_PM: 961 delta = amount / 2; 964 timeOfDay = 12 * (amount % 2); 965 break; 966 } 967 968 if (field >= HOUR) { 971 setTimeInMillis(time + delta); 972 return; 973 } 974 975 979 long fd = getCurrentFixedDate(); 982 timeOfDay += internalGet(HOUR_OF_DAY); 983 timeOfDay *= 60; 984 timeOfDay += internalGet(MINUTE); 985 timeOfDay *= 60; 986 timeOfDay += internalGet(SECOND); 987 timeOfDay *= 1000; 988 timeOfDay += internalGet(MILLISECOND); 989 if (timeOfDay >= ONE_DAY) { 990 fd++; 991 timeOfDay -= ONE_DAY; 992 } else if (timeOfDay < 0) { 993 fd--; 994 timeOfDay += ONE_DAY; 995 } 996 997 fd += delta; int zoneOffset = internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET); 999 setTimeInMillis((fd - EPOCH_OFFSET) * ONE_DAY + timeOfDay - zoneOffset); 1000 zoneOffset -= internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET); 1001 if (zoneOffset != 0) { 1003 setTimeInMillis(time + zoneOffset); 1004 long fd2 = getCurrentFixedDate(); 1005 if (fd2 != fd) { 1008 setTimeInMillis(time - zoneOffset); 1009 } 1010 } 1011 } 1012 } 1013 1014 1032 public void roll(int field, boolean up) { 1033 roll(field, up ? +1 : -1); 1034 } 1035 1036 1080 public void roll(int field, int amount) { 1081 if (amount == 0) { 1084 return; 1085 } 1086 1087 if (field < 0 || field >= ZONE_OFFSET) { 1088 throw new IllegalArgumentException (); 1089 } 1090 1091 complete(); 1093 1094 int min = getMinimum(field); 1095 int max = getMaximum(field); 1096 1097 switch (field) { 1098 case AM_PM: 1099 case ERA: 1100 case YEAR: 1101 case MINUTE: 1102 case SECOND: 1103 case MILLISECOND: 1104 break; 1109 1110 case HOUR: 1111 case HOUR_OF_DAY: 1112 { 1113 int unit = max + 1; int h = internalGet(field); 1115 int nh = (h + amount) % unit; 1116 if (nh < 0) { 1117 nh += unit; 1118 } 1119 time += ONE_HOUR * (nh - h); 1120 1121 CalendarDate d = calsys.getCalendarDate(time, getZone()); 1126 if (internalGet(DAY_OF_MONTH) != d.getDayOfMonth()) { 1127 d.setDate(internalGet(YEAR), 1128 internalGet(MONTH) + 1, 1129 internalGet(DAY_OF_MONTH)); 1130 if (field == HOUR) { 1131 assert (internalGet(AM_PM) == PM); 1132 d.addHours(+12); } 1134 time = calsys.getTime(d); 1135 } 1136 int hourOfDay = d.getHours(); 1137 internalSet(field, hourOfDay % unit); 1138 if (field == HOUR) { 1139 internalSet(HOUR_OF_DAY, hourOfDay); 1140 } else { 1141 internalSet(AM_PM, hourOfDay / 12); 1142 internalSet(HOUR, hourOfDay % 12); 1143 } 1144 1145 int zoneOffset = d.getZoneOffset(); 1147 int saving = d.getDaylightSaving(); 1148 internalSet(ZONE_OFFSET, zoneOffset - saving); 1149 internalSet(DST_OFFSET, saving); 1150 return; 1151 } 1152 1153 case MONTH: 1154 { 1159 if (!isCutoverYear(cdate.getNormalizedYear())) { 1160 int mon = (internalGet(MONTH) + amount) % 12; 1161 if (mon < 0) { 1162 mon += 12; 1163 } 1164 set(MONTH, mon); 1165 1166 int monthLen = monthLength(mon); 1170 if (internalGet(DAY_OF_MONTH) > monthLen) { 1171 set(DAY_OF_MONTH, monthLen); 1172 } 1173 } else { 1174 int yearLength = getActualMaximum(MONTH) + 1; 1177 int mon = (internalGet(MONTH) + amount) % yearLength; 1178 if (mon < 0) { 1179 mon += yearLength; 1180 } 1181 set(MONTH, mon); 1182 int monthLen = getActualMaximum(DAY_OF_MONTH); 1183 if (internalGet(DAY_OF_MONTH) > monthLen) { 1184 set(DAY_OF_MONTH, monthLen); 1185 } 1186 } 1187 return; 1188 } 1189 1190 case WEEK_OF_YEAR: 1191 { 1192 int y = cdate.getNormalizedYear(); 1193 max = getActualMaximum(WEEK_OF_YEAR); 1194 set(DAY_OF_WEEK, internalGet(DAY_OF_WEEK)); 1195 int woy = internalGet(WEEK_OF_YEAR); 1196 int value = woy + amount; 1197 if (!isCutoverYear(y)) { 1198 if (value > min && value < max) { 1201 set(WEEK_OF_YEAR, value); 1202 return; 1203 } 1204 long fd = getCurrentFixedDate(); 1205 long day1 = fd - (7 * (woy - min)); 1207 if (calsys.getYearFromFixedDate(day1) != y) { 1208 min++; 1209 } 1210 1211 fd += 7 * (max - internalGet(WEEK_OF_YEAR)); 1213 if (calsys.getYearFromFixedDate(fd) != y) { 1214 max--; 1215 } 1216 break; 1217 } 1218 1219 long fd = getCurrentFixedDate(); 1221 BaseCalendar cal; 1222 if (gregorianCutoverYear == gregorianCutoverYearJulian) { 1223 cal = getCutoverCalendarSystem(); 1224 } else if (y == gregorianCutoverYear) { 1225 cal = gcal; 1226 } else { 1227 cal = getJulianCalendarSystem(); 1228 } 1229 long day1 = fd - (7 * (woy - min)); 1230 if (cal.getYearFromFixedDate(day1) != y) { 1232 min++; 1233 } 1234 1235 fd += 7 * (max - woy); 1237 cal = (fd >= gregorianCutoverDate) ? gcal : getJulianCalendarSystem(); 1238 if (cal.getYearFromFixedDate(fd) != y) { 1239 max--; 1240 } 1241 value = getRolledValue(woy, amount, min, max) - 1; 1244 BaseCalendar.Date d = getCalendarDate(day1 + value * 7); 1245 set(MONTH, d.getMonth() - 1); 1246 set(DAY_OF_MONTH, d.getDayOfMonth()); 1247 return; 1248 } 1249 1250 case WEEK_OF_MONTH: 1251 { 1252 boolean isCutoverYear = isCutoverYear(cdate.getNormalizedYear()); 1253 int dow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek(); 1255 if (dow < 0) { 1256 dow += 7; 1257 } 1258 1259 long fd = getCurrentFixedDate(); 1260 long month1; int monthLength; if (isCutoverYear) { 1263 month1 = getFixedDateMonth1(cdate, fd); 1264 monthLength = actualMonthLength(); 1265 } else { 1266 month1 = fd - internalGet(DAY_OF_MONTH) + 1; 1267 monthLength = calsys.getMonthLength(cdate); 1268 } 1269 1270 long monthDay1st = calsys.getDayOfWeekDateOnOrBefore(month1 + 6, 1272 getFirstDayOfWeek()); 1273 if ((int)(monthDay1st - month1) >= getMinimalDaysInFirstWeek()) { 1276 monthDay1st -= 7; 1277 } 1278 max = getActualMaximum(field); 1279 1280 int value = getRolledValue(internalGet(field), amount, 1, max) - 1; 1282 1283 long nfd = monthDay1st + value * 7 + dow; 1285 1286 if (nfd < month1) { 1289 nfd = month1; 1290 } else if (nfd >= (month1 + monthLength)) { 1291 nfd = month1 + monthLength - 1; 1292 } 1293 int dayOfMonth; 1294 if (isCutoverYear) { 1295 BaseCalendar.Date d = getCalendarDate(nfd); 1298 dayOfMonth = d.getDayOfMonth(); 1299 } else { 1300 dayOfMonth = (int)(nfd - month1) + 1; 1301 } 1302 set(DAY_OF_MONTH, dayOfMonth); 1303 return; 1304 } 1305 1306 case DAY_OF_MONTH: 1307 { 1308 if (!isCutoverYear(cdate.getNormalizedYear())) { 1309 max = calsys.getMonthLength(cdate); 1310 break; 1311 } 1312 1313 long fd = getCurrentFixedDate(); 1315 long month1 = getFixedDateMonth1(cdate, fd); 1316 int value = getRolledValue((int)(fd - month1), amount, 0, actualMonthLength() - 1); 1320 BaseCalendar.Date d = getCalendarDate(month1 + value); 1321 assert d.getMonth()-1 == internalGet(MONTH); 1322 set(DAY_OF_MONTH, d.getDayOfMonth()); 1323 return; 1324 } 1325 1326 case DAY_OF_YEAR: 1327 { 1328 max = getActualMaximum(field); 1329 if (!isCutoverYear(cdate.getNormalizedYear())) { 1330 break; 1331 } 1332 1333 long fd = getCurrentFixedDate(); 1335 long jan1 = fd - internalGet(DAY_OF_YEAR) + 1; 1336 int value = getRolledValue((int)(fd - jan1) + 1, amount, min, max); 1337 BaseCalendar.Date d = getCalendarDate(jan1 + value - 1); 1338 set(MONTH, d.getMonth() - 1); 1339 set(DAY_OF_MONTH, d.getDayOfMonth()); 1340 return; 1341 } 1342 1343 case DAY_OF_WEEK: 1344 { 1345 if (!isCutoverYear(cdate.getNormalizedYear())) { 1346 int weekOfYear = internalGet(WEEK_OF_YEAR); 1349 if (weekOfYear > 1 && weekOfYear < 52) { 1350 set(WEEK_OF_YEAR, weekOfYear); max = SATURDAY; 1352 break; 1353 } 1354 } 1355 1356 amount %= 7; 1361 if (amount == 0) { 1362 return; 1363 } 1364 long fd = getCurrentFixedDate(); 1365 long dowFirst = calsys.getDayOfWeekDateOnOrBefore(fd, getFirstDayOfWeek()); 1366 fd += amount; 1367 if (fd < dowFirst) { 1368 fd += 7; 1369 } else if (fd >= dowFirst + 7) { 1370 fd -= 7; 1371 } 1372 BaseCalendar.Date d = getCalendarDate(fd); 1373 set(ERA, (d.getNormalizedYear() <= 0 ? BCE : CE)); 1374 set(d.getYear(), d.getMonth() - 1, d.getDayOfMonth()); 1375 return; 1376 } 1377 1378 case DAY_OF_WEEK_IN_MONTH: 1379 { 1380 min = 1; if (!isCutoverYear(cdate.getNormalizedYear())) { 1382 int dom = internalGet(DAY_OF_MONTH); 1383 int monthLength = calsys.getMonthLength(cdate); 1384 int lastDays = monthLength % 7; 1385 max = monthLength / 7; 1386 int x = (dom - 1) % 7; 1387 if (x < lastDays) { 1388 max++; 1389 } 1390 set(DAY_OF_WEEK, internalGet(DAY_OF_WEEK)); 1391 break; 1392 } 1393 1394 long fd = getCurrentFixedDate(); 1396 long month1 = getFixedDateMonth1(cdate, fd); 1397 int monthLength = actualMonthLength(); 1398 int lastDays = monthLength % 7; 1399 max = monthLength / 7; 1400 int x = (int)(fd - month1) % 7; 1401 if (x < lastDays) { 1402 max++; 1403 } 1404 int value = getRolledValue(internalGet(field), amount, min, max) - 1; 1405 fd = month1 + value * 7 + x; 1406 BaseCalendar cal = (fd >= gregorianCutoverDate) ? gcal : getJulianCalendarSystem(); 1407 BaseCalendar.Date d = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.NO_TIMEZONE); 1408 cal.getCalendarDateFromFixedDate(d, fd); 1409 set(DAY_OF_MONTH, d.getDayOfMonth()); 1410 return; 1411 } 1412 } 1413 1414 set(field, getRolledValue(internalGet(field), amount, min, max)); 1415 } 1416 1417 1436 public int getMinimum(int field) { 1437 return MIN_VALUES[field]; 1438 } 1439 1440 1459 public int getMaximum(int field) { 1460 switch (field) { 1461 case MONTH: 1462 case DAY_OF_MONTH: 1463 case DAY_OF_YEAR: 1464 case WEEK_OF_YEAR: 1465 case WEEK_OF_MONTH: 1466 case DAY_OF_WEEK_IN_MONTH: 1467 case YEAR: 1468 { 1469 if (gregorianCutoverYear > 200) { 1473 break; 1474 } 1475 GregorianCalendar gc = (GregorianCalendar ) clone(); 1477 gc.setLenient(true); 1478 gc.setTimeInMillis(gregorianCutover); 1479 int v1 = gc.getActualMaximum(field); 1480 gc.setTimeInMillis(gregorianCutover-1); 1481 int v2 = gc.getActualMaximum(field); 1482 return Math.max(MAX_VALUES[field], Math.max(v1, v2)); 1483 } 1484 } 1485 return MAX_VALUES[field]; 1486 } 1487 1488 1507 public int getGreatestMinimum(int field) { 1508 if (field == DAY_OF_MONTH) { 1509 BaseCalendar.Date d = getGregorianCutoverDate(); 1510 long mon1 = getFixedDateMonth1(d, gregorianCutoverDate); 1511 d = getCalendarDate(mon1); 1512 return Math.max(MIN_VALUES[field], d.getDayOfMonth()); 1513 } 1514 return MIN_VALUES[field]; 1515 } 1516 1517 1536 public int getLeastMaximum(int field) { 1537 switch (field) { 1538 case MONTH: 1539 case DAY_OF_MONTH: 1540 case DAY_OF_YEAR: 1541 case WEEK_OF_YEAR: 1542 case WEEK_OF_MONTH: 1543 case DAY_OF_WEEK_IN_MONTH: 1544 case YEAR: 1545 { 1546 GregorianCalendar gc = (GregorianCalendar ) clone(); 1547 gc.setLenient(true); 1548 gc.setTimeInMillis(gregorianCutover); 1549 int v1 = gc.getActualMaximum(field); 1550 gc.setTimeInMillis(gregorianCutover-1); 1551 int v2 = gc.getActualMaximum(field); 1552 return Math.min(LEAST_MAX_VALUES[field], Math.min(v1, v2)); 1553 } 1554 } 1555 return LEAST_MAX_VALUES[field]; 1556 } 1557 1558 1585 public int getActualMinimum(int field) { 1586 if (field == DAY_OF_MONTH) { 1587 GregorianCalendar gc = getNormalizedCalendar(); 1588 int year = gc.cdate.getNormalizedYear(); 1589 if (year == gregorianCutoverYear || year == gregorianCutoverYearJulian) { 1590 long month1 = getFixedDateMonth1(gc.cdate, gc.calsys.getFixedDate(gc.cdate)); 1591 BaseCalendar.Date d = getCalendarDate(month1); 1592 return d.getDayOfMonth(); 1593 } 1594 } 1595 return getMinimum(field); 1596 } 1597 1598 1621 public int getActualMaximum(int field) { 1622 final int fieldsForFixedMax = ERA_MASK|DAY_OF_WEEK_MASK|HOUR_MASK|AM_PM_MASK| 1623 HOUR_OF_DAY_MASK|MINUTE_MASK|SECOND_MASK|MILLISECOND_MASK| 1624 ZONE_OFFSET_MASK|DST_OFFSET_MASK; 1625 if ((fieldsForFixedMax & (1<<field)) != 0) { 1626 return getMaximum(field); 1627 } 1628 1629 GregorianCalendar gc = getNormalizedCalendar(); 1630 BaseCalendar.Date date = gc.cdate; 1631 BaseCalendar cal = gc.calsys; 1632 int normalizedYear = date.getNormalizedYear(); 1633 1634 int value = -1; 1635 switch (field) { 1636 case MONTH: 1637 { 1638 if (!gc.isCutoverYear(normalizedYear)) { 1639 value = DECEMBER; 1640 break; 1641 } 1642 1643 long nextJan1; 1645 do { 1646 nextJan1 = gcal.getFixedDate(++normalizedYear, BaseCalendar.JANUARY, 1, null); 1647 } while (nextJan1 < gregorianCutoverDate); 1648 BaseCalendar.Date d = (BaseCalendar.Date) date.clone(); 1649 cal.getCalendarDateFromFixedDate(d, nextJan1 - 1); 1650 value = d.getMonth() - 1; 1651 } 1652 break; 1653 1654 case DAY_OF_MONTH: 1655 { 1656 value = cal.getMonthLength(date); 1657 if (!gc.isCutoverYear(normalizedYear) || date.getDayOfMonth() == value) { 1658 break; 1659 } 1660 1661 long fd = gc.getCurrentFixedDate(); 1663 if (fd >= gregorianCutoverDate) { 1664 break; 1665 } 1666 int monthLength = gc.actualMonthLength(); 1667 long monthEnd = gc.getFixedDateMonth1(gc.cdate, fd) + monthLength - 1; 1668 BaseCalendar.Date d = gc.getCalendarDate(monthEnd); 1670 value = d.getDayOfMonth(); 1671 } 1672 break; 1673 1674 case DAY_OF_YEAR: 1675 { 1676 if (!gc.isCutoverYear(normalizedYear)) { 1677 value = cal.getYearLength(date); 1678 break; 1679 } 1680 1681 long jan1; 1683 if (gregorianCutoverYear == gregorianCutoverYearJulian) { 1684 BaseCalendar cocal = gc.getCutoverCalendarSystem(); 1685 jan1 = cocal.getFixedDate(normalizedYear, 1, 1, null); 1686 } else if (normalizedYear == gregorianCutoverYearJulian) { 1687 jan1 = cal.getFixedDate(normalizedYear, 1, 1, null); 1688 } else { 1689 jan1 = gregorianCutoverDate; 1690 } 1691 long nextJan1 = gcal.getFixedDate(++normalizedYear, 1, 1, null); 1693 if (nextJan1 < gregorianCutoverDate) { 1694 nextJan1 = gregorianCutoverDate; 1695 } 1696 assert jan1 <= cal.getFixedDate(date.getNormalizedYear(), date.getMonth(), 1697 date.getDayOfMonth(), date); 1698 assert nextJan1 >= cal.getFixedDate(date.getNormalizedYear(), date.getMonth(), 1699 date.getDayOfMonth(), date); 1700 value = (int)(nextJan1 - jan1); 1701 } 1702 break; 1703 1704 case WEEK_OF_YEAR: 1705 { 1706 if (!gc.isCutoverYear(normalizedYear)) { 1707 CalendarDate d = cal.newCalendarDate(TimeZone.NO_TIMEZONE); 1709 d.setDate(date.getYear(), BaseCalendar.JANUARY, 1); 1710 int dayOfWeek = cal.getDayOfWeek(d); 1711 dayOfWeek -= getFirstDayOfWeek(); 1713 if (dayOfWeek < 0) { 1714 dayOfWeek += 7; 1715 } 1716 value = 52; 1717 int magic = dayOfWeek + getMinimalDaysInFirstWeek() - 1; 1718 if ((magic == 6) || 1719 (date.isLeapYear() && (magic == 5 || magic == 12))) { 1720 value++; 1721 } 1722 break; 1723 } 1724 1725 if (gc == this) { 1726 gc = (GregorianCalendar ) gc.clone(); 1727 } 1728 gc.set(DAY_OF_YEAR, getActualMaximum(DAY_OF_YEAR)); 1729 value = gc.get(WEEK_OF_YEAR); 1730 } 1731 break; 1732 1733 case WEEK_OF_MONTH: 1734 { 1735 if (!gc.isCutoverYear(normalizedYear)) { 1736 CalendarDate d = cal.newCalendarDate(null); 1737 d.setDate(date.getYear(), date.getMonth(), 1); 1738 int dayOfWeek = cal.getDayOfWeek(d); 1739 int monthLength = cal.getMonthLength(d); 1740 dayOfWeek -= getFirstDayOfWeek(); 1741 if (dayOfWeek < 0) { 1742 dayOfWeek += 7; 1743 } 1744 int nDaysFirstWeek = 7 - dayOfWeek; value = 3; 1746 if (nDaysFirstWeek >= getMinimalDaysInFirstWeek()) { 1747 value++; 1748 } 1749 monthLength -= nDaysFirstWeek + 7 * 3; 1750 if (monthLength > 0) { 1751 value++; 1752 if (monthLength > 7) { 1753 value++; 1754 } 1755 } 1756 break; 1757 } 1758 1759 if (gc == this) { 1761 gc = (GregorianCalendar ) gc.clone(); 1762 } 1763 int y = gc.internalGet(YEAR); 1764 int m = gc.internalGet(MONTH); 1765 do { 1766 value = gc.get(WEEK_OF_MONTH); 1767 gc.add(WEEK_OF_MONTH, +1); 1768 } while (gc.get(YEAR) == y && gc.get(MONTH) == m); 1769 } 1770 break; 1771 1772 case DAY_OF_WEEK_IN_MONTH: 1773 { 1774 int ndays, dow1; 1776 int dow = date.getDayOfWeek(); 1777 if (!gc.isCutoverYear(normalizedYear)) { 1778 BaseCalendar.Date d = (BaseCalendar.Date) date.clone(); 1779 ndays = cal.getMonthLength(d); 1780 d.setDayOfMonth(1); 1781 cal.normalize(d); 1782 dow1 = d.getDayOfWeek(); 1783 } else { 1784 if (gc == this) { 1786 gc = (GregorianCalendar ) clone(); 1787 } 1788 ndays = gc.actualMonthLength(); 1789 gc.set(DAY_OF_MONTH, gc.getActualMinimum(DAY_OF_MONTH)); 1790 dow1 = gc.get(DAY_OF_WEEK); 1791 } 1792 int x = dow - dow1; 1793 if (x < 0) { 1794 x += 7; 1795 } 1796 ndays -= x; 1797 value = (ndays + 6) / 7; 1798 } 1799 break; 1800 1801 case YEAR: 1802 1821 { 1822 if (gc == this) { 1823 gc = (GregorianCalendar ) clone(); 1824 } 1825 1826 long current = gc.getYearOffsetInMillis(); 1831 1832 if (gc.internalGetEra() == CE) { 1833 gc.setTimeInMillis(Long.MAX_VALUE); 1834 value = gc.get(YEAR); 1835 long maxEnd = gc.getYearOffsetInMillis(); 1836 if (current > maxEnd) { 1837 value--; 1838 } 1839 } else { 1840 CalendarSystem mincal = gc.getTimeInMillis() >= gregorianCutover ? 1841 gcal : getJulianCalendarSystem(); 1842 CalendarDate d = mincal.getCalendarDate(Long.MIN_VALUE, getZone()); 1843 long maxEnd = (cal.getDayOfYear(d) - 1) * 24 + d.getHours(); 1844 maxEnd *= 60; 1845 maxEnd += d.getMinutes(); 1846 maxEnd *= 60; 1847 maxEnd += d.getSeconds(); 1848 maxEnd *= 1000; 1849 maxEnd += d.getMillis(); 1850 value = d.getYear(); 1851 if (value <= 0) { 1852 assert mincal == gcal; 1853 value = 1 - value; 1854 } 1855 if (current < maxEnd) { 1856 value--; 1857 } 1858 } 1859 } 1860 break; 1861 1862 default: 1863 throw new ArrayIndexOutOfBoundsException (field); 1864 } 1865 return value; 1866 } 1867 1868 1872 private final long getYearOffsetInMillis() { 1873 long t = (internalGet(DAY_OF_YEAR) - 1) * 24; 1874 t += internalGet(HOUR_OF_DAY); 1875 t *= 60; 1876 t += internalGet(MINUTE); 1877 t *= 60; 1878 t += internalGet(SECOND); 1879 t *= 1000; 1880 return t + internalGet(MILLISECOND) - 1881 (internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET)); 1882 } 1883 1884 public Object clone() 1885 { 1886 GregorianCalendar other = (GregorianCalendar ) super.clone(); 1887 1888 other.gdate = (BaseCalendar.Date) gdate.clone(); 1889 if (cdate != null) { 1890 if (cdate != gdate) { 1891 other.cdate = (BaseCalendar.Date) cdate.clone(); 1892 } else { 1893 other.cdate = other.gdate; 1894 } 1895 } 1896 other.originalFields = null; 1897 other.zoneOffsets = null; 1898 return other; 1899 } 1900 1901 public TimeZone getTimeZone() { 1902 TimeZone zone = super.getTimeZone(); 1903 gdate.setZone(zone); 1905 if (cdate != null && cdate != gdate) { 1906 cdate.setZone(zone); 1907 } 1908 return zone; 1909 } 1910 1911 public void setTimeZone(TimeZone zone) { 1912 super.setTimeZone(zone); 1913 gdate.setZone(zone); 1915 if (cdate != null && cdate != gdate) { 1916 cdate.setZone(zone); 1917 } 1918 } 1919 1920 1924 1941 1959 1960 1961 1965 1970 transient private long cachedFixedDate = Long.MIN_VALUE; 1971 1972 1981 protected void computeFields() { 1982 int mask = 0; 1983 if (isPartiallyNormalized()) { 1984 mask = getSetStateFields(); 1986 int fieldMask = ~mask & ALL_FIELDS; 1987 if (fieldMask != 0 || calsys == null) { 1990 mask |= computeFields(fieldMask, 1991 mask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK)); 1992 assert mask == ALL_FIELDS; 1993 } 1994 } else { 1995 mask = ALL_FIELDS; 1996 computeFields(mask, 0); 1997 } 1998 setFieldsComputed(mask); 2000 } 2001 2002 2016 private int computeFields(int fieldMask, int tzMask) { 2017 int zoneOffset = 0; 2018 TimeZone tz = getZone(); 2019 if (zoneOffsets == null) { 2020 zoneOffsets = new int[2]; 2021 } 2022 if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) { 2023 if (tz instanceof ZoneInfo) { 2024 zoneOffset = ((ZoneInfo)tz).getOffsets(time, zoneOffsets); 2025 } else { 2026 zoneOffset = tz.getOffset(time); 2027 zoneOffsets[0] = tz.getRawOffset(); 2028 zoneOffsets[1] = zoneOffset - zoneOffsets[0]; 2029 } 2030 } 2031 if (tzMask != 0) { 2032 if (isFieldSet(tzMask, ZONE_OFFSET)) { 2033 zoneOffsets[0] = internalGet(ZONE_OFFSET); 2034 } 2035 if (isFieldSet(tzMask, DST_OFFSET)) { 2036 zoneOffsets[1] = internalGet(DST_OFFSET); 2037 } 2038 zoneOffset = zoneOffsets[0] + zoneOffsets[1]; 2039 } 2040 2041 long fixedDate = zoneOffset / ONE_DAY; 2045 int timeOfDay = zoneOffset % (int)ONE_DAY; 2046 fixedDate += time / ONE_DAY; 2047 timeOfDay += (int) (time % ONE_DAY); 2048 if (timeOfDay >= ONE_DAY) { 2049 timeOfDay -= ONE_DAY; 2050 ++fixedDate; 2051 } else { 2052 while (timeOfDay < 0) { 2053 timeOfDay += ONE_DAY; 2054 --fixedDate; 2055 } 2056 } 2057 fixedDate += EPOCH_OFFSET; 2058 2059 int era = CE; 2060 int year; 2061 if (fixedDate >= gregorianCutoverDate) { 2062 assert cachedFixedDate == Long.MIN_VALUE || gdate.isNormalized() 2064 : "cache control: not normalized"; 2065 assert cachedFixedDate == Long.MIN_VALUE || 2066 gcal.getFixedDate(gdate.getNormalizedYear(), 2067 gdate.getMonth(), 2068 gdate.getDayOfMonth(), gdate) 2069 == cachedFixedDate 2070 : "cache control: inconsictency" + 2071 ", cachedFixedDate=" + cachedFixedDate + 2072 ", computed=" + 2073 gcal.getFixedDate(gdate.getNormalizedYear(), 2074 gdate.getMonth(), 2075 gdate.getDayOfMonth(), 2076 gdate) + 2077 ", date=" + gdate; 2078 2079 if (fixedDate != cachedFixedDate) { 2081 gcal.getCalendarDateFromFixedDate(gdate, fixedDate); 2082 cachedFixedDate = fixedDate; 2083 } 2084 2085 year = gdate.getYear(); 2086 if (year <= 0) { 2087 year = 1 - year; 2088 era = BCE; 2089 } 2090 calsys = gcal; 2091 cdate = gdate; 2092 assert cdate.getDayOfWeek() > 0 : "dow="+cdate.getDayOfWeek()+", date="+cdate; 2093 } else { 2094 calsys = getJulianCalendarSystem(); 2096 cdate = (BaseCalendar.Date) jcal.newCalendarDate(getZone()); 2097 jcal.getCalendarDateFromFixedDate(cdate, fixedDate); 2098 Era e = cdate.getEra(); 2099 if (e == jeras[0]) { 2100 era = BCE; 2101 } 2102 year = cdate.getYear(); 2103 } 2104 2105 internalSet(ERA, era); 2107 internalSet(YEAR, year); 2108 int mask = fieldMask | (ERA_MASK|YEAR_MASK); 2109 2110 int month = cdate.getMonth() - 1; int dayOfMonth = cdate.getDayOfMonth(); 2112 2113 if ((fieldMask & (MONTH_MASK|DAY_OF_MONTH_MASK|DAY_OF_WEEK_MASK)) 2115 != 0) { 2116 internalSet(MONTH, month); 2117 internalSet(DAY_OF_MONTH, dayOfMonth); 2118 internalSet(DAY_OF_WEEK, cdate.getDayOfWeek()); 2119 mask |= MONTH_MASK|DAY_OF_MONTH_MASK|DAY_OF_WEEK_MASK; 2120 } 2121 2122 if ((fieldMask & (HOUR_OF_DAY_MASK|AM_PM_MASK|HOUR_MASK 2123 |MINUTE_MASK|SECOND_MASK|MILLISECOND_MASK)) != 0) { 2124 if (timeOfDay != 0) { 2125 int hours = timeOfDay / ONE_HOUR; 2126 internalSet(HOUR_OF_DAY, hours); 2127 internalSet(AM_PM, hours / 12); internalSet(HOUR, hours % 12); 2129 int r = timeOfDay % ONE_HOUR; 2130 internalSet(MINUTE, r / ONE_MINUTE); 2131 r %= ONE_MINUTE; 2132 internalSet(SECOND, r / ONE_SECOND); 2133 internalSet(MILLISECOND, r % ONE_SECOND); 2134 } else { 2135 internalSet(HOUR_OF_DAY, 0); 2136 internalSet(AM_PM, AM); 2137 internalSet(HOUR, 0); 2138 internalSet(MINUTE, 0); 2139 internalSet(SECOND, 0); 2140 internalSet(MILLISECOND, 0); 2141 } 2142 mask |= (HOUR_OF_DAY_MASK|AM_PM_MASK|HOUR_MASK 2143 |MINUTE_MASK|SECOND_MASK|MILLISECOND_MASK); 2144 } 2145 2146 if ((fieldMask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) != 0) { 2147 internalSet(ZONE_OFFSET, zoneOffsets[0]); 2148 internalSet(DST_OFFSET, zoneOffsets[1]); 2149 mask |= (ZONE_OFFSET_MASK|DST_OFFSET_MASK); 2150 } 2151 2152 if ((fieldMask & (DAY_OF_YEAR_MASK|WEEK_OF_YEAR_MASK|WEEK_OF_MONTH_MASK|DAY_OF_WEEK_IN_MONTH_MASK)) != 0) { 2153 int normalizedYear = cdate.getNormalizedYear(); 2154 long fixedDateJan1 = calsys.getFixedDate(normalizedYear, 1, 1, cdate); 2155 int dayOfYear = (int)(fixedDate - fixedDateJan1) + 1; 2156 long fixedDateMonth1 = fixedDate - dayOfMonth + 1; 2157 int cutoverGap = 0; 2158 int cutoverYear = (calsys == gcal) ? gregorianCutoverYear : gregorianCutoverYearJulian; 2159 int relativeDayOfMonth = dayOfMonth - 1; 2160 2161 if (normalizedYear == cutoverYear) { 2163 if (getCutoverCalendarSystem() == jcal) { 2165 fixedDateJan1 = getFixedDateJan1(cdate, fixedDate); 2169 if (fixedDate >= gregorianCutoverDate) { 2170 fixedDateMonth1 = getFixedDateMonth1(cdate, fixedDate); 2171 } 2172 } 2173 int realDayOfYear = (int)(fixedDate - fixedDateJan1) + 1; 2174 cutoverGap = dayOfYear - realDayOfYear; 2175 dayOfYear = realDayOfYear; 2176 relativeDayOfMonth = (int)(fixedDate - fixedDateMonth1); 2177 } 2178 internalSet(DAY_OF_YEAR, dayOfYear); 2179 internalSet(DAY_OF_WEEK_IN_MONTH, relativeDayOfMonth / 7 + 1); 2180 2181 int weekOfYear = getWeekNumber(fixedDateJan1, fixedDate); 2182 2183 if (weekOfYear == 0) { 2186 long fixedDec31 = fixedDateJan1 - 1; 2194 long prevJan1; 2195 if (normalizedYear > (cutoverYear + 1)) { 2196 prevJan1 = fixedDateJan1 - 365; 2197 if (CalendarUtils.isGregorianLeapYear(normalizedYear - 1)) { 2198 --prevJan1; 2199 } 2200 } else { 2201 BaseCalendar calForJan1 = calsys; 2202 int prevYear = normalizedYear - 1; 2203 if (prevYear == cutoverYear) { 2204 calForJan1 = getCutoverCalendarSystem(); 2205 } 2206 prevJan1 = calForJan1.getFixedDate(prevYear, 2207 BaseCalendar.JANUARY, 2208 1, 2209 null); 2210 while (prevJan1 > fixedDec31) { 2211 prevJan1 = getJulianCalendarSystem().getFixedDate(--prevYear, 2212 BaseCalendar.JANUARY, 2213 1, 2214 null); 2215 } 2216 } 2217 weekOfYear = getWeekNumber(prevJan1, fixedDec31); 2218 } else { 2219 if (normalizedYear > gregorianCutoverYear || 2220 normalizedYear < (gregorianCutoverYearJulian - 1)) { 2221 if (weekOfYear >= 52) { 2223 long nextJan1 = fixedDateJan1 + 365; 2224 if (cdate.isLeapYear()) { 2225 nextJan1++; 2226 } 2227 long nextJan1st = calsys.getDayOfWeekDateOnOrBefore(nextJan1 + 6, 2228 getFirstDayOfWeek()); 2229 int ndays = (int)(nextJan1st - nextJan1); 2230 if (ndays >= getMinimalDaysInFirstWeek() && fixedDate >= (nextJan1st - 7)) { 2231 weekOfYear = 1; 2233 } 2234 } 2235 } else { 2236 BaseCalendar calForJan1 = calsys; 2237 int nextYear = normalizedYear + 1; 2238 if (nextYear == (gregorianCutoverYearJulian + 1) && 2239 nextYear < gregorianCutoverYear) { 2240 nextYear = gregorianCutoverYear; 2242 } 2243 if (nextYear == gregorianCutoverYear) { 2244 calForJan1 = getCutoverCalendarSystem(); 2245 } 2246 long nextJan1 = calForJan1.getFixedDate(nextYear, 2247 BaseCalendar.JANUARY, 2248 1, 2249 null); 2250 if (nextJan1 < fixedDate) { 2251 nextJan1 = gregorianCutoverDate; 2252 calForJan1 = gcal; 2253 } 2254 long nextJan1st = calForJan1.getDayOfWeekDateOnOrBefore(nextJan1 + 6, 2255 getFirstDayOfWeek()); 2256 int ndays = (int)(nextJan1st - nextJan1); 2257 if (ndays >= getMinimalDaysInFirstWeek() && fixedDate >= (nextJan1st - 7)) { 2258 weekOfYear = 1; 2260 } 2261 } 2262 } 2263 internalSet(WEEK_OF_YEAR, weekOfYear); 2264 internalSet(WEEK_OF_MONTH, getWeekNumber(fixedDateMonth1, fixedDate)); 2265 mask |= (DAY_OF_YEAR_MASK|WEEK_OF_YEAR_MASK|WEEK_OF_MONTH_MASK|DAY_OF_WEEK_IN_MONTH_MASK); 2266 } 2267 return mask; 2268 } 2269 2270 2279 private final int getWeekNumber(long fixedDay1, long fixedDate) { 2280 long fixedDay1st = gcal.getDayOfWeekDateOnOrBefore(fixedDay1 + 6, 2283 getFirstDayOfWeek()); 2284 int ndays = (int)(fixedDay1st - fixedDay1); 2285 assert ndays <= 7; 2286 if (ndays >= getMinimalDaysInFirstWeek()) { 2287 fixedDay1st -= 7; 2288 } 2289 int normalizedDayOfPeriod = (int)(fixedDate - fixedDay1st); 2290 if (normalizedDayOfPeriod >= 0) { 2291 return normalizedDayOfPeriod / 7 + 1; 2292 } 2293 return CalendarUtils.floorDivide(normalizedDayOfPeriod, 7) + 1; 2294 } 2295 2296 2302 protected void computeTime() { 2303 if (!isLenient()) { 2308 if (originalFields == null) { 2309 originalFields = new int[FIELD_COUNT]; 2310 } 2311 for (int field = 0; field < FIELD_COUNT; field++) { 2312 int value = internalGet(field); 2313 if (isExternallySet(field)) { 2314 if (value < getMinimum(field) || value > getMaximum(field)) { 2316 throw new IllegalArgumentException (getFieldName(field)); 2317 } 2318 } 2319 originalFields[field] = value; 2320 } 2321 } 2322 2323 int fieldMask = selectFields(); 2326 2327 int year = isSet(YEAR) ? internalGet(YEAR) : EPOCH_YEAR; 2331 2332 int era = internalGetEra(); 2333 if (era == BCE) { 2334 year = 1 - year; 2335 } else if (era != CE) { 2336 throw new IllegalArgumentException ("Invalid era"); 2341 } 2342 2343 if (year <= 0 && !isSet(ERA)) { 2345 fieldMask |= ERA_MASK; 2346 setFieldsComputed(ERA_MASK); 2347 } 2348 2349 long timeOfDay = 0; 2352 if (isFieldSet(fieldMask, HOUR_OF_DAY)) { 2353 timeOfDay += (long) internalGet(HOUR_OF_DAY); 2354 } else { 2355 timeOfDay += internalGet(HOUR); 2356 if (isFieldSet(fieldMask, AM_PM)) { 2358 timeOfDay += 12 * internalGet(AM_PM); 2359 } 2360 } 2361 timeOfDay *= 60; 2362 timeOfDay += internalGet(MINUTE); 2363 timeOfDay *= 60; 2364 timeOfDay += internalGet(SECOND); 2365 timeOfDay *= 1000; 2366 timeOfDay += internalGet(MILLISECOND); 2367 2368 long fixedDate = timeOfDay / ONE_DAY; 2371 timeOfDay %= ONE_DAY; 2372 while (timeOfDay < 0) { 2373 timeOfDay += ONE_DAY; 2374 --fixedDate; 2375 } 2376 2377 calculateFixedDate: { 2379 long gfd, jfd; 2380 if (year > gregorianCutoverYear && year > gregorianCutoverYearJulian) { 2381 gfd = fixedDate + getFixedDate(gcal, year, fieldMask); 2382 if (gfd >= gregorianCutoverDate) { 2383 fixedDate = gfd; 2384 break calculateFixedDate; 2385 } 2386 jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask); 2387 } else if (year < gregorianCutoverYear && year < gregorianCutoverYearJulian) { 2388 jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask); 2389 if (jfd < gregorianCutoverDate) { 2390 fixedDate = jfd; 2391 break calculateFixedDate; 2392 } 2393 gfd = fixedDate + getFixedDate(gcal, year, fieldMask); 2394 } else { 2395 gfd = fixedDate + getFixedDate(gcal, year, fieldMask); 2396 jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask); 2397 } 2398 if (gfd >= gregorianCutoverDate) { 2400 if (jfd >= gregorianCutoverDate) { 2401 fixedDate = gfd; 2402 } else { 2403 if (calsys == gcal || calsys == null) { 2407 fixedDate = gfd; 2408 } else { 2409 fixedDate = jfd; 2410 } 2411 } 2412 } else { 2413 if (jfd < gregorianCutoverDate) { 2414 fixedDate = jfd; 2415 } else { 2416 if (!isLenient()) { 2418 throw new IllegalArgumentException ("the specified date doesn't exist"); 2419 } 2420 fixedDate = jfd; 2423 } 2424 } 2425 } 2426 2427 long millis = (fixedDate - EPOCH_OFFSET) * ONE_DAY + timeOfDay; 2429 2430 TimeZone zone = getZone(); 2444 if (zoneOffsets == null) { 2445 zoneOffsets = new int[2]; 2446 } 2447 int tzMask = fieldMask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK); 2448 if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) { 2449 if (zone instanceof ZoneInfo) { 2450 ((ZoneInfo)zone).getOffsetsByWall(millis, zoneOffsets); 2451 } else { 2452 int gmtOffset = isFieldSet(fieldMask, ZONE_OFFSET) ? 2453 internalGet(ZONE_OFFSET) : zone.getRawOffset(); 2454 zone.getOffsets(millis - gmtOffset, zoneOffsets); 2455 } 2456 } 2457 if (tzMask != 0) { 2458 if (isFieldSet(tzMask, ZONE_OFFSET)) { 2459 zoneOffsets[0] = internalGet(ZONE_OFFSET); 2460 } 2461 if (isFieldSet(tzMask, DST_OFFSET)) { 2462 zoneOffsets[1] = internalGet(DST_OFFSET); 2463 } 2464 } 2465 2466 millis -= zoneOffsets[0] + zoneOffsets[1]; 2468 2469 time = millis; 2471 2472 int mask = computeFields(fieldMask | getSetStateFields(), tzMask); 2473 2474 if (!isLenient()) { 2475 for (int field = 0; field < FIELD_COUNT; field++) { 2476 if (!isExternallySet(field)) { 2477 continue; 2478 } 2479 if (originalFields[field] != internalGet(field)) { 2480 System.arraycopy(originalFields, 0, fields, 0, fields.length); 2482 throw new IllegalArgumentException (getFieldName(field)); 2483 } 2484 } 2485 } 2486 setFieldsNormalized(mask); 2487 } 2488 2489 2500 private long getFixedDate(BaseCalendar cal, int year, int fieldMask) { 2501 int month = JANUARY; 2502 if (isFieldSet(fieldMask, MONTH)) { 2503 month = internalGet(MONTH); 2506 2507 if (month > DECEMBER) { 2509 year += month / 12; 2510 month %= 12; 2511 } else if (month < JANUARY) { 2512 int[] rem = new int[1]; 2513 year += CalendarUtils.floorDivide(month, 12, rem); 2514 month = rem[0]; 2515 } 2516 } 2517 2518 long fixedDate = cal.getFixedDate(year, month + 1, 1, 2521 cal == gcal ? gdate : null); 2522 if (isFieldSet(fieldMask, MONTH)) { 2523 if (isFieldSet(fieldMask, DAY_OF_MONTH)) { 2525 if (isSet(DAY_OF_MONTH)) { 2532 fixedDate += internalGet(DAY_OF_MONTH); 2535 fixedDate--; 2536 } 2537 } else { 2538 if (isFieldSet(fieldMask, WEEK_OF_MONTH)) { 2539 long firstDayOfWeek = cal.getDayOfWeekDateOnOrBefore(fixedDate + 6, 2540 getFirstDayOfWeek()); 2541 if ((firstDayOfWeek - fixedDate) >= getMinimalDaysInFirstWeek()) { 2544 firstDayOfWeek -= 7; 2545 } 2546 if (isFieldSet(fieldMask, DAY_OF_WEEK)) { 2547 firstDayOfWeek = cal.getDayOfWeekDateOnOrBefore(firstDayOfWeek + 6, 2548 internalGet(DAY_OF_WEEK)); 2549 } 2550 fixedDate = firstDayOfWeek + 7 * (internalGet(WEEK_OF_MONTH) - 1); 2554 } else { 2555 int dayOfWeek; 2556 if (isFieldSet(fieldMask, DAY_OF_WEEK)) { 2557 dayOfWeek = internalGet(DAY_OF_WEEK); 2558 } else { 2559 dayOfWeek = getFirstDayOfWeek(); 2560 } 2561 int dowim; 2565 if (isFieldSet(fieldMask, DAY_OF_WEEK_IN_MONTH)) { 2566 dowim = internalGet(DAY_OF_WEEK_IN_MONTH); 2567 } else { 2568 dowim = 1; 2569 } 2570 if (dowim >= 0) { 2571 fixedDate = cal.getDayOfWeekDateOnOrBefore(fixedDate + (7 * dowim) - 1, 2572 dayOfWeek); 2573 } else { 2574 int lastDate = monthLength(month, year) + (7 * (dowim + 1)); 2577 fixedDate = cal.getDayOfWeekDateOnOrBefore(fixedDate + lastDate - 1, 2579 dayOfWeek); 2580 } 2581 } 2582 } 2583 } else { 2584 if (year == gregorianCutoverYear && cal == gcal 2585 && fixedDate < gregorianCutoverDate 2586 && gregorianCutoverYear != gregorianCutoverYearJulian) { 2587 fixedDate = gregorianCutoverDate; 2591 } 2592 if (isFieldSet(fieldMask, DAY_OF_YEAR)) { 2594 fixedDate += internalGet(DAY_OF_YEAR); 2596 fixedDate--; 2597 } else { 2598 long firstDayOfWeek = cal.getDayOfWeekDateOnOrBefore(fixedDate + 6, 2599 getFirstDayOfWeek()); 2600 if ((firstDayOfWeek - fixedDate) >= getMinimalDaysInFirstWeek()) { 2603 firstDayOfWeek -= 7; 2604 } 2605 if (isFieldSet(fieldMask, DAY_OF_WEEK)) { 2606 int dayOfWeek = internalGet(DAY_OF_WEEK); 2607 if (dayOfWeek != getFirstDayOfWeek()) { 2608 firstDayOfWeek = cal.getDayOfWeekDateOnOrBefore(firstDayOfWeek + 6, 2609 dayOfWeek); 2610 } 2611 } 2612 fixedDate = firstDayOfWeek + 7 * ((long)internalGet(WEEK_OF_YEAR) - 1); 2613 } 2614 } 2615 2616 return fixedDate; 2617 } 2618 2619 2624 private final GregorianCalendar getNormalizedCalendar() { 2625 GregorianCalendar gc; 2626 if (isFullyNormalized()) { 2627 gc = this; 2628 } else { 2629 gc = (GregorianCalendar ) this.clone(); 2631 gc.setLenient(true); 2632 gc.complete(); 2633 } 2634 return gc; 2635 } 2636 2637 2641 synchronized private static final BaseCalendar getJulianCalendarSystem() { 2642 if (jcal == null) { 2643 jcal = (JulianCalendar) CalendarSystem.forName("julian"); 2644 jeras = jcal.getEras(); 2645 } 2646 return jcal; 2647 } 2648 2649 2654 private BaseCalendar getCutoverCalendarSystem() { 2655 CalendarDate date = getGregorianCutoverDate(); 2656 if (date.getMonth() == BaseCalendar.JANUARY 2657 && date.getDayOfMonth() == 1) { 2658 return gcal; 2659 } 2660 return getJulianCalendarSystem(); 2661 } 2662 2663 2667 private final boolean isCutoverYear(int normalizedYear) { 2668 int cutoverYear = (calsys == gcal) ? gregorianCutoverYear : gregorianCutoverYearJulian; 2669 return normalizedYear == cutoverYear; 2670 } 2671 2672 2681 private final long getFixedDateJan1(BaseCalendar.Date date, long fixedDate) { 2682 assert date.getNormalizedYear() == gregorianCutoverYear || 2683 date.getNormalizedYear() == gregorianCutoverYearJulian; 2684 if (gregorianCutoverYear != gregorianCutoverYearJulian) { 2685 if (fixedDate >= gregorianCutoverDate) { 2686 return gregorianCutoverDate; 2691 } 2692 } 2693 BaseCalendar jcal = getJulianCalendarSystem(); 2695 return jcal.getFixedDate(date.getNormalizedYear(), BaseCalendar.JANUARY, 1, null); 2696 } 2697 2698 2707 private final long getFixedDateMonth1(BaseCalendar.Date date, long fixedDate) { 2708 assert date.getNormalizedYear() == gregorianCutoverYear || 2709 date.getNormalizedYear() == gregorianCutoverYearJulian; 2710 BaseCalendar.Date gCutover = getGregorianCutoverDate(); 2711 if (gCutover.getMonth() == BaseCalendar.JANUARY 2712 && gCutover.getDayOfMonth() == 1) { 2713 return fixedDate - date.getDayOfMonth() + 1; 2715 } 2716 2717 long fixedDateMonth1; 2718 if (date.getMonth() == gCutover.getMonth()) { 2720 BaseCalendar.Date jLastDate = getLastJulianDate(); 2722 if (gregorianCutoverYear == gregorianCutoverYearJulian 2723 && gCutover.getMonth() == jLastDate.getMonth()) { 2724 fixedDateMonth1 = jcal.getFixedDate(date.getNormalizedYear(), 2726 date.getMonth(), 2727 1, 2728 null); 2729 } else { 2730 fixedDateMonth1 = gregorianCutoverDate; 2732 } 2733 } else { 2734 fixedDateMonth1 = fixedDate - date.getDayOfMonth() + 1; 2736 } 2737 2738 return fixedDateMonth1; 2739 } 2740 2741 2746 private final BaseCalendar.Date getCalendarDate(long fd) { 2747 BaseCalendar cal = (fd >= gregorianCutoverDate) ? gcal : getJulianCalendarSystem(); 2748 BaseCalendar.Date d = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.NO_TIMEZONE); 2749 cal.getCalendarDateFromFixedDate(d, fd); 2750 return d; 2751 } 2752 2753 2757 private final BaseCalendar.Date getGregorianCutoverDate() { 2758 return getCalendarDate(gregorianCutoverDate); 2759 } 2760 2761 2765 private final BaseCalendar.Date getLastJulianDate() { 2766 return getCalendarDate(gregorianCutoverDate - 1); 2767 } 2768 2769 2775 private final int monthLength(int month, int year) { 2776 return isLeapYear(year) ? LEAP_MONTH_LENGTH[month] : MONTH_LENGTH[month]; 2777 } 2778 2779 2785 private final int monthLength(int month) { 2786 int year = internalGet(YEAR); 2787 if (internalGetEra() == BCE) { 2788 year = 1 - year; 2789 } 2790 return monthLength(month, year); 2791 } 2792 2793 private final int actualMonthLength() { 2794 int year = cdate.getNormalizedYear(); 2795 if (year != gregorianCutoverYear && year != gregorianCutoverYearJulian) { 2796 return calsys.getMonthLength(cdate); 2797 } 2798 BaseCalendar.Date date = (BaseCalendar.Date) cdate.clone(); 2799 long fd = calsys.getFixedDate(date); 2800 long month1 = getFixedDateMonth1(date, fd); 2801 long next1 = month1 + calsys.getMonthLength(date); 2802 if (next1 < gregorianCutoverDate) { 2803 return (int)(next1 - month1); 2804 } 2805 if (cdate != gdate) { 2806 date = (BaseCalendar.Date) gcal.newCalendarDate(TimeZone.NO_TIMEZONE); 2807 } 2808 gcal.getCalendarDateFromFixedDate(date, next1); 2809 next1 = getFixedDateMonth1(date, next1); 2810 return (int)(next1 - month1); 2811 } 2812 2813 2817 private final int yearLength(int year) { 2818 return isLeapYear(year) ? 366 : 365; 2819 } 2820 2821 2825 private final int yearLength() { 2826 int year = internalGet(YEAR); 2827 if (internalGetEra() == BCE) { 2828 year = 1 - year; 2829 } 2830 return yearLength(year); 2831 } 2832 2833 2839 private final void pinDayOfMonth() { 2840 int year = internalGet(YEAR); 2841 int monthLen; 2842 if (year > gregorianCutoverYear || year < gregorianCutoverYearJulian) { 2843 monthLen = monthLength(internalGet(MONTH)); 2844 } else { 2845 GregorianCalendar gc = getNormalizedCalendar(); 2846 monthLen = gc.getActualMaximum(DAY_OF_MONTH); 2847 } 2848 int dom = internalGet(DAY_OF_MONTH); 2849 if (dom > monthLen) { 2850 set(DAY_OF_MONTH, monthLen); 2851 } 2852 } 2853 2854 2858 private final long getCurrentFixedDate() { 2859 return (calsys == gcal) ? cachedFixedDate : calsys.getFixedDate(cdate); 2860 } 2861 2862 2865 private static final int getRolledValue(int value, int amount, int min, int max) { 2866 assert value >= min && value <= max; 2867 int range = max - min + 1; 2868 amount %= range; 2869 int n = value + amount; 2870 if (n > max) { 2871 n -= range; 2872 } else if (n < min) { 2873 n += range; 2874 } 2875 assert n >= min && n <= max; 2876 return n; 2877 } 2878 2879 2883 private final int internalGetEra() { 2884 return isSet(ERA) ? internalGet(ERA) : CE; 2885 } 2886 2887 2890 private void readObject(ObjectInputStream stream) 2891 throws IOException , ClassNotFoundException { 2892 stream.defaultReadObject(); 2893 if (gdate == null) { 2894 gdate = (BaseCalendar.Date) gcal.newCalendarDate(getZone()); 2895 cachedFixedDate = Long.MIN_VALUE; 2896 } 2897 setGregorianChange(gregorianCutover); 2898 } 2899} 2900 | Popular Tags |