1 16 package org.joda.time.chrono; 17 18 import java.util.ArrayList ; 19 import java.util.HashMap ; 20 import java.util.Locale ; 21 import java.util.Map ; 22 23 import org.joda.time.Chronology; 24 import org.joda.time.DateTimeField; 25 import org.joda.time.DateTimeUtils; 26 import org.joda.time.DateTimeZone; 27 import org.joda.time.DurationField; 28 import org.joda.time.IllegalFieldValueException; 29 import org.joda.time.Instant; 30 import org.joda.time.ReadableInstant; 31 import org.joda.time.ReadablePartial; 32 import org.joda.time.field.BaseDateTimeField; 33 import org.joda.time.field.DecoratedDurationField; 34 import org.joda.time.format.DateTimeFormatter; 35 import org.joda.time.format.ISODateTimeFormat; 36 37 74 public final class GJChronology extends AssembledChronology { 75 76 77 private static final long serialVersionUID = -2545574827706931671L; 78 79 82 private static long convertByYear(long instant, Chronology from, Chronology to) { 83 return to.getDateTimeMillis 84 (from.year().get(instant), 85 from.monthOfYear().get(instant), 86 from.dayOfMonth().get(instant), 87 from.millisOfDay().get(instant)); 88 } 89 90 93 private static long convertByWeekyear(final long instant, Chronology from, Chronology to) { 94 long newInstant; 95 newInstant = to.weekyear().set(0, from.weekyear().get(instant)); 96 newInstant = to.weekOfWeekyear().set(newInstant, from.weekOfWeekyear().get(instant)); 97 newInstant = to.dayOfWeek().set(newInstant, from.dayOfWeek().get(instant)); 98 newInstant = to.millisOfDay().set(newInstant, from.millisOfDay().get(instant)); 99 return newInstant; 100 } 101 102 105 static final Instant DEFAULT_CUTOVER = new Instant(-12219292800000L); 106 107 108 private static final Map cCache = new HashMap (); 109 110 122 public static GJChronology getInstanceUTC() { 123 return getInstance(DateTimeZone.UTC, DEFAULT_CUTOVER, 4); 124 } 125 126 138 public static GJChronology getInstance() { 139 return getInstance(DateTimeZone.getDefault(), DEFAULT_CUTOVER, 4); 140 } 141 142 154 public static GJChronology getInstance(DateTimeZone zone) { 155 return getInstance(zone, DEFAULT_CUTOVER, 4); 156 } 157 158 169 public static GJChronology getInstance( 170 DateTimeZone zone, 171 ReadableInstant gregorianCutover) { 172 173 return getInstance(zone, gregorianCutover, 4); 174 } 175 176 184 public static synchronized GJChronology getInstance( 185 DateTimeZone zone, 186 ReadableInstant gregorianCutover, 187 int minDaysInFirstWeek) { 188 189 zone = DateTimeUtils.getZone(zone); 190 Instant cutoverInstant; 191 if (gregorianCutover == null) { 192 cutoverInstant = DEFAULT_CUTOVER; 193 } else { 194 cutoverInstant = gregorianCutover.toInstant(); 195 } 196 197 GJChronology chrono; 198 199 ArrayList chronos = (ArrayList )cCache.get(zone); 200 if (chronos == null) { 201 chronos = new ArrayList (2); 202 cCache.put(zone, chronos); 203 } else { 204 for (int i=chronos.size(); --i>=0; ) { 205 chrono = (GJChronology)chronos.get(i); 206 if (minDaysInFirstWeek == chrono.getMinimumDaysInFirstWeek() && 207 cutoverInstant.equals(chrono.getGregorianCutover())) { 208 209 return chrono; 210 } 211 } 212 } 213 214 if (zone == DateTimeZone.UTC) { 215 chrono = new GJChronology 216 (JulianChronology.getInstance(zone, minDaysInFirstWeek), 217 GregorianChronology.getInstance(zone, minDaysInFirstWeek), 218 cutoverInstant); 219 } else { 220 chrono = getInstance(DateTimeZone.UTC, cutoverInstant, minDaysInFirstWeek); 221 chrono = new GJChronology 222 (ZonedChronology.getInstance(chrono, zone), 223 chrono.iJulianChronology, 224 chrono.iGregorianChronology, 225 chrono.iCutoverInstant); 226 } 227 228 chronos.add(chrono); 229 230 return chrono; 231 } 232 233 241 public static GJChronology getInstance( 242 DateTimeZone zone, 243 long gregorianCutover, 244 int minDaysInFirstWeek) { 245 246 Instant cutoverInstant; 247 if (gregorianCutover == DEFAULT_CUTOVER.getMillis()) { 248 cutoverInstant = null; 249 } else { 250 cutoverInstant = new Instant(gregorianCutover); 251 } 252 return getInstance(zone, cutoverInstant, minDaysInFirstWeek); 253 } 254 255 private JulianChronology iJulianChronology; 257 private GregorianChronology iGregorianChronology; 258 private Instant iCutoverInstant; 259 260 private long iCutoverMillis; 261 private long iGapDuration; 262 263 268 private GJChronology(JulianChronology julian, 269 GregorianChronology gregorian, 270 Instant cutoverInstant) { 271 super(null, new Object [] {julian, gregorian, cutoverInstant}); 272 } 273 274 277 private GJChronology(Chronology base, 278 JulianChronology julian, 279 GregorianChronology gregorian, 280 Instant cutoverInstant) { 281 super(base, new Object [] {julian, gregorian, cutoverInstant}); 282 } 283 284 287 private Object readResolve() { 288 return getInstance(getZone(), iCutoverInstant, getMinimumDaysInFirstWeek()); 289 } 290 291 public DateTimeZone getZone() { 292 Chronology base; 293 if ((base = getBase()) != null) { 294 return base.getZone(); 295 } 296 return DateTimeZone.UTC; 297 } 298 299 306 public Chronology withUTC() { 307 return withZone(DateTimeZone.UTC); 308 } 309 310 316 public Chronology withZone(DateTimeZone zone) { 317 if (zone == null) { 318 zone = DateTimeZone.getDefault(); 319 } 320 if (zone == getZone()) { 321 return this; 322 } 323 return getInstance(zone, iCutoverInstant, getMinimumDaysInFirstWeek()); 324 } 325 326 public long getDateTimeMillis(int year, int monthOfYear, int dayOfMonth, 327 int millisOfDay) 328 throws IllegalArgumentException 329 { 330 Chronology base; 331 if ((base = getBase()) != null) { 332 return base.getDateTimeMillis(year, monthOfYear, dayOfMonth, millisOfDay); 333 } 334 335 long instant = iGregorianChronology.getDateTimeMillis 337 (year, monthOfYear, dayOfMonth, millisOfDay); 338 if (instant < iCutoverMillis) { 339 instant = iJulianChronology.getDateTimeMillis 341 (year, monthOfYear, dayOfMonth, millisOfDay); 342 if (instant >= iCutoverMillis) { 343 throw new IllegalArgumentException ("Specified date does not exist"); 345 } 346 } 347 return instant; 348 } 349 350 public long getDateTimeMillis(int year, int monthOfYear, int dayOfMonth, 351 int hourOfDay, int minuteOfHour, 352 int secondOfMinute, int millisOfSecond) 353 throws IllegalArgumentException 354 { 355 Chronology base; 356 if ((base = getBase()) != null) { 357 return base.getDateTimeMillis 358 (year, monthOfYear, dayOfMonth, 359 hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond); 360 } 361 362 long instant = iGregorianChronology.getDateTimeMillis 364 (year, monthOfYear, dayOfMonth, 365 hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond); 366 if (instant < iCutoverMillis) { 367 instant = iJulianChronology.getDateTimeMillis 369 (year, monthOfYear, dayOfMonth, 370 hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond); 371 if (instant >= iCutoverMillis) { 372 throw new IllegalArgumentException ("Specified date does not exist"); 374 } 375 } 376 return instant; 377 } 378 379 383 public Instant getGregorianCutover() { 384 return iCutoverInstant; 385 } 386 387 392 public int getMinimumDaysInFirstWeek() { 393 return iGregorianChronology.getMinimumDaysInFirstWeek(); 394 } 395 396 403 public String toString() { 404 StringBuffer sb = new StringBuffer (60); 405 sb.append("GJChronology"); 406 sb.append('['); 407 sb.append(getZone().getID()); 408 409 if (iCutoverMillis != DEFAULT_CUTOVER.getMillis()) { 410 sb.append(",cutover="); 411 DateTimeFormatter printer; 412 if (withUTC().dayOfYear().remainder(iCutoverMillis) == 0) { 413 printer = ISODateTimeFormat.date(); 414 } else { 415 printer = ISODateTimeFormat.dateTime(); 416 } 417 printer.withChronology(withUTC()).printTo(sb, iCutoverMillis); 418 } 419 420 if (getMinimumDaysInFirstWeek() != 4) { 421 sb.append(",mdfw="); 422 sb.append(getMinimumDaysInFirstWeek()); 423 } 424 sb.append(']'); 425 426 return sb.toString(); 427 } 428 429 protected void assemble(Fields fields) { 430 Object [] params = (Object [])getParam(); 431 432 JulianChronology julian = (JulianChronology)params[0]; 433 GregorianChronology gregorian = (GregorianChronology)params[1]; 434 Instant cutoverInstant = (Instant)params[2]; 435 iCutoverMillis = cutoverInstant.getMillis(); 436 437 iJulianChronology = julian; 438 iGregorianChronology = gregorian; 439 iCutoverInstant = cutoverInstant; 440 441 if (getBase() != null) { 442 return; 443 } 444 445 if (julian.getMinimumDaysInFirstWeek() != gregorian.getMinimumDaysInFirstWeek()) { 446 throw new IllegalArgumentException (); 447 } 448 449 iGapDuration = iCutoverMillis - julianToGregorianByYear(iCutoverMillis); 451 452 454 fields.copyFieldsFrom(gregorian); 457 458 461 if (gregorian.millisOfDay().get(iCutoverMillis) == 0) { 463 466 fields.millisOfSecond = new CutoverField(julian.millisOfSecond(), fields.millisOfSecond, iCutoverMillis); 467 fields.millisOfDay = new CutoverField(julian.millisOfDay(), fields.millisOfDay, iCutoverMillis); 468 fields.secondOfMinute = new CutoverField(julian.secondOfMinute(), fields.secondOfMinute, iCutoverMillis); 469 fields.secondOfDay = new CutoverField(julian.secondOfDay(), fields.secondOfDay, iCutoverMillis); 470 fields.minuteOfHour = new CutoverField(julian.minuteOfHour(), fields.minuteOfHour, iCutoverMillis); 471 fields.minuteOfDay = new CutoverField(julian.minuteOfDay(), fields.minuteOfDay, iCutoverMillis); 472 fields.hourOfDay = new CutoverField(julian.hourOfDay(), fields.hourOfDay, iCutoverMillis); 473 fields.hourOfHalfday = new CutoverField(julian.hourOfHalfday(), fields.hourOfHalfday, iCutoverMillis); 474 fields.clockhourOfDay = new CutoverField(julian.clockhourOfDay(), fields.clockhourOfDay, iCutoverMillis); 475 fields.clockhourOfHalfday = new CutoverField(julian.clockhourOfHalfday(), 476 fields.clockhourOfHalfday, iCutoverMillis); 477 fields.halfdayOfDay = new CutoverField(julian.halfdayOfDay(), fields.halfdayOfDay, iCutoverMillis); 478 } 479 480 { 482 fields.era = new CutoverField(julian.era(), fields.era, iCutoverMillis); 483 } 484 485 490 { 491 long cutover = gregorian.year().roundCeiling(iCutoverMillis); 492 fields.dayOfYear = new CutoverField( 493 julian.dayOfYear(), fields.dayOfYear, cutover); 494 } 495 496 { 497 long cutover = gregorian.weekyear().roundCeiling(iCutoverMillis); 498 fields.weekOfWeekyear = new CutoverField( 499 julian.weekOfWeekyear(), fields.weekOfWeekyear, cutover, true); 500 } 501 502 { 506 fields.year = new ImpreciseCutoverField( 507 julian.year(), fields.year, iCutoverMillis); 508 fields.years = fields.year.getDurationField(); 509 fields.yearOfEra = new ImpreciseCutoverField( 510 julian.yearOfEra(), fields.yearOfEra, fields.years, iCutoverMillis); 511 fields.yearOfCentury = new ImpreciseCutoverField( 512 julian.yearOfCentury(), fields.yearOfCentury, fields.years, iCutoverMillis); 513 514 fields.centuryOfEra = new ImpreciseCutoverField( 515 julian.centuryOfEra(), fields.centuryOfEra, iCutoverMillis); 516 fields.centuries = fields.centuryOfEra.getDurationField(); 517 518 fields.monthOfYear = new ImpreciseCutoverField( 519 julian.monthOfYear(), fields.monthOfYear, iCutoverMillis); 520 fields.months = fields.monthOfYear.getDurationField(); 521 522 fields.weekyear = new ImpreciseCutoverField( 523 julian.weekyear(), fields.weekyear, null, iCutoverMillis, true); 524 fields.weekyearOfCentury = new ImpreciseCutoverField( 525 julian.weekyearOfCentury(), fields.weekyearOfCentury, fields.weekyears, iCutoverMillis); 526 fields.weekyears = fields.weekyear.getDurationField(); 527 } 528 529 { 532 CutoverField cf = new CutoverField 533 (julian.dayOfMonth(), fields.dayOfMonth, iCutoverMillis); 534 cf.iRangeDurationField = fields.months; 535 fields.dayOfMonth = cf; 536 } 537 } 538 539 long julianToGregorianByYear(long instant) { 540 return convertByYear(instant, iJulianChronology, iGregorianChronology); 541 } 542 543 long gregorianToJulianByYear(long instant) { 544 return convertByYear(instant, iGregorianChronology, iJulianChronology); 545 } 546 547 long julianToGregorianByWeekyear(long instant) { 548 return convertByWeekyear(instant, iJulianChronology, iGregorianChronology); 549 } 550 551 long gregorianToJulianByWeekyear(long instant) { 552 return convertByWeekyear(instant, iGregorianChronology, iJulianChronology); 553 } 554 555 560 private class CutoverField extends BaseDateTimeField { 561 private static final long serialVersionUID = 3528501219481026402L; 562 563 final DateTimeField iJulianField; 564 final DateTimeField iGregorianField; 565 final long iCutover; 566 final boolean iConvertByWeekyear; 567 568 protected DurationField iDurationField; 569 protected DurationField iRangeDurationField; 570 571 576 CutoverField(DateTimeField julianField, DateTimeField gregorianField, long cutoverMillis) { 577 this(julianField, gregorianField, cutoverMillis, false); 578 } 579 580 586 CutoverField(DateTimeField julianField, DateTimeField gregorianField, 587 long cutoverMillis, boolean convertByWeekyear) { 588 super(gregorianField.getType()); 589 iJulianField = julianField; 590 iGregorianField = gregorianField; 591 iCutover = cutoverMillis; 592 iConvertByWeekyear = convertByWeekyear; 593 iDurationField = gregorianField.getDurationField(); 596 597 DurationField rangeField = gregorianField.getRangeDurationField(); 598 if (rangeField == null) { 599 rangeField = julianField.getRangeDurationField(); 600 } 601 iRangeDurationField = rangeField; 602 } 603 604 public boolean isLenient() { 605 return false; 606 } 607 608 public int get(long instant) { 609 if (instant >= iCutover) { 610 return iGregorianField.get(instant); 611 } else { 612 return iJulianField.get(instant); 613 } 614 } 615 616 public String getAsText(long instant, Locale locale) { 617 if (instant >= iCutover) { 618 return iGregorianField.getAsText(instant, locale); 619 } else { 620 return iJulianField.getAsText(instant, locale); 621 } 622 } 623 624 public String getAsText(int fieldValue, Locale locale) { 625 return iGregorianField.getAsText(fieldValue, locale); 626 } 627 628 public String getAsShortText(long instant, Locale locale) { 629 if (instant >= iCutover) { 630 return iGregorianField.getAsShortText(instant, locale); 631 } else { 632 return iJulianField.getAsShortText(instant, locale); 633 } 634 } 635 636 public String getAsShortText(int fieldValue, Locale locale) { 637 return iGregorianField.getAsShortText(fieldValue, locale); 638 } 639 640 public long add(long instant, int value) { 641 return iGregorianField.add(instant, value); 642 } 643 644 public long add(long instant, long value) { 645 return iGregorianField.add(instant, value); 646 } 647 648 public int[] add(ReadablePartial partial, int fieldIndex, int[] values, int valueToAdd) { 649 if (valueToAdd == 0) { 652 return values; 653 } 654 if (DateTimeUtils.isContiguous(partial)) { 655 long instant = 0L; 656 for (int i = 0, isize = partial.size(); i < isize; i++) { 657 instant = partial.getFieldType(i).getField(GJChronology.this).set(instant, values[i]); 658 } 659 instant = add(instant, valueToAdd); 660 return GJChronology.this.get(partial, instant); 661 } else { 662 return super.add(partial, fieldIndex, values, valueToAdd); 663 } 664 } 665 666 public int getDifference(long minuendInstant, long subtrahendInstant) { 667 return iGregorianField.getDifference(minuendInstant, subtrahendInstant); 668 } 669 670 public long getDifferenceAsLong(long minuendInstant, long subtrahendInstant) { 671 return iGregorianField.getDifferenceAsLong(minuendInstant, subtrahendInstant); 672 } 673 674 public long set(long instant, int value) { 675 if (instant >= iCutover) { 676 instant = iGregorianField.set(instant, value); 677 if (instant < iCutover) { 678 if (instant + iGapDuration < iCutover) { 680 instant = gregorianToJulian(instant); 681 } 682 if (get(instant) != value) { 684 throw new IllegalFieldValueException 685 (iGregorianField.getType(), new Integer (value), null, null); 686 } 687 } 688 } else { 689 instant = iJulianField.set(instant, value); 690 if (instant >= iCutover) { 691 if (instant - iGapDuration >= iCutover) { 693 instant = julianToGregorian(instant); 694 } 695 if (get(instant) != value) { 697 throw new IllegalFieldValueException 698 (iJulianField.getType(), new Integer (value), null, null); 699 } 700 } 701 } 702 return instant; 703 } 704 705 public long set(long instant, String text, Locale locale) { 706 if (instant >= iCutover) { 707 instant = iGregorianField.set(instant, text, locale); 708 if (instant < iCutover) { 709 if (instant + iGapDuration < iCutover) { 711 instant = gregorianToJulian(instant); 712 } 713 } 715 } else { 716 instant = iJulianField.set(instant, text, locale); 717 if (instant >= iCutover) { 718 if (instant - iGapDuration >= iCutover) { 720 instant = julianToGregorian(instant); 721 } 722 } 724 } 725 return instant; 726 } 727 728 public DurationField getDurationField() { 729 return iDurationField; 730 } 731 732 public DurationField getRangeDurationField() { 733 return iRangeDurationField; 734 } 735 736 public boolean isLeap(long instant) { 737 if (instant >= iCutover) { 738 return iGregorianField.isLeap(instant); 739 } else { 740 return iJulianField.isLeap(instant); 741 } 742 } 743 744 public int getLeapAmount(long instant) { 745 if (instant >= iCutover) { 746 return iGregorianField.getLeapAmount(instant); 747 } else { 748 return iJulianField.getLeapAmount(instant); 749 } 750 } 751 752 public DurationField getLeapDurationField() { 753 return iGregorianField.getLeapDurationField(); 754 } 755 756 757 public int getMinimumValue() { 758 return iJulianField.getMinimumValue(); 761 } 762 763 public int getMinimumValue(ReadablePartial partial) { 764 return iJulianField.getMinimumValue(partial); 765 } 766 767 public int getMinimumValue(ReadablePartial partial, int[] values) { 768 return iJulianField.getMinimumValue(partial, values); 769 } 770 771 public int getMinimumValue(long instant) { 772 if (instant < iCutover) { 773 return iJulianField.getMinimumValue(instant); 774 } 775 776 int min = iGregorianField.getMinimumValue(instant); 777 778 instant = iGregorianField.set(instant, min); 781 if (instant < iCutover) { 782 min = iGregorianField.get(iCutover); 783 } 784 785 return min; 786 } 787 788 public int getMaximumValue() { 789 return iGregorianField.getMaximumValue(); 792 } 793 794 public int getMaximumValue(long instant) { 795 if (instant >= iCutover) { 796 return iGregorianField.getMaximumValue(instant); 797 } 798 799 int max = iJulianField.getMaximumValue(instant); 800 801 instant = iJulianField.set(instant, max); 804 if (instant >= iCutover) { 805 max = iJulianField.get(iJulianField.add(iCutover, -1)); 806 } 807 808 return max; 809 } 810 811 public int getMaximumValue(ReadablePartial partial) { 812 long instant = GJChronology.getInstanceUTC().set(partial, 0L); 813 return getMaximumValue(instant); 814 } 815 816 public int getMaximumValue(ReadablePartial partial, int[] values) { 817 Chronology chrono = GJChronology.getInstanceUTC(); 818 long instant = 0L; 819 for (int i = 0, isize = partial.size(); i < isize; i++) { 820 DateTimeField field = partial.getFieldType(i).getField(chrono); 821 if (values[i] <= field.getMaximumValue(instant)) { 822 instant = field.set(instant, values[i]); 823 } 824 } 825 return getMaximumValue(instant); 826 } 827 828 public long roundFloor(long instant) { 829 if (instant >= iCutover) { 830 instant = iGregorianField.roundFloor(instant); 831 if (instant < iCutover) { 832 if (instant + iGapDuration < iCutover) { 834 instant = gregorianToJulian(instant); 835 } 836 } 837 } else { 838 instant = iJulianField.roundFloor(instant); 839 } 840 return instant; 841 } 842 843 public long roundCeiling(long instant) { 844 if (instant >= iCutover) { 845 instant = iGregorianField.roundCeiling(instant); 846 } else { 847 instant = iJulianField.roundCeiling(instant); 848 if (instant >= iCutover) { 849 if (instant - iGapDuration >= iCutover) { 851 instant = julianToGregorian(instant); 852 } 853 } 854 } 855 return instant; 856 } 857 858 public int getMaximumTextLength(Locale locale) { 859 return Math.max(iJulianField.getMaximumTextLength(locale), 860 iGregorianField.getMaximumTextLength(locale)); 861 } 862 863 public int getMaximumShortTextLength(Locale locale) { 864 return Math.max(iJulianField.getMaximumShortTextLength(locale), 865 iGregorianField.getMaximumShortTextLength(locale)); 866 } 867 868 protected long julianToGregorian(long instant) { 869 if (iConvertByWeekyear) { 870 return julianToGregorianByWeekyear(instant); 871 } else { 872 return julianToGregorianByYear(instant); 873 } 874 } 875 876 protected long gregorianToJulian(long instant) { 877 if (iConvertByWeekyear) { 878 return gregorianToJulianByWeekyear(instant); 879 } else { 880 return gregorianToJulianByYear(instant); 881 } 882 } 883 } 884 885 892 private final class ImpreciseCutoverField extends CutoverField { 893 private static final long serialVersionUID = 3410248757173576441L; 894 895 898 ImpreciseCutoverField(DateTimeField julianField, DateTimeField gregorianField, long cutoverMillis) { 899 this(julianField, gregorianField, null, cutoverMillis, false); 900 } 901 902 907 ImpreciseCutoverField(DateTimeField julianField, DateTimeField gregorianField, 908 DurationField durationField, long cutoverMillis) 909 { 910 this(julianField, gregorianField, durationField, cutoverMillis, false); 911 } 912 913 918 ImpreciseCutoverField(DateTimeField julianField, DateTimeField gregorianField, 919 DurationField durationField, 920 long cutoverMillis, boolean convertByWeekyear) 921 { 922 super(julianField, gregorianField, cutoverMillis, convertByWeekyear); 923 if (durationField == null) { 924 durationField = new LinkedDurationField(iDurationField, this); 925 } 926 iDurationField = durationField; 927 } 928 929 public long add(long instant, int value) { 930 if (instant >= iCutover) { 931 instant = iGregorianField.add(instant, value); 932 if (instant < iCutover) { 933 if (instant + iGapDuration < iCutover) { 935 instant = gregorianToJulian(instant); 936 } 937 } 938 } else { 939 instant = iJulianField.add(instant, value); 940 if (instant >= iCutover) { 941 if (instant - iGapDuration >= iCutover) { 943 instant = julianToGregorian(instant); 944 } 945 } 946 } 947 return instant; 948 } 949 950 public long add(long instant, long value) { 951 if (instant >= iCutover) { 952 instant = iGregorianField.add(instant, value); 953 if (instant < iCutover) { 954 if (instant + iGapDuration < iCutover) { 956 instant = gregorianToJulian(instant); 957 } 958 } 959 } else { 960 instant = iJulianField.add(instant, value); 961 if (instant >= iCutover) { 962 if (instant - iGapDuration >= iCutover) { 964 instant = julianToGregorian(instant); 965 } 966 } 967 } 968 return instant; 969 } 970 971 public int getDifference(long minuendInstant, long subtrahendInstant) { 972 if (minuendInstant >= iCutover) { 973 if (subtrahendInstant >= iCutover) { 974 return iGregorianField.getDifference(minuendInstant, subtrahendInstant); 975 } 976 minuendInstant = gregorianToJulian(minuendInstant); 979 return iJulianField.getDifference(minuendInstant, subtrahendInstant); 980 } else { 981 if (subtrahendInstant < iCutover) { 982 return iJulianField.getDifference(minuendInstant, subtrahendInstant); 983 } 984 minuendInstant = julianToGregorian(minuendInstant); 987 return iGregorianField.getDifference(minuendInstant, subtrahendInstant); 988 } 989 } 990 991 public long getDifferenceAsLong(long minuendInstant, long subtrahendInstant) { 992 if (minuendInstant >= iCutover) { 993 if (subtrahendInstant >= iCutover) { 994 return iGregorianField.getDifferenceAsLong(minuendInstant, subtrahendInstant); 995 } 996 minuendInstant = gregorianToJulian(minuendInstant); 999 return iJulianField.getDifferenceAsLong(minuendInstant, subtrahendInstant); 1000 } else { 1001 if (subtrahendInstant < iCutover) { 1002 return iJulianField.getDifferenceAsLong(minuendInstant, subtrahendInstant); 1003 } 1004 minuendInstant = julianToGregorian(minuendInstant); 1007 return iGregorianField.getDifferenceAsLong(minuendInstant, subtrahendInstant); 1008 } 1009 } 1010 1011 1021 public int getMinimumValue(long instant) { 1022 if (instant >= iCutover) { 1023 return iGregorianField.getMinimumValue(instant); 1024 } else { 1025 return iJulianField.getMinimumValue(instant); 1026 } 1027 } 1028 1029 public int getMaximumValue(long instant) { 1030 if (instant >= iCutover) { 1031 return iGregorianField.getMaximumValue(instant); 1032 } else { 1033 return iJulianField.getMaximumValue(instant); 1034 } 1035 } 1036 } 1037 1038 1042 private static class LinkedDurationField extends DecoratedDurationField { 1043 private static final long serialVersionUID = 4097975388007713084L; 1044 1045 private final ImpreciseCutoverField iField; 1046 1047 LinkedDurationField(DurationField durationField, ImpreciseCutoverField dateTimeField) { 1048 super(durationField, durationField.getType()); 1049 iField = dateTimeField; 1050 } 1051 1052 public long add(long instant, int value) { 1053 return iField.add(instant, value); 1054 } 1055 1056 public long add(long instant, long value) { 1057 return iField.add(instant, value); 1058 } 1059 1060 public int getDifference(long minuendInstant, long subtrahendInstant) { 1061 return iField.getDifference(minuendInstant, subtrahendInstant); 1062 } 1063 1064 public long getDifferenceAsLong(long minuendInstant, long subtrahendInstant) { 1065 return iField.getDifferenceAsLong(minuendInstant, subtrahendInstant); 1066 } 1067 } 1068 1069} 1070 | Popular Tags |