1 5 package com.ibm.icu.util; 6 7 import java.util.Date ; 8 import java.util.Locale ; 9 10 170 public class GregorianCalendar extends Calendar { 171 private static final long serialVersionUID = 9199388694351062137L; 173 174 205 206 210 218 public static final int BC = 0; 219 220 228 public static final int AD = 1; 229 230 private static final int EPOCH_YEAR = 1970; 231 232 private static final int[][] MONTH_COUNT = { 233 { 31, 31, 0, 0 }, { 28, 29, 31, 31 }, { 31, 31, 59, 60 }, { 30, 30, 90, 91 }, { 31, 31, 120, 121 }, { 30, 30, 151, 152 }, { 31, 31, 181, 182 }, { 31, 31, 212, 213 }, { 30, 30, 243, 244 }, { 31, 31, 273, 274 }, { 30, 30, 304, 305 }, { 31, 31, 334, 335 } }; 251 252 255 private static final int LIMITS[][] = { 256 { 0, 0, 1, 1 }, { 1, 1, 5828963, 5838270 }, { 0, 0, 11, 11 }, { 1, 1, 52, 53 }, { 0, 0, 4, 6 }, { 1, 1, 28, 31 }, { 1, 1, 365, 366 }, {}, { -1, -1, 4, 6 }, {}, {}, {}, {}, {}, {}, {}, {}, { -5838270, -5838270, 5828964, 5838271 }, {}, { -5838269, -5838269, 5828963, 5838270 }, {}, {}, }; 281 282 285 protected int handleGetLimit(int field, int limitType) { 286 return LIMITS[field][limitType]; 287 } 288 289 293 301 private long gregorianCutover = -12219292800000L; 302 303 306 private transient int cutoverJulianDay = 2299161; 307 308 312 private transient int gregorianCutoverYear = 1582; 313 314 318 transient protected boolean isGregorian; 319 320 324 transient protected boolean invertGregorian; 325 326 330 335 public GregorianCalendar() { 336 this(TimeZone.getDefault(), ULocale.getDefault()); 337 } 338 339 345 public GregorianCalendar(TimeZone zone) { 346 this(zone, ULocale.getDefault()); 347 } 348 349 355 public GregorianCalendar(Locale aLocale) { 356 this(TimeZone.getDefault(), aLocale); 357 } 358 359 366 public GregorianCalendar(ULocale locale) { 367 this(TimeZone.getDefault(), locale); 368 } 369 370 377 public GregorianCalendar(TimeZone zone, Locale aLocale) { 378 super(zone, aLocale); 379 setTimeInMillis(System.currentTimeMillis()); 380 } 381 382 390 public GregorianCalendar(TimeZone zone, ULocale locale) { 391 super(zone, locale); 392 setTimeInMillis(System.currentTimeMillis()); 393 } 394 395 404 public GregorianCalendar(int year, int month, int date) { 405 super(TimeZone.getDefault(), ULocale.getDefault()); 406 set(ERA, AD); 407 set(YEAR, year); 408 set(MONTH, month); 409 set(DATE, date); 410 } 411 412 425 public GregorianCalendar(int year, int month, int date, int hour, 426 int minute) { 427 super(TimeZone.getDefault(), ULocale.getDefault()); 428 set(ERA, AD); 429 set(YEAR, year); 430 set(MONTH, month); 431 set(DATE, date); 432 set(HOUR_OF_DAY, hour); 433 set(MINUTE, minute); 434 } 435 436 451 public GregorianCalendar(int year, int month, int date, int hour, 452 int minute, int second) { 453 super(TimeZone.getDefault(), ULocale.getDefault()); 454 set(ERA, AD); 455 set(YEAR, year); 456 set(MONTH, month); 457 set(DATE, date); 458 set(HOUR_OF_DAY, hour); 459 set(MINUTE, minute); 460 set(SECOND, second); 461 } 462 463 467 479 public void setGregorianChange(Date date) { 480 gregorianCutover = date.getTime(); 481 482 if (gregorianCutover <= MIN_MILLIS) { 486 gregorianCutoverYear = cutoverJulianDay = Integer.MIN_VALUE; 487 } else if (gregorianCutover >= MAX_MILLIS) { 488 gregorianCutoverYear = cutoverJulianDay = Integer.MAX_VALUE; 489 } else { 490 cutoverJulianDay = (int) floorDivide(gregorianCutover, ONE_DAY); 494 495 GregorianCalendar cal = new GregorianCalendar(getTimeZone()); 497 cal.setTime(date); 498 gregorianCutoverYear = cal.get(EXTENDED_YEAR); 499 } 500 } 501 502 510 public final Date getGregorianChange() { 511 return new Date (gregorianCutover); 512 } 513 514 521 public boolean isLeapYear(int year) { 522 return year >= gregorianCutoverYear ? 523 ((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))) : (year%4 == 0); } 526 527 534 public boolean isEquivalentTo(Calendar other) { 535 return super.isEquivalentTo(other) && 536 gregorianCutover == ((GregorianCalendar)other).gregorianCutover; 537 } 538 539 544 public int hashCode() { 545 return super.hashCode() ^ (int)gregorianCutover; 546 } 547 548 552 public void roll(int field, int amount) { 553 554 switch (field) { 555 case WEEK_OF_YEAR: 556 { 557 int woy = get(WEEK_OF_YEAR); 565 int isoYear = get(YEAR_WOY); 568 int isoDoy = internalGet(DAY_OF_YEAR); 569 if (internalGet(MONTH) == Calendar.JANUARY) { 570 if (woy >= 52) { 571 isoDoy += handleGetYearLength(isoYear); 572 } 573 } else { 574 if (woy == 1) { 575 isoDoy -= handleGetYearLength(isoYear - 1); 576 } 577 } 578 woy += amount; 579 if (woy < 1 || woy > 52) { 581 int lastDoy = handleGetYearLength(isoYear); 588 int lastRelDow = (lastDoy - isoDoy + internalGet(DAY_OF_WEEK) - 589 getFirstDayOfWeek()) % 7; 590 if (lastRelDow < 0) lastRelDow += 7; 591 if ((6 - lastRelDow) >= getMinimalDaysInFirstWeek()) lastDoy -= 7; 592 int lastWoy = weekNumber(lastDoy, lastRelDow + 1); 593 woy = ((woy + lastWoy - 1) % lastWoy) + 1; 594 } 595 set(WEEK_OF_YEAR, woy); 596 set(YEAR, isoYear); return; 598 } 599 600 default: 601 super.roll(field, amount); 602 return; 603 } 604 } 605 606 611 public int getActualMinimum(int field) { 612 return getMinimum(field); 613 } 614 615 622 public int getActualMaximum(int field) { 623 641 642 switch (field) { 643 644 case YEAR: 645 664 { 665 Calendar cal = (Calendar) clone(); 666 cal.setLenient(true); 667 668 int era = cal.get(ERA); 669 Date d = cal.getTime(); 670 671 674 int lowGood = LIMITS[YEAR][1]; 675 int highBad = LIMITS[YEAR][2]+1; 676 while ((lowGood + 1) < highBad) { 677 int y = (lowGood + highBad) / 2; 678 cal.set(YEAR, y); 679 if (cal.get(YEAR) == y && cal.get(ERA) == era) { 680 lowGood = y; 681 } else { 682 highBad = y; 683 cal.setTime(d); } 685 } 686 687 return lowGood; 688 } 689 690 default: 691 return super.getActualMaximum(field); 692 } 693 } 694 695 699 706 boolean inDaylightTime() { 707 if (!getTimeZone().useDaylightTime()) return false; 708 complete(); return internalGet(DST_OFFSET) != 0; 710 } 711 712 713 717 720 protected int handleGetMonthLength(int extendedYear, int month) { 721 return MONTH_COUNT[month][isLeapYear(extendedYear)?1:0]; 722 } 723 724 727 protected int handleGetYearLength(int eyear) { 728 return isLeapYear(eyear) ? 366 : 365; 729 } 730 731 735 747 protected void handleComputeFields(int julianDay) { 748 int eyear, month, dayOfMonth, dayOfYear; 749 750 if (julianDay >= cutoverJulianDay) { 751 month = getGregorianMonth(); 752 dayOfMonth = getGregorianDayOfMonth(); 753 dayOfYear = getGregorianDayOfYear(); 754 eyear = getGregorianYear(); 755 } else { 756 long julianEpochDay = julianDay - (JAN_1_1_JULIAN_DAY - 2); 759 eyear = (int) floorDivide(4*julianEpochDay + 1464, 1461); 760 761 long january1 = 365*(eyear-1) + floorDivide(eyear-1, 4); 763 dayOfYear = (int)(julianEpochDay - january1); 765 boolean isLeap = ((eyear&0x3) == 0); 773 int correction = 0; 775 int march1 = isLeap ? 60 : 59; if (dayOfYear >= march1) { 777 correction = isLeap ? 1 : 2; 778 } 779 month = (12 * (dayOfYear + correction) + 6) / 367; dayOfMonth = dayOfYear - MONTH_COUNT[month][isLeap?3:2] + 1; ++dayOfYear; 782 } 783 internalSet(MONTH, month); 784 internalSet(DAY_OF_MONTH, dayOfMonth); 785 internalSet(DAY_OF_YEAR, dayOfYear); 786 internalSet(EXTENDED_YEAR, eyear); 787 int era = AD; 788 if (eyear < 1) { 789 era = BC; 790 eyear = 1 - eyear; 791 } 792 internalSet(ERA, era); 793 internalSet(YEAR, eyear); 794 } 795 796 800 803 protected int handleGetExtendedYear() { 804 int year; 805 if (newerField(EXTENDED_YEAR, YEAR) == EXTENDED_YEAR) { 806 year = internalGet(EXTENDED_YEAR, EPOCH_YEAR); 807 } else { 808 int era = internalGet(ERA, AD); 810 if (era == BC) { 811 year = 1 - internalGet(YEAR, 1); } else { 813 year = internalGet(YEAR, EPOCH_YEAR); 814 } 815 } 816 return year; 817 } 818 819 822 protected int handleComputeJulianDay(int bestField) { 823 824 invertGregorian = false; 825 826 int jd = super.handleComputeJulianDay(bestField); 827 828 if (isGregorian != (jd >= cutoverJulianDay)) { 831 invertGregorian = true; 832 jd = super.handleComputeJulianDay(bestField); 833 } 834 835 return jd; 836 } 837 838 842 protected int handleComputeMonthStart(int eyear, int month, boolean useMonth) { 843 844 if (month < 0 || month > 11) { 847 int[] rem = new int[1]; 848 eyear += floorDivide(month, 12, rem); 849 month = rem[0]; 850 } 851 852 boolean isLeap = eyear%4 == 0; 853 int y = eyear - 1; 854 int julianDay = 365*y + floorDivide(y, 4) + (JAN_1_1_JULIAN_DAY - 3); 855 856 isGregorian = (eyear >= gregorianCutoverYear); 857 if (invertGregorian) { 858 isGregorian = !isGregorian; 859 } 860 if (isGregorian) { 861 isLeap = isLeap && ((eyear%100 != 0) || (eyear%400 == 0)); 862 julianDay += floorDivide(y, 400) - floorDivide(y, 100) + 2; 865 } 866 867 871 if (month != 0) { 872 julianDay += MONTH_COUNT[month][isLeap?3:2]; 873 } 874 875 return julianDay; 876 } 877 878 884 public String getType() { 885 return "gregorian"; 886 } 887 888 905 } 906 | Popular Tags |