src/share/classes/java/time/Period.java

Print this page




  44  *    and/or other materials provided with the distribution.
  45  *
  46  *  * Neither the name of JSR-310 nor the names of its contributors
  47  *    may be used to endorse or promote products derived from this software
  48  *    without specific prior written permission.
  49  *
  50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  54  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  55  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  56  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  57  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  58  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  59  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  61  */
  62 package java.time;
  63 
  64 import static java.time.LocalTime.NANOS_PER_DAY;
  65 import static java.time.LocalTime.NANOS_PER_HOUR;
  66 import static java.time.LocalTime.NANOS_PER_MINUTE;
  67 import static java.time.LocalTime.NANOS_PER_SECOND;
  68 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
  69 import static java.time.temporal.ChronoField.EPOCH_MONTH;
  70 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
  71 import static java.time.temporal.ChronoField.NANO_OF_DAY;
  72 import static java.time.temporal.ChronoField.YEAR;
  73 import static java.time.temporal.ChronoUnit.DAYS;
  74 import static java.time.temporal.ChronoUnit.MONTHS;
  75 import static java.time.temporal.ChronoUnit.NANOS;
  76 import static java.time.temporal.ChronoUnit.YEARS;
  77 





  78 import java.io.Serializable;


  79 import java.time.format.DateTimeParseException;
  80 import java.time.temporal.Chrono;
  81 import java.time.temporal.ChronoField;
  82 import java.time.temporal.ChronoUnit;
  83 import java.time.temporal.Temporal;
  84 import java.time.temporal.TemporalAccessor;
  85 import java.time.temporal.TemporalAdder;
  86 import java.time.temporal.TemporalSubtractor;
  87 import java.time.temporal.TemporalUnit;
  88 import java.time.temporal.ValueRange;



  89 import java.util.Objects;


  90 
  91 /**
  92  * A period of time, measured using the most common units, such as '3 Months, 4 Days and 7 Hours'.
  93  * <p>
  94  * A {@code Period} represents an amount of time measured in terms of the most commonly used units:
  95  * <p><ul>
  96  * <li>{@link ChronoUnit#YEARS YEARS}</li>
  97  * <li>{@link ChronoUnit#MONTHS MONTHS}</li>
  98  * <li>{@link ChronoUnit#DAYS DAYS}</li>
  99  * <li>time units with an {@linkplain TemporalUnit#isDurationEstimated() exact duration}</li>
 100  * </ul><p>
 101  * The period may be used with any calendar system with the exception is methods with an "ISO" suffix.
 102  * The meaning of a "year" or a "month" is only applied when the object is added to a date.












 103  * <p>
 104  * The period is modeled as a directed amount of time, meaning that individual parts of the
 105  * period may be negative.



 106  *
 107  * <h3>Specification for implementors</h3>
 108  * This class is immutable and thread-safe.
 109  * The maximum number of hours that can be stored is about 2.5 million, limited by storing
 110  * a single {@code long} nanoseconds for all time units internally.
 111  *
 112  * @since 1.8
 113  */
 114 public final class Period
 115         implements TemporalAdder, TemporalSubtractor, Serializable {
 116     // maximum hours is 2,562,047
 117 
 118     /**
 119      * A constant for a period of zero.
 120      */
 121     public static final Period ZERO = new Period(0, 0, 0, 0);
 122     /**
 123      * Serialization version.
 124      */
 125     private static final long serialVersionUID = -8290556941213247973L;










 126 
 127     /**
 128      * The number of years.
 129      */
 130     private final int years;
 131     /**
 132      * The number of months.
 133      */
 134     private final int months;
 135     /**
 136      * The number of days.
 137      */
 138     private final int days;
 139     /**
 140      * The number of nanoseconds.
 141      */
 142     private final long nanos;
 143 
 144     //-----------------------------------------------------------------------
 145     /**
 146      * Obtains a {@code Period} from date-based and time-based fields.
 147      * <p>
 148      * This creates an instance based on years, months, days, hours, minutes and seconds.
 149      * Within a period, the time fields are always normalized.
 150      *
 151      * @param years  the amount of years, may be negative
 152      * @param months  the amount of months, may be negative
 153      * @param days  the amount of days, may be negative
 154      * @param hours  the amount of hours, may be negative
 155      * @param minutes  the amount of minutes, may be negative
 156      * @param seconds  the amount of seconds, may be negative
 157      * @return the period, not null
 158      */
 159     public static Period of(int years, int months, int days, int hours, int minutes, int seconds) {
 160         return of(years, months, days, hours, minutes, seconds, 0);
 161     }
 162 
 163     /**
 164      * Obtains a {@code Period} from date-based and time-based fields.
 165      * <p>
 166      * This creates an instance based on years, months, days, hours, minutes, seconds and nanoseconds.
 167      * Within a period, the time fields are always normalized.
 168      *
 169      * @param years  the amount of years, may be negative
 170      * @param months  the amount of months, may be negative
 171      * @param days  the amount of days, may be negative
 172      * @param hours  the amount of hours, may be negative
 173      * @param minutes  the amount of minutes, may be negative
 174      * @param seconds  the amount of seconds, may be negative
 175      * @param nanos  the amount of nanos, may be negative
 176      * @return the period, not null
 177      */
 178     public static Period of(int years, int months, int days, int hours, int minutes, int seconds, long nanos) {
 179         if ((years | months | days | hours | minutes | seconds | nanos) == 0) {
 180             return ZERO;
 181         }
 182         long totSecs = Math.addExact(hours * 3600L, minutes * 60L) + seconds;
 183         long totNanos = Math.addExact(Math.multiplyExact(totSecs, 1_000_000_000L), nanos);
 184         return create(years, months, days, totNanos);
 185     }
 186 
 187     //-----------------------------------------------------------------------
 188     /**
 189      * Obtains a {@code Period} from date-based fields.
 190      * <p>
 191      * This creates an instance based on years, months and days.

 192      *
 193      * @param years  the amount of years, may be negative
 194      * @param months  the amount of months, may be negative
 195      * @param days  the amount of days, may be negative
 196      * @return the period, not null
 197      */
 198     public static Period ofDate(int years, int months, int days) {
 199         return of(years, months, days, 0, 0, 0, 0);
 200     }
 201 
 202     //-----------------------------------------------------------------------
 203     /**
 204      * Obtains a {@code Period} from time-based fields.
 205      * <p>
 206      * This creates an instance based on hours, minutes and seconds.
 207      * Within a period, the time fields are always normalized.
 208      *
 209      * @param hours  the amount of hours, may be negative
 210      * @param minutes  the amount of minutes, may be negative
 211      * @param seconds  the amount of seconds, may be negative
 212      * @return the period, not null
 213      */
 214     public static Period ofTime(int hours, int minutes, int seconds) {
 215         return of(0, 0, 0, hours, minutes, seconds, 0);
 216     }
 217 
 218     /**
 219      * Obtains a {@code Period} from time-based fields.
 220      * <p>
 221      * This creates an instance based on hours, minutes, seconds and nanoseconds.
 222      * Within a period, the time fields are always normalized.
 223      *
 224      * @param hours  the amount of hours, may be negative
 225      * @param minutes  the amount of minutes, may be negative
 226      * @param seconds  the amount of seconds, may be negative
 227      * @param nanos  the amount of nanos, may be negative
 228      * @return the period, not null
 229      */
 230     public static Period ofTime(int hours, int minutes, int seconds, long nanos) {
 231         return of(0, 0, 0, hours, minutes, seconds, nanos);
 232     }
 233 
 234     //-----------------------------------------------------------------------
 235     /**
 236      * Obtains an instance of {@code Period} from a period in the specified unit.
 237      * <p>
 238      * The parameters represent the two parts of a phrase like '6 Days'. For example:
 239      * <pre>
 240      *  Period.of(3, SECONDS);
 241      *  Period.of(5, YEARS);
 242      * </pre>
 243      * The specified unit must be one of the supported units from {@link ChronoUnit},
 244      * {@code YEARS}, {@code MONTHS} or {@code DAYS} or be a time unit with an
 245      * {@linkplain TemporalUnit#isDurationEstimated() exact duration}.
 246      * Other units throw an exception.
 247      *
 248      * @param amount  the amount of the period, measured in terms of the unit, positive or negative
 249      * @param unit  the unit that the period is measured in, must have an exact duration, not null
 250      * @return the period, not null
 251      * @throws DateTimeException if the period unit is invalid
 252      * @throws ArithmeticException if a numeric overflow occurs
 253      */
 254     public static Period of(long amount, TemporalUnit unit) {
 255         return ZERO.plus(amount, unit);
 256     }
 257 
 258     //-----------------------------------------------------------------------
 259     /**
 260      * Obtains a {@code Period} from a {@code Duration}.
 261      * <p>
 262      * This converts the duration to a period.
 263      * Within a period, the time fields are always normalized.
 264      * The years, months and days fields will be zero.
 265      * <p>
 266      * To populate the days field, call {@link #normalizedHoursToDays()} on the created period.
 267      *
 268      * @param duration  the duration to convert, not null
 269      * @return the period, not null
 270      * @throws ArithmeticException if numeric overflow occurs
 271      */
 272     public static Period of(Duration duration) {
 273         Objects.requireNonNull(duration, "duration");
 274         if (duration.isZero()) {
 275             return ZERO;
 276         }
 277         return new Period(0, 0, 0, duration.toNanos());
 278     }
 279 
 280     //-----------------------------------------------------------------------
 281     /**
 282      * Returns a {@code Period} consisting of the number of years, months, days,
 283      * hours, minutes, seconds, and nanoseconds between two {@code TemporalAccessor} instances.
 284      * <p>
 285      * The start date is included, but the end date is not. Only whole years count.
 286      * For example, from {@code 2010-01-15} to {@code 2011-03-18} is one year, two months and three days.
 287      * <p>
 288      * This method examines the {@link ChronoField fields} {@code YEAR}, {@code MONTH_OF_YEAR},
 289      * {@code DAY_OF_MONTH} and {@code NANO_OF_DAY}
 290      * The difference between each of the fields is calculated independently from the others.
 291      * At least one of the four fields must be present.
 292      * <p>
 293      * The four units are typically retained without normalization.
 294      * However, years and months are normalized if the range of months is fixed, as it is with ISO.
 295      * <p>
 296      * The result of this method can be a negative period if the end is before the start.
 297      * The negative sign can be different in each of the four major units.
 298      *
 299      * @param start  the start date, inclusive, not null
 300      * @param end  the end date, exclusive, not null
 301      * @return the period between the date-times, not null
 302      * @throws DateTimeException if the two date-times do have similar available fields
 303      * @throws ArithmeticException if numeric overflow occurs
 304      */
 305     public static Period between(TemporalAccessor start, TemporalAccessor end) {
 306         if (Chrono.from(start).equals(Chrono.from(end)) == false) {
 307             throw new DateTimeException("Unable to calculate period as date-times have different chronologies");
 308         }
 309         int years = 0;
 310         int months = 0;
 311         int days = 0;
 312         long nanos = 0;
 313         boolean valid = false;
 314         if (start.isSupported(YEAR)) {
 315             years = Math.toIntExact(Math.subtractExact(end.getLong(YEAR), start.getLong(YEAR)));
 316             valid = true;
 317         }
 318         if (start.isSupported(MONTH_OF_YEAR)) {
 319             months = Math.toIntExact(Math.subtractExact(end.getLong(MONTH_OF_YEAR), start.getLong(MONTH_OF_YEAR)));
 320             ValueRange startRange = Chrono.from(start).range(MONTH_OF_YEAR);
 321             ValueRange endRange = Chrono.from(end).range(MONTH_OF_YEAR);
 322             if (startRange.isFixed() && startRange.isIntValue() && startRange.equals(endRange)) {
 323                 int monthCount = (int) (startRange.getMaximum() - startRange.getMinimum() + 1);
 324                 long totMonths = ((long) months) + years * monthCount;
 325                 months = (int) (totMonths % monthCount);
 326                 years = Math.toIntExact(totMonths / monthCount);
 327             }
 328             valid = true;
 329         }
 330         if (start.isSupported(DAY_OF_MONTH)) {
 331             days = Math.toIntExact(Math.subtractExact(end.getLong(DAY_OF_MONTH), start.getLong(DAY_OF_MONTH)));
 332             valid = true;
 333         }
 334         if (start.isSupported(NANO_OF_DAY)) {
 335             nanos = Math.subtractExact(end.getLong(NANO_OF_DAY), start.getLong(NANO_OF_DAY));
 336             valid = true;
 337         }
 338         if (valid == false) {
 339             throw new DateTimeException("Unable to calculate period as date-times do not have any valid fields");
 340         }
 341         return create(years, months, days, nanos);
 342     }
 343 
 344     //-----------------------------------------------------------------------
 345     /**
 346      * Obtains a {@code Period} consisting of the number of years, months,
 347      * and days between two dates.
 348      * <p>
 349      * The start date is included, but the end date is not.
 350      * The period is calculated by removing complete months, then calculating
 351      * the remaining number of days, adjusting to ensure that both have the same sign.
 352      * The number of months is then split into years and months based on a 12 month year.
 353      * A month is considered if the end day-of-month is greater than or equal to the start day-of-month.
 354      * For example, from {@code 2010-01-15} to {@code 2011-03-18} is one year, two months and three days.
 355      * <p>
 356      * The result of this method can be a negative period if the end is before the start.
 357      * The negative sign will be the same in each of year, month and day.
 358      *
 359      * @param startDate  the start date, inclusive, not null
 360      * @param endDate  the end date, exclusive, not null
 361      * @return the period between the dates, not null
 362      * @throws ArithmeticException if numeric overflow occurs
 363      */
 364     public static Period betweenISO(LocalDate startDate, LocalDate endDate) {
 365         long startMonth = startDate.getLong(EPOCH_MONTH);
 366         long endMonth = endDate.getLong(EPOCH_MONTH);
 367         long totalMonths = endMonth - startMonth;  // safe
 368         int days = endDate.getDayOfMonth() - startDate.getDayOfMonth();
 369         if (totalMonths > 0 && days < 0) {
 370             totalMonths--;
 371             LocalDate calcDate = startDate.plusMonths(totalMonths);
 372             days = (int) (endDate.toEpochDay() - calcDate.toEpochDay());  // safe
 373         } else if (totalMonths < 0 && days > 0) {
 374             totalMonths++;
 375             days -= endDate.lengthOfMonth();
 376         }
 377         long years = totalMonths / 12;  // safe
 378         int months = (int) (totalMonths % 12);  // safe
 379         return ofDate(Math.toIntExact(years), months, days);
 380     }
 381 
 382     //-----------------------------------------------------------------------
 383     /**
 384      * Obtains a {@code Period} consisting of the number of hours, minutes,
 385      * seconds and nanoseconds between two times.
 386      * <p>
 387      * The start time is included, but the end time is not.
 388      * The period is calculated from the difference between the nano-of-day values
 389      * of the two times. For example, from {@code 13:45:00} to {@code 14:50:30.123456789}
 390      * is {@code P1H5M30.123456789S}.
 391      * <p>
 392      * The result of this method can be a negative period if the end is before the start.
 393      *
 394      * @param startTime  the start time, inclusive, not null
 395      * @param endTime  the end time, exclusive, not null
 396      * @return the period between the times, not null
 397      * @throws ArithmeticException if numeric overflow occurs
 398      */
 399     public static Period betweenISO(LocalTime startTime, LocalTime endTime) {
 400         return create(0, 0, 0, endTime.toNanoOfDay() - startTime.toNanoOfDay());
 401     }
 402 
 403     //-----------------------------------------------------------------------
 404     /**
 405      * Obtains a {@code Period} from a text string such as {@code PnYnMnDTnHnMn.nS}.
 406      * <p>
 407      * This will parse the string produced by {@code toString()} which is
 408      * a subset of the ISO-8601 period format {@code PnYnMnDTnHnMn.nS}.












 409      * <p>
 410      * The string consists of a series of numbers with a suffix identifying their meaning.
 411      * The values, and suffixes, must be in the sequence year, month, day, hour, minute, second.
 412      * Any of the number/suffix pairs may be omitted providing at least one is present.
 413      * If the period is zero, the value is normally represented as {@code PT0S}.
 414      * The numbers must consist of ASCII digits.
 415      * Any of the numbers may be negative. Negative zero is not accepted.
 416      * The number of nanoseconds is expressed as an optional fraction of the seconds.
 417      * There must be at least one digit before any decimal point.
 418      * There must be between 1 and 9 inclusive digits after any decimal point.
 419      * The letters will all be accepted in upper or lower case.
 420      * The decimal point may be either a dot or a comma.
 421      *
 422      * @param text  the text to parse, not null
 423      * @return the parsed period, not null
 424      * @throws DateTimeParseException if the text cannot be parsed to a period
 425      */
 426     public static Period parse(final CharSequence text) {
 427         Objects.requireNonNull(text, "text");
 428         return new PeriodParser(text).parse();




























 429     }
 430 
 431     //-----------------------------------------------------------------------
 432     /**
 433      * Creates an instance.
 434      *
 435      * @param years  the amount
 436      * @param months  the amount
 437      * @param days  the amount
 438      * @param nanos  the amount
 439      */
 440     private static Period create(int years, int months, int days, long nanos) {
 441         if ((years | months | days | nanos) == 0) {
 442             return ZERO;
 443         }
 444         return new Period(years, months, days, nanos);
 445     }
 446 
 447     /**
 448      * Constructor.
 449      *
 450      * @param years  the amount
 451      * @param months  the amount
 452      * @param days  the amount
 453      * @param nanos  the amount
 454      */
 455     private Period(int years, int months, int days, long nanos) {
 456         this.years = years;
 457         this.months = months;
 458         this.days = days;
 459         this.nanos = nanos;
 460     }
 461 

 462     /**
 463      * Resolves singletons.
 464      *
 465      * @return the resolved instance







 466      */
 467     private Object readResolve() {
 468         if ((years | months | days | nanos) == 0) {
 469             return ZERO;







 470         }
 471         return this;
















 472     }
 473 
 474     //-----------------------------------------------------------------------
 475     /**
 476      * Checks if this period is zero-length.


 477      *
 478      * @return true if this period is zero-length
 479      */
 480     public boolean isZero() {
 481         return (this == ZERO);
 482     }
 483 
 484     /**
 485      * Checks if this period is fully positive, excluding zero.
 486      * <p>
 487      * This checks whether all the amounts in the period are positive,
 488      * defined as greater than zero.
 489      *
 490      * @return true if this period is fully positive excluding zero
 491      */
 492     public boolean isPositive() {
 493         return ((years | months | days | nanos) > 0);
 494     }
 495 
 496     //-----------------------------------------------------------------------
 497     /**
 498      * Gets the amount of years of this period.






 499      *
 500      * @return the amount of years of this period
 501      */
 502     public int getYears() {
 503         return years;
 504     }
 505 
 506     /**
 507      * Gets the amount of months of this period.






 508      *
 509      * @return the amount of months of this period
 510      */
 511     public int getMonths() {
 512         return months;
 513     }
 514 
 515     /**
 516      * Gets the amount of days of this period.


 517      *
 518      * @return the amount of days of this period
 519      */
 520     public int getDays() {
 521         return days;
 522     }
 523 
 524     /**
 525      * Gets the amount of hours of this period.
 526      * <p>
 527      * Within a period, the time fields are always normalized.
 528      *
 529      * @return the amount of hours of this period
 530      */
 531     public int getHours() {
 532         return (int) (nanos / NANOS_PER_HOUR);
 533     }
 534 
 535     /**
 536      * Gets the amount of minutes within an hour of this period.
 537      * <p>
 538      * Within a period, the time fields are always normalized.
 539      *
 540      * @return the amount of minutes within an hour of this period
 541      */
 542     public int getMinutes() {
 543         return (int) ((nanos / NANOS_PER_MINUTE) % 60);
 544     }
 545 
 546     /**
 547      * Gets the amount of seconds within a minute of this period.
 548      * <p>
 549      * Within a period, the time fields are always normalized.
 550      *
 551      * @return the amount of seconds within a minute of this period
 552      */
 553     public int getSeconds() {
 554         return (int) ((nanos / NANOS_PER_SECOND) % 60);
 555     }
 556 
 557     /**
 558      * Gets the amount of nanoseconds within a second of this period.
 559      * <p>
 560      * Within a period, the time fields are always normalized.
 561      *
 562      * @return the amount of nanoseconds within a second of this period
 563      */
 564     public int getNanos() {
 565         return (int) (nanos % NANOS_PER_SECOND);  // safe from overflow
 566     }
 567 
 568     /**
 569      * Gets the total amount of the time units of this period, measured in nanoseconds.
 570      * <p>
 571      * Within a period, the time fields are always normalized.
 572      *
 573      * @return the total amount of time unit nanoseconds of this period
 574      */
 575     public long getTimeNanos() {
 576         return nanos;
 577     }
 578 
 579     //-----------------------------------------------------------------------
 580     /**
 581      * Returns a copy of this period with the specified amount of years.
 582      * <p>
 583      * This method will only affect the years field.
 584      * All other units are unaffected.




 585      * <p>
 586      * This instance is immutable and unaffected by this method call.
 587      *
 588      * @param years  the years to represent
 589      * @return a {@code Period} based on this period with the requested years, not null
 590      */
 591     public Period withYears(int years) {
 592         if (years == this.years) {
 593             return this;
 594         }
 595         return create(years, months, days, nanos);
 596     }
 597 
 598     /**
 599      * Returns a copy of this period with the specified amount of months.
 600      * <p>
 601      * This method will only affect the months field.
 602      * All other units are unaffected.




 603      * <p>
 604      * This instance is immutable and unaffected by this method call.
 605      *
 606      * @param months  the months to represent
 607      * @return a {@code Period} based on this period with the requested months, not null
 608      */
 609     public Period withMonths(int months) {
 610         if (months == this.months) {
 611             return this;
 612         }
 613         return create(years, months, days, nanos);
 614     }
 615 
 616     /**
 617      * Returns a copy of this period with the specified amount of days.
 618      * <p>
 619      * This method will only affect the days field.
 620      * All other units are unaffected.
 621      * <p>
 622      * This instance is immutable and unaffected by this method call.
 623      *
 624      * @param days  the days to represent
 625      * @return a {@code Period} based on this period with the requested days, not null
 626      */
 627     public Period withDays(int days) {
 628         if (days == this.days) {
 629             return this;
 630         }
 631         return create(years, months, days, nanos);
 632     }
 633 
 634     /**
 635      * Returns a copy of this period with the specified total amount of time units
 636      * expressed in nanoseconds.
 637      * <p>
 638      * Within a period, the time fields are always normalized.
 639      * This method will affect all the time units - hours, minutes, seconds and nanos.
 640      * The date units are unaffected.
 641      * <p>
 642      * This instance is immutable and unaffected by this method call.
 643      *
 644      * @param nanos  the nanoseconds to represent
 645      * @return a {@code Period} based on this period with the requested nanoseconds, not null
 646      */
 647     public Period withTimeNanos(long nanos) {
 648         if (nanos == this.nanos) {
 649             return this;
 650         }
 651         return create(years, months, days, nanos);
 652     }
 653 
 654     //-----------------------------------------------------------------------
 655     /**
 656      * Returns a copy of this period with the specified period added.
 657      * <p>
 658      * This operates separately on the years, months, days and the normalized time.
 659      * There is no further normalization beyond the normalized time.
 660      * <p>



 661      * This instance is immutable and unaffected by this method call.
 662      *
 663      * @param other  the period to add, not null
 664      * @return a {@code Period} based on this period with the requested period added, not null
 665      * @throws ArithmeticException if numeric overflow occurs
 666      */
 667     public Period plus(Period other) {
 668         return create(
 669                 Math.addExact(years, other.years),
 670                 Math.addExact(months, other.months),
 671                 Math.addExact(days, other.days),
 672                 Math.addExact(nanos, other.nanos));
 673     }
 674 
 675     /**
 676      * Returns a copy of this period with the specified period added.
 677      * <p>
 678      * The specified unit must be one of the supported units from {@link ChronoUnit},
 679      * {@code YEARS}, {@code MONTHS} or {@code DAYS} or be a time unit with an
 680      * {@linkplain TemporalUnit#isDurationEstimated() exact duration}.
 681      * Other units throw an exception.
 682      * <p>
 683      * This instance is immutable and unaffected by this method call.
 684      *
 685      * @param amount  the amount to add, positive or negative
 686      * @param unit  the unit that the amount is expressed in, not null
 687      * @return a {@code Period} based on this period with the requested amount added, not null
 688      * @throws ArithmeticException if numeric overflow occurs
 689      */
 690     public Period plus(long amount, TemporalUnit unit) {
 691         Objects.requireNonNull(unit, "unit");
 692         if (unit instanceof ChronoUnit) {
 693             if (unit == YEARS || unit == MONTHS || unit == DAYS || unit.isDurationEstimated() == false) {
 694                 if (amount == 0) {
 695                     return this;
 696                 }
 697                 switch((ChronoUnit) unit) {
 698                     case NANOS: return plusNanos(amount);
 699                     case MICROS: return plusNanos(Math.multiplyExact(amount, 1000L));
 700                     case MILLIS: return plusNanos(Math.multiplyExact(amount, 1000_000L));
 701                     case SECONDS: return plusSeconds(amount);
 702                     case MINUTES: return plusMinutes(amount);
 703                     case HOURS: return plusHours(amount);
 704                     case HALF_DAYS: return plusNanos(Math.multiplyExact(amount, 12 * NANOS_PER_HOUR));
 705                     case DAYS: return plusDays(amount);
 706                     case MONTHS: return plusMonths(amount);
 707                     case YEARS: return plusYears(amount);
 708                     default: throw new DateTimeException("Unsupported unit: " + unit.getName());
 709                 }
 710             }
 711         }
 712         if (unit.isDurationEstimated()) {
 713             throw new DateTimeException("Unsupported unit: " + unit.getName());
 714         }
 715         return plusNanos(Duration.of(amount, unit).toNanos());
 716     }
 717 
 718     public Period plusYears(long amount) {
 719         return create(Math.toIntExact(Math.addExact(years, amount)), months, days, nanos);
 720     }
 721 
 722     public Period plusMonths(long amount) {
 723         return create(years, Math.toIntExact(Math.addExact(months, amount)), days, nanos);
 724     }
 725 
 726     public Period plusDays(long amount) {
 727         return create(years, months, Math.toIntExact(Math.addExact(days, amount)), nanos);
 728     }
 729 
 730     public Period plusHours(long amount) {
 731         return plusNanos(Math.multiplyExact(amount, NANOS_PER_HOUR));


 732     }
 733 
 734     public Period plusMinutes(long amount) {
 735         return plusNanos(Math.multiplyExact(amount, NANOS_PER_MINUTE));
 736     }
 737 
 738     public Period plusSeconds(long amount) {
 739         return plusNanos(Math.multiplyExact(amount, NANOS_PER_SECOND));














 740     }
 741 
 742     public Period plusNanos(long amount) {
 743         return create(years, months, days, Math.addExact(nanos,  amount));
 744     }
 745 
 746     //-----------------------------------------------------------------------
 747     /**
 748      * Returns a copy of this period with the specified period subtracted.
 749      * <p>
 750      * This operates separately on the years, months, days and the normalized time.
 751      * There is no further normalization beyond the normalized time.
 752      * <p>



 753      * This instance is immutable and unaffected by this method call.
 754      *
 755      * @param other  the period to subtract, not null
 756      * @return a {@code Period} based on this period with the requested period subtracted, not null
 757      * @throws ArithmeticException if numeric overflow occurs
 758      */
 759     public Period minus(Period other) {
 760         return create(
 761                 Math.subtractExact(years, other.years),
 762                 Math.subtractExact(months, other.months),
 763                 Math.subtractExact(days, other.days),
 764                 Math.subtractExact(nanos, other.nanos));
 765     }
 766 
 767     /**
 768      * Returns a copy of this period with the specified period subtracted.
 769      * <p>
 770      * The specified unit must be one of the supported units from {@link ChronoUnit},
 771      * {@code YEARS}, {@code MONTHS} or {@code DAYS} or be a time unit with an
 772      * {@linkplain TemporalUnit#isDurationEstimated() exact duration}.
 773      * Other units throw an exception.
 774      * <p>
 775      * This instance is immutable and unaffected by this method call.
 776      *
 777      * @param amount  the amount to subtract, positive or negative
 778      * @param unit  the unit that the amount is expressed in, not null
 779      * @return a {@code Period} based on this period with the requested amount subtracted, not null
 780      * @throws ArithmeticException if numeric overflow occurs
 781      */
 782     public Period minus(long amount, TemporalUnit unit) {
 783         return (amount == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amount, unit));
 784     }
 785 
 786     public Period minusYears(long amount) {
 787         return (amount == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-amount));
 788     }
 789 
 790     public Period minusMonths(long amount) {
 791         return (amount == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-amount));
 792     }
 793 
 794     public Period minusDays(long amount) {
 795         return (amount == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-amount));
 796     }
 797 
 798     public Period minusHours(long amount) {
 799         return (amount == Long.MIN_VALUE ? plusHours(Long.MAX_VALUE).plusHours(1) : plusHours(-amount));
 800     }
 801 
 802     public Period minusMinutes(long amount) {
 803         return (amount == Long.MIN_VALUE ? plusMinutes(Long.MAX_VALUE).plusMinutes(1) : plusMinutes(-amount));
 804     }
 805 
 806     public Period minusSeconds(long amount) {
 807         return (amount == Long.MIN_VALUE ? plusSeconds(Long.MAX_VALUE).plusSeconds(1) : plusSeconds(-amount));

 808     }
 809 
 810     public Period minusNanos(long amount) {
 811         return (amount == Long.MIN_VALUE ? plusNanos(Long.MAX_VALUE).plusNanos(1) : plusNanos(-amount));













 812     }
 813 
 814     //-----------------------------------------------------------------------
 815     /**
 816      * Returns a new instance with each element in this period multiplied
 817      * by the specified scalar.
 818      * <p>
 819      * This simply multiplies each field, years, months, days and normalized time,
 820      * by the scalar. No normalization is performed.



 821      *
 822      * @param scalar  the scalar to multiply by, not null
 823      * @return a {@code Period} based on this period with the amounts multiplied by the scalar, not null
 824      * @throws ArithmeticException if numeric overflow occurs
 825      */
 826     public Period multipliedBy(int scalar) {
 827         if (this == ZERO || scalar == 1) {
 828             return this;
 829         }
 830         return create(
 831                 Math.multiplyExact(years, scalar),
 832                 Math.multiplyExact(months, scalar),
 833                 Math.multiplyExact(days, scalar),
 834                 Math.multiplyExact(nanos, scalar));
 835     }
 836 
 837     /**
 838      * Returns a new instance with each amount in this period negated.






 839      *
 840      * @return a {@code Period} based on this period with the amounts negated, not null
 841      * @throws ArithmeticException if numeric overflow occurs

 842      */
 843     public Period negated() {
 844         return multipliedBy(-1);
 845     }
 846 
 847     //-----------------------------------------------------------------------
 848     /**
 849      * Returns a copy of this period with the days and hours normalized using a 24 hour day.
 850      * <p>
 851      * This normalizes the days and hours units, leaving years and months unchanged.
 852      * The hours unit is adjusted to have an absolute value less than 23,
 853      * with the days unit being adjusted to compensate.
 854      * For example, a period of {@code P1DT27H} will be normalized to {@code P2DT3H}.
 855      * <p>
 856      * The sign of the days and hours units will be the same after normalization.
 857      * For example, a period of {@code P1DT-51H} will be normalized to {@code P-1DT-3H}.
 858      * Since all time units are always normalized, if the hours units changes sign then
 859      * other time units will also be affected.
 860      * <p>
 861      * This instance is immutable and unaffected by this method call.
 862      *
 863      * @return a {@code Period} based on this period with excess hours normalized to days, not null
 864      * @throws ArithmeticException if numeric overflow occurs
 865      */
 866     public Period normalizedHoursToDays() {
 867         // logic uses if statements to normalize signs to avoid unnecessary overflows
 868         long totalDays = (nanos / NANOS_PER_DAY) + days;  // no overflow
 869         long splitNanos = nanos % NANOS_PER_DAY;
 870         if (totalDays > 0 && splitNanos < 0) {
 871             splitNanos += NANOS_PER_DAY;
 872             totalDays--;
 873         } else if (totalDays < 0 && splitNanos > 0) {
 874             splitNanos -= NANOS_PER_DAY;
 875             totalDays++;
 876         }
 877         if (totalDays == days && splitNanos == nanos) {
 878             return this;
 879         }
 880         return create(years, months, Math.toIntExact(totalDays), splitNanos);
 881     }
 882 
 883     /**
 884      * Returns a copy of this period with any days converted to hours using a 24 hour day.
 885      * <p>
 886      * The days unit is reduced to zero, with the hours unit increased by 24 times the
 887      * days unit to compensate. Other units are unaffected.
 888      * For example, a period of {@code P2DT4H} will be normalized to {@code PT52H}.
 889      * <p>
 890      * This instance is immutable and unaffected by this method call.
 891      *
 892      * @return a {@code Period} based on this period with days normalized to hours, not null
 893      * @throws ArithmeticException if numeric overflow occurs
 894      */
 895     public Period normalizedDaysToHours() {
 896         if (days == 0) {
 897             return this;
 898         }
 899         return create(years, months, 0, Math.addExact(Math.multiplyExact(days, NANOS_PER_DAY), nanos));
 900     }
 901 
 902     /**
 903      * Returns a copy of this period with the years and months normalized using a 12 month year.
 904      * <p>
 905      * This normalizes the years and months units, leaving other units unchanged.
 906      * The months unit is adjusted to have an absolute value less than 11,
 907      * with the years unit being adjusted to compensate.
 908      * For example, a period of {@code P1Y15M} will be normalized to {@code P2Y3M}.
 909      * <p>
 910      * The sign of the years and months units will be the same after normalization.
 911      * For example, a period of {@code P1Y-25M} will be normalized to {@code P-1Y-1M}.

 912      * <p>
 913      * This normalization uses a 12 month year it is not valid for all calendar systems.
 914      * <p>
 915      * This instance is immutable and unaffected by this method call.
 916      *
 917      * @return a {@code Period} based on this period with years and months normalized, not null
 918      * @throws ArithmeticException if numeric overflow occurs
 919      */
 920     public Period normalizedMonthsISO() {
 921         long totalMonths = years * 12L + months;  // no overflow
 922         long splitYears = totalMonths / 12;
 923         int splitMonths = (int) (totalMonths % 12);  // no overflow
 924         if (splitYears == years && splitMonths == months) {
 925             return this;
 926         }
 927         return create(Math.toIntExact(splitYears), splitMonths, days, nanos);
 928     }
 929 
 930     //-------------------------------------------------------------------------
 931     /**
 932      * Converts this period to one that only has date units.



 933      * <p>
 934      * The resulting period will have the same years, months and days as this period
 935      * but the time units will all be zero. No normalization occurs in the calculation.
 936      * For example, a period of {@code P1Y3MT12H} will be converted to {@code P1Y3M}.
 937      * <p>
 938      * This instance is immutable and unaffected by this method call.
 939      *
 940      * @return a {@code Period} based on this period with the time units set to zero, not null
 941      */
 942     public Period toDateOnly() {
 943         if (nanos == 0) {
 944             return this;
 945         }
 946         return create(years, months, days, 0);
 947     }
 948 
 949     //-------------------------------------------------------------------------
 950     /**
 951      * Adds this period to the specified temporal object.
 952      * <p>
 953      * This returns a temporal object of the same observable type as the input
 954      * with this period added.
 955      * <p>
 956      * In most cases, it is clearer to reverse the calling pattern by using
 957      * {@link Temporal#plus(TemporalAdder)}.
 958      * <pre>
 959      *   // these two lines are equivalent, but the second approach is recommended
 960      *   dateTime = thisPeriod.addTo(dateTime);
 961      *   dateTime = dateTime.plus(thisPeriod);
 962      * </pre>
 963      * <p>
 964      * The calculation will add the years, then months, then days, then nanos.
 965      * Only non-zero amounts will be added.
 966      * If the date-time has a calendar system with a fixed number of months in a
 967      * year, then the years and months will be combined before being added.
 968      * <p>
 969      * This instance is immutable and unaffected by this method call.
 970      *
 971      * @param temporal  the temporal object to adjust, not null
 972      * @return an object of the same type with the adjustment made, not null
 973      * @throws DateTimeException if unable to add
 974      * @throws ArithmeticException if numeric overflow occurs
 975      */
 976     @Override
 977     public Temporal addTo(Temporal temporal) {
 978         Objects.requireNonNull(temporal, "temporal");
 979         if ((years | months) != 0) {
 980             ValueRange startRange = Chrono.from(temporal).range(MONTH_OF_YEAR);
 981             if (startRange.isFixed() && startRange.isIntValue()) {
 982                 long monthCount = startRange.getMaximum() - startRange.getMinimum() + 1;
 983                 temporal = temporal.plus(years * monthCount + months, MONTHS);
 984             } else {
 985                 if (years != 0) {
 986                     temporal = temporal.plus(years, YEARS);
 987                 }
 988                 if (months != 0) {
 989                     temporal = temporal.plus(months, MONTHS);
 990                 }
 991             }
 992         }
 993         if (days != 0) {
 994             temporal = temporal.plus(days, DAYS);
 995         }
 996         if (nanos != 0) {
 997             temporal = temporal.plus(nanos, NANOS);
 998         }
 999         return temporal;
1000     }
1001 
1002     /**
1003      * Subtracts this period from the specified temporal object.
1004      * <p>
1005      * This returns a temporal object of the same observable type as the input
1006      * with this period subtracted.
1007      * <p>
1008      * In most cases, it is clearer to reverse the calling pattern by using
1009      * {@link Temporal#minus(TemporalSubtractor)}.
1010      * <pre>
1011      *   // these two lines are equivalent, but the second approach is recommended
1012      *   dateTime = thisPeriod.subtractFrom(dateTime);
1013      *   dateTime = dateTime.minus(thisPeriod);
1014      * </pre>
1015      * <p>
1016      * The calculation will subtract the years, then months, then days, then nanos.
1017      * Only non-zero amounts will be subtracted.
1018      * If the date-time has a calendar system with a fixed number of months in a
1019      * year, then the years and months will be combined before being subtracted.
1020      * <p>
1021      * This instance is immutable and unaffected by this method call.
1022      *
1023      * @param temporal  the temporal object to adjust, not null
1024      * @return an object of the same type with the adjustment made, not null
1025      * @throws DateTimeException if unable to subtract
1026      * @throws ArithmeticException if numeric overflow occurs
1027      */
1028     @Override
1029     public Temporal subtractFrom(Temporal temporal) {
1030         Objects.requireNonNull(temporal, "temporal");
1031         if ((years | months) != 0) {
1032             ValueRange startRange = Chrono.from(temporal).range(MONTH_OF_YEAR);
1033             if (startRange.isFixed() && startRange.isIntValue()) {
1034                 long monthCount = startRange.getMaximum() - startRange.getMinimum() + 1;
1035                 temporal = temporal.minus(years * monthCount + months, MONTHS);
1036             } else {
1037                 if (years != 0) {
1038                     temporal = temporal.minus(years, YEARS);
1039                 }
1040                 if (months != 0) {
1041                     temporal = temporal.minus(months, MONTHS);
1042                 }
1043             }
1044         }
1045         if (days != 0) {
1046             temporal = temporal.minus(days, DAYS);
1047         }
1048         if (nanos != 0) {
1049             temporal = temporal.minus(nanos, NANOS);
1050         }
1051         return temporal;
1052     }
1053 
1054     //-----------------------------------------------------------------------
1055     /**
1056      * Converts this period to one that only has time units.
1057      * <p>
1058      * The resulting period will have the same time units as this period
1059      * but the date units will all be zero. No normalization occurs in the calculation.
1060      * For example, a period of {@code P1Y3MT12H} will be converted to {@code PT12H}.
1061      * <p>
1062      * This instance is immutable and unaffected by this method call.
1063      *
1064      * @return a {@code Period} based on this period with the date units set to zero, not null

1065      */
1066     public Period toTimeOnly() {
1067         if ((years | months | days) == 0) {
1068             return this;
1069         }
1070         return create(0, 0, 0, nanos);
1071     }
1072 
1073     //-------------------------------------------------------------------------
1074     /**
1075      * Calculates the duration of this period.
1076      * <p>
1077      * The calculation uses the hours, minutes, seconds and nanoseconds fields.
1078      * If years, months or days are present an exception is thrown.
1079      * See {@link #toTimeOnly()} for a way to remove the date units and
1080      * {@link #normalizedDaysToHours()} for a way to convert days to hours.
1081      *
1082      * @return a {@code Duration} equivalent to this period, not null
1083      * @throws DateTimeException if the period cannot be converted as it contains years, months or days
1084      */
1085     public Duration toDuration() {
1086         if ((years | months | days) != 0) {
1087             throw new DateTimeException("Unable to convert period to duration as years/months/days are present: " + this);
1088         }
1089         return Duration.ofNanos(nanos);
1090     }
1091 
1092     //-----------------------------------------------------------------------
1093     /**
1094      * Checks if this period is equal to another period.
1095      * <p>
1096      * The comparison is based on the amounts held in the period.
1097      * To be equal, the years, months, days and normalized time fields must be equal.


1098      *
1099      * @param obj  the object to check, null returns false
1100      * @return true if this is equal to the other period
1101      */
1102     @Override
1103     public boolean equals(Object obj) {
1104         if (this == obj) {
1105             return true;
1106         }
1107         if (obj instanceof Period) {
1108             Period other = (Period) obj;
1109             return years == other.years && months == other.months &&
1110                     days == other.days && nanos == other.nanos;

1111         }
1112         return false;
1113     }
1114 
1115     /**
1116      * A hash code for this period.
1117      *
1118      * @return a suitable hash code
1119      */
1120     @Override
1121     public int hashCode() {
1122         // ordered such that overflow from one field doesn't immediately affect the next field
1123         return ((years << 27) | (years >>> 5)) ^
1124                 ((days << 21) | (days >>> 11)) ^
1125                 ((months << 17) | (months >>> 15)) ^
1126                 ((int) (nanos ^ (nanos >>> 32)));
1127     }
1128 
1129     //-----------------------------------------------------------------------
1130     /**
1131      * Outputs this period as a {@code String}, such as {@code P6Y3M1DT12H}.
1132      * <p>
1133      * The output will be in the ISO-8601 period format.

1134      *
1135      * @return a string representation of this period, not null
1136      */
1137     @Override
1138     public String toString() {
1139         if (this == ZERO) {
1140             return "PT0S";
1141         } else {
1142             StringBuilder buf = new StringBuilder();
1143             buf.append('P');
1144             if (years != 0) {
1145                 buf.append(years).append('Y');
1146             }
1147             if (months != 0) {
1148                 buf.append(months).append('M');
1149             }
1150             if (days != 0) {
1151                 buf.append(days).append('D');
1152             }
1153             if (nanos != 0) {
1154                 buf.append('T');
1155                 if (getHours() != 0) {
1156                     buf.append(getHours()).append('H');
1157                 }
1158                 if (getMinutes() != 0) {
1159                     buf.append(getMinutes()).append('M');
1160                 }
1161                 int secondPart = getSeconds();
1162                 int nanoPart = getNanos();
1163                 int secsNanosOr = secondPart | nanoPart;
1164                 if (secsNanosOr != 0) {  // if either non-zero
1165                     if ((secsNanosOr & Integer.MIN_VALUE) != 0) {  // if either less than zero
1166                         buf.append('-');
1167                         secondPart = Math.abs(secondPart);
1168                         nanoPart = Math.abs(nanoPart);
1169                     }
1170                     buf.append(secondPart);
1171                     if (nanoPart != 0) {
1172                         int dotPos = buf.length();
1173                         nanoPart += 1000_000_000;
1174                         while (nanoPart % 10 == 0) {
1175                             nanoPart /= 10;
1176                         }
1177                         buf.append(nanoPart);
1178                         buf.setCharAt(dotPos, '.');
1179                     }
1180                     buf.append('S');















1181                 }








1182             }
1183             return buf.toString();




1184         }






1185     }
1186 
1187 }


  44  *    and/or other materials provided with the distribution.
  45  *
  46  *  * Neither the name of JSR-310 nor the names of its contributors
  47  *    may be used to endorse or promote products derived from this software
  48  *    without specific prior written permission.
  49  *
  50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  54  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  55  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  56  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  57  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  58  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  59  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  61  */
  62 package java.time;
  63 






  64 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;


  65 import static java.time.temporal.ChronoUnit.DAYS;
  66 import static java.time.temporal.ChronoUnit.MONTHS;

  67 import static java.time.temporal.ChronoUnit.YEARS;
  68 
  69 import java.io.DataInput;
  70 import java.io.DataOutput;
  71 import java.io.IOException;
  72 import java.io.InvalidObjectException;
  73 import java.io.ObjectStreamException;
  74 import java.io.Serializable;
  75 import java.time.chrono.ChronoLocalDate;
  76 import java.time.chrono.Chronology;
  77 import java.time.format.DateTimeParseException;


  78 import java.time.temporal.ChronoUnit;
  79 import java.time.temporal.Temporal;
  80 import java.time.temporal.TemporalAmount;


  81 import java.time.temporal.TemporalUnit;
  82 import java.time.temporal.ValueRange;
  83 import java.util.Arrays;
  84 import java.util.Collections;
  85 import java.util.List;
  86 import java.util.Objects;
  87 import java.util.regex.Matcher;
  88 import java.util.regex.Pattern;
  89 
  90 /**
  91  * A date-based amount of time, such as '2 years, 3 months and 4 days'.
  92  * <p>
  93  * This class models a quantity or amount of time in terms of years, months and days.
  94  * See {@link Duration} for the time-based equivalent to this class.
  95  * <p>
  96  * Durations and period differ in their treatment of daylight savings time
  97  * when added to {@link ZonedDateTime}. A {@code Duration} will add an exact
  98  * number of seconds, thus a duration of one day is always exactly 24 hours.
  99  * By contrast, a {@code Period} will add a conceptual day, trying to maintain
 100  * the local time.
 101  * <p>
 102  * For example, consider adding a period of one day and a duration of one day to
 103  * 18:00 on the evening before a daylight savings gap. The {@code Period} will add
 104  * the conceptual day and result in a {@code ZonedDateTime} at 18:00 the following day.
 105  * By contrast, the {@code Duration} will add exactly 24 hours, resulting in a
 106  * {@code ZonedDateTime} at 19:00 the following day (assuming a one hour DST gap).
 107  * <p>
 108  * The supported units of a period are {@link ChronoUnit#YEARS YEARS},
 109  * {@link ChronoUnit#MONTHS MONTHS} and {@link ChronoUnit#DAYS DAYS}.
 110  * All three fields are always present, but may be set to zero.
 111  * <p>
 112  * The period may be used with any calendar system.
 113  * The meaning of a "year" or "month" is only applied when the object is added to a date.
 114  * <p>
 115  * The period is modeled as a directed amount of time, meaning that individual parts of the
 116  * period may be negative.
 117  * <p>
 118  * The months and years fields may be {@linkplain #normalized() normalized}.
 119  * The normalization assumes a 12 month year, so is not appropriate for all calendar systems.
 120  *
 121  * <h3>Specification for implementors</h3>
 122  * This class is immutable and thread-safe.


 123  *
 124  * @since 1.8
 125  */
 126 public final class Period
 127         implements TemporalAmount, Serializable {

 128 
 129     /**
 130      * A constant for a period of zero.
 131      */
 132     public static final Period ZERO = new Period(0, 0, 0);
 133     /**
 134      * Serialization version.
 135      */
 136     private static final long serialVersionUID = -3587258372562876L;
 137     /**
 138      * The pattern for parsing.
 139      */
 140     private final static Pattern PATTERN =
 141             Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)Y)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)D)?", Pattern.CASE_INSENSITIVE);
 142     /**
 143      * The set of supported units.
 144      */
 145     private final static List<TemporalUnit> SUPPORTED_UNITS =
 146             Collections.unmodifiableList(Arrays.<TemporalUnit>asList(YEARS, MONTHS, DAYS));
 147 
 148     /**
 149      * The number of years.
 150      */
 151     private final int years;
 152     /**
 153      * The number of months.
 154      */
 155     private final int months;
 156     /**
 157      * The number of days.
 158      */
 159     private final int days;




 160 
 161     //-----------------------------------------------------------------------
 162     /**
 163      * Obtains a {@code Period} representing a number of years.
 164      * <p>
 165      * The resulting period will have the specified years.
 166      * The months and days units will be zero.
 167      *
 168      * @param years  the number of years, positive or negative
 169      * @return the period of years, not null





 170      */
 171     public static Period ofYears(int years) {
 172         return create(years, 0, 0);
 173     }
 174 
 175     /**
 176      * Obtains a {@code Period} representing a number of months.
 177      * <p>
 178      * The resulting period will have the specified months.
 179      * The years and days units will be zero.
 180      *
 181      * @param months  the number of months, positive or negative
 182      * @return the period of months, not null






 183      */
 184     public static Period ofMonths(int months) {
 185         return create(0, months, 0);





 186     }
 187 

 188     /**
 189      * Obtains a {@code Period} representing a number of days.
 190      * <p>
 191      * The resulting period will have the specified days.
 192      * The years and months units will be zero.
 193      *
 194      * @param days  the number of days, positive or negative
 195      * @return the period of days, not null


 196      */
 197     public static Period ofDays(int days) {
 198         return create(0, 0, days);
 199     }
 200 
 201     //-----------------------------------------------------------------------
 202     /**
 203      * Obtains a {@code Period} representing a number of years, months and days.
 204      * <p>
 205      * This creates an instance based on years, months and days.



























































































 206      *
 207      * @param years  the amount of years, may be negative
 208      * @param months  the amount of months, may be negative
 209      * @param days  the amount of days, may be negative
 210      * @return the period of years, months and days, not null

 211      */
 212     public static Period of(int years, int months, int days) {
 213         return create(years, months, days);



































 214     }
 215 
 216     //-----------------------------------------------------------------------
 217     /**
 218      * Obtains a {@code Period} consisting of the number of years, months,
 219      * and days between two dates.
 220      * <p>
 221      * The start date is included, but the end date is not.
 222      * The period is calculated by removing complete months, then calculating
 223      * the remaining number of days, adjusting to ensure that both have the same sign.
 224      * The number of months is then split into years and months based on a 12 month year.
 225      * A month is considered if the end day-of-month is greater than or equal to the start day-of-month.
 226      * For example, from {@code 2010-01-15} to {@code 2011-03-18} is one year, two months and three days.
 227      * <p>
 228      * The result of this method can be a negative period if the end is before the start.
 229      * The negative sign will be the same in each of year, month and day.
 230      *
 231      * @param startDate  the start date, inclusive, not null
 232      * @param endDate  the end date, exclusive, not null
 233      * @return the period between this date and the end date, not null
 234      * @see ChronoLocalDate#periodUntil(ChronoLocalDate)
 235      */
 236     public static Period between(LocalDate startDate, LocalDate endDate) {
 237         return startDate.periodUntil(endDate);














 238     }
 239 
 240     //-----------------------------------------------------------------------
 241     /**
 242      * Obtains a {@code Period} from a text string such as {@code PnYnMnD}.





















 243      * <p>
 244      * This will parse the string produced by {@code toString()} which is
 245      * based on the ISO-8601 period format {@code PnYnMnD}.
 246      * <p>
 247      * The string starts with an optional sign, denoted by the ASCII negative
 248      * or positive symbol. If negative, the whole period is negated.
 249      * The ASCII letter "P" is next in upper or lower case.
 250      * There are then three sections, each consisting of a number and a suffix.
 251      * At least one of the three sections must be present.
 252      * The sections have suffixes in ASCII of "Y", "M" and "D" for
 253      * years, months and days, accepted in upper or lower case.
 254      * The suffixes must occur in order.
 255      * The number part of each section must consist of ASCII digits.
 256      * The number may be prefixed by the ASCII negative or positive symbol.
 257      * The number must parse to an {@code int}.
 258      * <p>
 259      * The leading plus/minus sign, and negative values for other units are
 260      * not part of the ISO-8601 standard.









 261      *
 262      * @param text  the text to parse, not null
 263      * @return the parsed period, not null
 264      * @throws DateTimeParseException if the text cannot be parsed to a period
 265      */
 266     public static Period parse(CharSequence text) {
 267         Objects.requireNonNull(text, "text");
 268         Matcher matcher = PATTERN.matcher(text);
 269         if (matcher.matches()) {
 270             int negate = ("-".equals(matcher.group(1)) ? -1 : 1);
 271             String yearMatch = matcher.group(2);
 272             String monthMatch = matcher.group(3);
 273             String dayMatch = matcher.group(4);
 274             if (yearMatch != null || monthMatch != null || dayMatch != null) {
 275                 try {
 276                     return create(parseNumber(text, yearMatch, negate),
 277                             parseNumber(text, monthMatch, negate),
 278                             parseNumber(text, dayMatch, negate));
 279                 } catch (NumberFormatException ex) {
 280                     throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Period", text, 0).initCause(ex);
 281                 }
 282             }
 283         }
 284         throw new DateTimeParseException("Text cannot be parsed to a Period", text, 0);
 285     }
 286 
 287     private static int parseNumber(CharSequence text, String str, int negate) {
 288         if (str == null) {
 289             return 0;
 290         }
 291         int val = Integer.parseInt(str);
 292         try {
 293             return Math.multiplyExact(val, negate);
 294         } catch (ArithmeticException ex) {
 295             throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Period", text, 0).initCause(ex);
 296         }
 297     }
 298 
 299     //-----------------------------------------------------------------------
 300     /**
 301      * Creates an instance.
 302      *
 303      * @param years  the amount
 304      * @param months  the amount
 305      * @param days  the amount

 306      */
 307     private static Period create(int years, int months, int days) {
 308         if ((years | months | days) == 0) {
 309             return ZERO;
 310         }
 311         return new Period(years, months, days);
 312     }
 313 
 314     /**
 315      * Constructor.
 316      *
 317      * @param years  the amount
 318      * @param months  the amount
 319      * @param days  the amount

 320      */
 321     private Period(int years, int months, int days) {
 322         this.years = years;
 323         this.months = months;
 324         this.days = days;

 325     }
 326 
 327     //-----------------------------------------------------------------------
 328     /**
 329      * Gets the value of the requested unit.
 330      * <p>
 331      * This returns a value for each of the three supported units,
 332      * {@link ChronoUnit#YEARS YEARS}, {@link ChronoUnit#MONTHS MONTHS} and
 333      * {@link ChronoUnit#DAYS DAYS}.
 334      * All other units throw an exception.
 335      *
 336      * @param unit the {@code TemporalUnit} for which to return the value
 337      * @return the long value of the unit
 338      * @throws DateTimeException if the unit is not supported
 339      */
 340     @Override
 341     public long get(TemporalUnit unit) {
 342         if (unit == ChronoUnit.YEARS) {
 343             return getYears();
 344         } else if (unit == ChronoUnit.MONTHS) {
 345             return getMonths();
 346         } else if (unit == ChronoUnit.DAYS) {
 347             return getDays();
 348         } else {
 349             throw new DateTimeException("Unsupported unit: " + unit.getName());
 350         }
 351     }
 352 
 353     /**
 354      * Gets the set of units supported by this period.
 355      * <p>
 356      * The supported units are {@link ChronoUnit#YEARS YEARS},
 357      * {@link ChronoUnit#MONTHS MONTHS} and {@link ChronoUnit#DAYS DAYS}.
 358      * They are returned in the order years, months, days.
 359      * <p>
 360      * This set can be used in conjunction with {@link #get(TemporalUnit)}
 361      * to access the entire state of the period.
 362      *
 363      * @return a list containing the years, months and days units, not null
 364      */
 365     @Override
 366     public List<TemporalUnit> getUnits() {
 367         return SUPPORTED_UNITS;
 368     }
 369 
 370     //-----------------------------------------------------------------------
 371     /**
 372      * Checks if all three units of this period are zero.
 373      * <p>
 374      * A zero period has the value zero for the years, months and days units.
 375      *
 376      * @return true if this period is zero-length
 377      */
 378     public boolean isZero() {
 379         return (this == ZERO);
 380     }
 381 
 382     /**
 383      * Checks if any of the three units of this period are negative.
 384      * <p>
 385      * This checks whether the years, months or days units are less than zero.

 386      *
 387      * @return true if any unit of this period is negative
 388      */
 389     public boolean isNegative() {
 390         return years < 0 || months < 0 || days < 0;
 391     }
 392 
 393     //-----------------------------------------------------------------------
 394     /**
 395      * Gets the amount of years of this period.
 396      * <p>
 397      * This returns the years unit.
 398      * <p>
 399      * The months unit is not normalized with the years unit.
 400      * This means that a period of "15 months" is different to a period
 401      * of "1 year and 3 months".
 402      *
 403      * @return the amount of years of this period, may be negative
 404      */
 405     public int getYears() {
 406         return years;
 407     }
 408 
 409     /**
 410      * Gets the amount of months of this period.
 411      * <p>
 412      * This returns the months unit.
 413      * <p>
 414      * The months unit is not normalized with the years unit.
 415      * This means that a period of "15 months" is different to a period
 416      * of "1 year and 3 months".
 417      *
 418      * @return the amount of months of this period, may be negative
 419      */
 420     public int getMonths() {
 421         return months;
 422     }
 423 
 424     /**
 425      * Gets the amount of days of this period.
 426      * <p>
 427      * This returns the days unit.
 428      *
 429      * @return the amount of days of this period, may be negative
 430      */
 431     public int getDays() {
 432         return days;
 433     }
 434 























































 435     //-----------------------------------------------------------------------
 436     /**
 437      * Returns a copy of this period with the specified amount of years.
 438      * <p>
 439      * This sets the amount of the years unit in a copy of this period.
 440      * The months and days units are unaffected.
 441      * <p>
 442      * The months unit is not normalized with the years unit.
 443      * This means that a period of "15 months" is different to a period
 444      * of "1 year and 3 months".
 445      * <p>
 446      * This instance is immutable and unaffected by this method call.
 447      *
 448      * @param years  the years to represent, may be negative
 449      * @return a {@code Period} based on this period with the requested years, not null
 450      */
 451     public Period withYears(int years) {
 452         if (years == this.years) {
 453             return this;
 454         }
 455         return create(years, months, days);
 456     }
 457 
 458     /**
 459      * Returns a copy of this period with the specified amount of months.
 460      * <p>
 461      * This sets the amount of the months unit in a copy of this period.
 462      * The years and days units are unaffected.
 463      * <p>
 464      * The months unit is not normalized with the years unit.
 465      * This means that a period of "15 months" is different to a period
 466      * of "1 year and 3 months".
 467      * <p>
 468      * This instance is immutable and unaffected by this method call.
 469      *
 470      * @param months  the months to represent, may be negative
 471      * @return a {@code Period} based on this period with the requested months, not null
 472      */
 473     public Period withMonths(int months) {
 474         if (months == this.months) {
 475             return this;
 476         }
 477         return create(years, months, days);
 478     }
 479 
 480     /**
 481      * Returns a copy of this period with the specified amount of days.
 482      * <p>
 483      * This sets the amount of the days unit in a copy of this period.
 484      * The years and months units are unaffected.
 485      * <p>
 486      * This instance is immutable and unaffected by this method call.
 487      *
 488      * @param days  the days to represent, may be negative
 489      * @return a {@code Period} based on this period with the requested days, not null
 490      */
 491     public Period withDays(int days) {
 492         if (days == this.days) {
 493             return this;
 494         }
 495         return create(years, months, days);




















 496     }
 497 
 498     //-----------------------------------------------------------------------
 499     /**
 500      * Returns a copy of this period with the specified period added.
 501      * <p>
 502      * This operates separately on the years, months, days and the normalized time.
 503      * There is no further normalization beyond the normalized time.
 504      * <p>
 505      * For example, "1 year, 6 months and 3 days" plus "2 years, 2 months and 2 days"
 506      * returns "3 years, 8 months and 5 days".
 507      * <p>
 508      * This instance is immutable and unaffected by this method call.
 509      *
 510      * @param amountToAdd  the period to add, not null
 511      * @return a {@code Period} based on this period with the requested period added, not null
 512      * @throws ArithmeticException if numeric overflow occurs
 513      */
 514     public Period plus(Period amountToAdd) {
 515         return create(
 516                 Math.addExact(years, amountToAdd.years),
 517                 Math.addExact(months, amountToAdd.months),
 518                 Math.addExact(days, amountToAdd.days));

 519     }
 520 
 521     /**
 522      * Returns a copy of this period with the specified years added.
 523      * <p>
 524      * This adds the amount to the years unit in a copy of this period.
 525      * The months and days units are unaffected.
 526      * For example, "1 year, 6 months and 3 days" plus 2 years returns "3 years, 6 months and 3 days".

 527      * <p>
 528      * This instance is immutable and unaffected by this method call.
 529      *
 530      * @param yearsToAdd  the years to add, positive or negative
 531      * @return a {@code Period} based on this period with the specified years added, not null

 532      * @throws ArithmeticException if numeric overflow occurs
 533      */
 534     public Period plusYears(long yearsToAdd) {
 535         if (yearsToAdd == 0) {



 536             return this;
 537         }
 538         return create(Math.toIntExact(Math.addExact(years, yearsToAdd)), months, days);


















 539     }
 540 
 541     /**
 542      * Returns a copy of this period with the specified months added.
 543      * <p>
 544      * This adds the amount to the months unit in a copy of this period.
 545      * The years and days units are unaffected.
 546      * For example, "1 year, 6 months and 3 days" plus 2 months returns "1 year, 8 months and 3 days".
 547      * <p>
 548      * This instance is immutable and unaffected by this method call.
 549      *
 550      * @param monthsToAdd  the months to add, positive or negative
 551      * @return a {@code Period} based on this period with the specified months added, not null
 552      * @throws ArithmeticException if numeric overflow occurs
 553      */
 554     public Period plusMonths(long monthsToAdd) {
 555         if (monthsToAdd == 0) {
 556             return this;
 557         }
 558         return create(years, Math.toIntExact(Math.addExact(months, monthsToAdd)), days);


 559     }
 560 
 561     /**
 562      * Returns a copy of this period with the specified days added.
 563      * <p>
 564      * This adds the amount to the days unit in a copy of this period.
 565      * The years and months units are unaffected.
 566      * For example, "1 year, 6 months and 3 days" plus 2 days returns "1 year, 6 months and 5 days".
 567      * <p>
 568      * This instance is immutable and unaffected by this method call.
 569      *
 570      * @param daysToAdd  the days to add, positive or negative
 571      * @return a {@code Period} based on this period with the specified days added, not null
 572      * @throws ArithmeticException if numeric overflow occurs
 573      */
 574     public Period plusDays(long daysToAdd) {
 575         if (daysToAdd == 0) {
 576             return this;
 577         }
 578         return create(years, months, Math.toIntExact(Math.addExact(days, daysToAdd)));


 579     }
 580 
 581     //-----------------------------------------------------------------------
 582     /**
 583      * Returns a copy of this period with the specified period subtracted.
 584      * <p>
 585      * This operates separately on the years, months, days and the normalized time.
 586      * There is no further normalization beyond the normalized time.
 587      * <p>
 588      * For example, "1 year, 6 months and 3 days" minus "2 years, 2 months and 2 days"
 589      * returns "-1 years, 4 months and 1 day".
 590      * <p>
 591      * This instance is immutable and unaffected by this method call.
 592      *
 593      * @param amountToSubtract  the period to subtract, not null
 594      * @return a {@code Period} based on this period with the requested period subtracted, not null
 595      * @throws ArithmeticException if numeric overflow occurs
 596      */
 597     public Period minus(Period amountToSubtract) {
 598         return create(
 599                 Math.subtractExact(years, amountToSubtract.years),
 600                 Math.subtractExact(months, amountToSubtract.months),
 601                 Math.subtractExact(days, amountToSubtract.days));

 602     }
 603 
 604     /**
 605      * Returns a copy of this period with the specified years subtracted.
 606      * <p>
 607      * This subtracts the amount from the years unit in a copy of this period.
 608      * The months and days units are unaffected.
 609      * For example, "1 year, 6 months and 3 days" minus 2 years returns "-1 years, 6 months and 3 days".

 610      * <p>
 611      * This instance is immutable and unaffected by this method call.
 612      *
 613      * @param yearsToSubtract  the years to subtract, positive or negative
 614      * @return a {@code Period} based on this period with the specified years subtracted, not null

 615      * @throws ArithmeticException if numeric overflow occurs
 616      */
 617     public Period minusYears(long yearsToSubtract) {
 618         return (yearsToSubtract == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-yearsToSubtract));








 619     }
 620 
 621     /**
 622      * Returns a copy of this period with the specified months subtracted.
 623      * <p>
 624      * This subtracts the amount from the months unit in a copy of this period.
 625      * The years and days units are unaffected.
 626      * For example, "1 year, 6 months and 3 days" minus 2 months returns "1 year, 4 months and 3 days".
 627      * <p>
 628      * This instance is immutable and unaffected by this method call.
 629      *
 630      * @param monthsToSubtract  the years to subtract, positive or negative
 631      * @return a {@code Period} based on this period with the specified months subtracted, not null
 632      * @throws ArithmeticException if numeric overflow occurs
 633      */
 634     public Period minusMonths(long monthsToSubtract) {
 635         return (monthsToSubtract == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-monthsToSubtract));
 636     }
 637 
 638     /**
 639      * Returns a copy of this period with the specified days subtracted.
 640      * <p>
 641      * This subtracts the amount from the days unit in a copy of this period.
 642      * The years and months units are unaffected.
 643      * For example, "1 year, 6 months and 3 days" minus 2 days returns "1 year, 6 months and 1 day".
 644      * <p>
 645      * This instance is immutable and unaffected by this method call.
 646      *
 647      * @param daysToSubtract  the months to subtract, positive or negative
 648      * @return a {@code Period} based on this period with the specified days subtracted, not null
 649      * @throws ArithmeticException if numeric overflow occurs
 650      */
 651     public Period minusDays(long daysToSubtract) {
 652         return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));
 653     }
 654 
 655     //-----------------------------------------------------------------------
 656     /**
 657      * Returns a new instance with each element in this period multiplied
 658      * by the specified scalar.
 659      * <p>
 660      * This returns a period with each of the years, months and days units
 661      * individually multiplied.
 662      * For example, a period of "2 years, -3 months and 4 days" multiplied by
 663      * 3 will return "6 years, -9 months and 12 days".
 664      * No normalization is performed.
 665      *
 666      * @param scalar  the scalar to multiply by, not null
 667      * @return a {@code Period} based on this period with the amounts multiplied by the scalar, not null
 668      * @throws ArithmeticException if numeric overflow occurs
 669      */
 670     public Period multipliedBy(int scalar) {
 671         if (this == ZERO || scalar == 1) {
 672             return this;
 673         }
 674         return create(
 675                 Math.multiplyExact(years, scalar),
 676                 Math.multiplyExact(months, scalar),
 677                 Math.multiplyExact(days, scalar));

 678     }
 679 
 680     /**
 681      * Returns a new instance with each amount in this period negated.
 682      * <p>
 683      * This returns a period with each of the years, months and days units
 684      * individually negated.
 685      * For example, a period of "2 years, -3 months and 4 days" will be
 686      * negated to "-2 years, 3 months and -4 days".
 687      * No normalization is performed.
 688      *
 689      * @return a {@code Period} based on this period with the amounts negated, not null
 690      * @throws ArithmeticException if numeric overflow occurs, which only happens if
 691      *  one of the units has the value {@code Long.MIN_VALUE}
 692      */
 693     public Period negated() {
 694         return multipliedBy(-1);
 695     }
 696 
 697     //-----------------------------------------------------------------------
 698     /**
 699      * Returns a copy of this period with the years and months normalized
 700      * using a 12 month year.









 701      * <p>
 702      * This normalizes the years and months units, leaving the days unit unchanged.












































 703      * The months unit is adjusted to have an absolute value less than 11,
 704      * with the years unit being adjusted to compensate. For example, a period of
 705      * "1 Year and 15 months" will be normalized to "2 years and 3 months".
 706      * <p>
 707      * The sign of the years and months units will be the same after normalization.
 708      * For example, a period of "1 year and -25 months" will be normalized to
 709      * "-1 year and -1 month".
 710      * <p>
 711      * This normalization uses a 12 month year which is not valid for all calendar systems.
 712      * <p>
 713      * This instance is immutable and unaffected by this method call.
 714      *
 715      * @return a {@code Period} based on this period with excess months normalized to years, not null
 716      * @throws ArithmeticException if numeric overflow occurs
 717      */
 718     public Period normalized() {
 719         long totalMonths = toTotalMonths();
 720         long splitYears = totalMonths / 12;
 721         int splitMonths = (int) (totalMonths % 12);  // no overflow
 722         if (splitYears == years && splitMonths == months) {
 723             return this;
 724         }
 725         return create(Math.toIntExact(splitYears), splitMonths, days);
 726     }
 727 

 728     /**
 729      * Gets the total number of months in this period using a 12 month year.
 730      * <p>
 731      * This returns the total number of months in the period by multiplying the
 732      * number of years by 12 and adding the number of months.
 733      * <p>
 734      * This uses a 12 month year which is not valid for all calendar systems.


 735      * <p>
 736      * This instance is immutable and unaffected by this method call.
 737      *
 738      * @return the total number of months in the period, may be negative
 739      */
 740     public long toTotalMonths() {
 741         return years * 12L + months;  // no overflow



 742     }
 743 
 744     //-------------------------------------------------------------------------
 745     /**
 746      * Adds this period to the specified temporal object.
 747      * <p>
 748      * This returns a temporal object of the same observable type as the input
 749      * with this period added.
 750      * <p>
 751      * In most cases, it is clearer to reverse the calling pattern by using
 752      * {@link Temporal#plus(TemporalAmount)}.
 753      * <pre>
 754      *   // these two lines are equivalent, but the second approach is recommended
 755      *   dateTime = thisPeriod.addTo(dateTime);
 756      *   dateTime = dateTime.plus(thisPeriod);
 757      * </pre>
 758      * <p>
 759      * The calculation will add the years, then months, then days.
 760      * Only non-zero amounts will be added.
 761      * If the date-time has a calendar system with a fixed number of months in a
 762      * year, then the years and months will be combined before being added.
 763      * <p>
 764      * This instance is immutable and unaffected by this method call.
 765      *
 766      * @param temporal  the temporal object to adjust, not null
 767      * @return an object of the same type with the adjustment made, not null
 768      * @throws DateTimeException if unable to add
 769      * @throws ArithmeticException if numeric overflow occurs
 770      */
 771     @Override
 772     public Temporal addTo(Temporal temporal) {
 773         Objects.requireNonNull(temporal, "temporal");
 774         if ((years | months) != 0) {
 775             long monthRange = monthRange(temporal);
 776             if (monthRange >= 0) {
 777                 temporal = temporal.plus(years * monthRange + months, MONTHS);

 778             } else {
 779                 if (years != 0) {
 780                     temporal = temporal.plus(years, YEARS);
 781                 }
 782                 if (months != 0) {
 783                     temporal = temporal.plus(months, MONTHS);
 784                 }
 785             }
 786         }
 787         if (days != 0) {
 788             temporal = temporal.plus(days, DAYS);
 789         }



 790         return temporal;
 791     }
 792 
 793     /**
 794      * Subtracts this period from the specified temporal object.
 795      * <p>
 796      * This returns a temporal object of the same observable type as the input
 797      * with this period subtracted.
 798      * <p>
 799      * In most cases, it is clearer to reverse the calling pattern by using
 800      * {@link Temporal#minus(TemporalAmount)}.
 801      * <pre>
 802      *   // these two lines are equivalent, but the second approach is recommended
 803      *   dateTime = thisPeriod.subtractFrom(dateTime);
 804      *   dateTime = dateTime.minus(thisPeriod);
 805      * </pre>
 806      * <p>
 807      * The calculation will subtract the years, then months, then days.
 808      * Only non-zero amounts will be subtracted.
 809      * If the date-time has a calendar system with a fixed number of months in a
 810      * year, then the years and months will be combined before being subtracted.
 811      * <p>
 812      * This instance is immutable and unaffected by this method call.
 813      *
 814      * @param temporal  the temporal object to adjust, not null
 815      * @return an object of the same type with the adjustment made, not null
 816      * @throws DateTimeException if unable to subtract
 817      * @throws ArithmeticException if numeric overflow occurs
 818      */
 819     @Override
 820     public Temporal subtractFrom(Temporal temporal) {
 821         Objects.requireNonNull(temporal, "temporal");
 822         if ((years | months) != 0) {
 823             long monthRange = monthRange(temporal);
 824             if (monthRange >= 0) {
 825                 temporal = temporal.minus(years * monthRange + months, MONTHS);

 826             } else {
 827                 if (years != 0) {
 828                     temporal = temporal.minus(years, YEARS);
 829                 }
 830                 if (months != 0) {
 831                     temporal = temporal.minus(months, MONTHS);
 832                 }
 833             }
 834         }
 835         if (days != 0) {
 836             temporal = temporal.minus(days, DAYS);
 837         }



 838         return temporal;
 839     }
 840 

 841     /**
 842      * Calculates the range of months based on the temporal.






 843      *
 844      * @param temporal  the temporal, not null
 845      * @return the month range, negative if not fixed range
 846      */
 847     private long monthRange(Temporal temporal) {
 848         ValueRange startRange = Chronology.from(temporal).range(MONTH_OF_YEAR);
 849         if (startRange.isFixed() && startRange.isIntValue()) {
 850             return startRange.getMaximum() - startRange.getMinimum() + 1;


















 851         }
 852         return -1;
 853     }
 854 
 855     //-----------------------------------------------------------------------
 856     /**
 857      * Checks if this period is equal to another period.
 858      * <p>
 859      * The comparison is based on the amounts held in the period.
 860      * To be equal, the years, months and days units must be individually equal.
 861      * Note that this means that a period of "15 Months" is not equal to a period
 862      * of "1 Year and 3 Months".
 863      *
 864      * @param obj  the object to check, null returns false
 865      * @return true if this is equal to the other period
 866      */
 867     @Override
 868     public boolean equals(Object obj) {
 869         if (this == obj) {
 870             return true;
 871         }
 872         if (obj instanceof Period) {
 873             Period other = (Period) obj;
 874             return years == other.years &&
 875                     months == other.months &&
 876                     days == other.days;
 877         }
 878         return false;
 879     }
 880 
 881     /**
 882      * A hash code for this period.
 883      *
 884      * @return a suitable hash code
 885      */
 886     @Override
 887     public int hashCode() {
 888         return years + Integer.rotateLeft(months, 8) + Integer.rotateLeft(days, 16);




 889     }
 890 
 891     //-----------------------------------------------------------------------
 892     /**
 893      * Outputs this period as a {@code String}, such as {@code P6Y3M1D}.
 894      * <p>
 895      * The output will be in the ISO-8601 period format.
 896      * A zero period will be represented as zero days, 'P0D'.
 897      *
 898      * @return a string representation of this period, not null
 899      */
 900     @Override
 901     public String toString() {
 902         if (this == ZERO) {
 903             return "P0D";
 904         } else {
 905             StringBuilder buf = new StringBuilder();
 906             buf.append('P');
 907             if (years != 0) {
 908                 buf.append(years).append('Y');
 909             }
 910             if (months != 0) {
 911                 buf.append(months).append('M');
 912             }
 913             if (days != 0) {
 914                 buf.append(days).append('D');
 915             }
 916             return buf.toString();






















 917         }


 918     }
 919 
 920     //-----------------------------------------------------------------------
 921     /**
 922      * Writes the object using a
 923      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
 924      * <pre>
 925      *  out.writeByte(14);  // identifies this as a Period
 926      *  out.writeInt(years);
 927      *  out.writeInt(months);
 928      *  out.writeInt(seconds);
 929      * </pre>
 930      *
 931      * @return the instance of {@code Ser}, not null
 932      */
 933     private Object writeReplace() {
 934         return new Ser(Ser.PERIOD_TYPE, this);
 935     }
 936 
 937     /**
 938      * Defend against malicious streams.
 939      * @return never
 940      * @throws java.io.InvalidObjectException always
 941      */
 942     private Object readResolve() throws ObjectStreamException {
 943         throw new InvalidObjectException("Deserialization via serialization delegate");
 944     }
 945 
 946     void writeExternal(DataOutput out) throws IOException {
 947         out.writeInt(years);
 948         out.writeInt(months);
 949         out.writeInt(days);
 950     }
 951 
 952     static Period readExternal(DataInput in) throws IOException {
 953         int years = in.readInt();
 954         int months = in.readInt();
 955         int days = in.readInt();
 956         return Period.of(years, months, days);
 957     }
 958 
 959 }