src/share/classes/java/time/YearMonth.java

Print this page




  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.ERA;
  65 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
  66 import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
  67 import static java.time.temporal.ChronoField.YEAR;
  68 import static java.time.temporal.ChronoField.YEAR_OF_ERA;




  69 import static java.time.temporal.ChronoUnit.MONTHS;

  70 
  71 import java.io.DataInput;
  72 import java.io.DataOutput;
  73 import java.io.IOException;
  74 import java.io.InvalidObjectException;
  75 import java.io.ObjectStreamException;
  76 import java.io.Serializable;
  77 import java.time.chrono.Chronology;
  78 import java.time.chrono.IsoChronology;
  79 import java.time.format.DateTimeFormatter;
  80 import java.time.format.DateTimeFormatterBuilder;
  81 import java.time.format.DateTimeParseException;
  82 import java.time.format.SignStyle;
  83 import java.time.temporal.ChronoField;
  84 import java.time.temporal.ChronoUnit;
  85 import java.time.temporal.Temporal;
  86 import java.time.temporal.TemporalAccessor;
  87 import java.time.temporal.TemporalAdjuster;
  88 import java.time.temporal.TemporalAmount;
  89 import java.time.temporal.TemporalField;


 296     /**
 297      * Returns a copy of this year-month with the new year and month, checking
 298      * to see if a new object is in fact required.
 299      *
 300      * @param newYear  the year to represent, validated from MIN_YEAR to MAX_YEAR
 301      * @param newMonth  the month-of-year to represent, validated not null
 302      * @return the year-month, not null
 303      */
 304     private YearMonth with(int newYear, int newMonth) {
 305         if (year == newYear && month == newMonth) {
 306             return this;
 307         }
 308         return new YearMonth(newYear, newMonth);
 309     }
 310 
 311     //-----------------------------------------------------------------------
 312     /**
 313      * Checks if the specified field is supported.
 314      * <p>
 315      * This checks if this year-month can be queried for the specified field.
 316      * If false, then calling the {@link #range(TemporalField) range} and
 317      * {@link #get(TemporalField) get} methods will throw an exception.

 318      * <p>
 319      * If the field is a {@link ChronoField} then the query is implemented here.
 320      * The supported fields are:
 321      * <ul>
 322      * <li>{@code MONTH_OF_YEAR}
 323      * <li>{@code PROLEPTIC_MONTH}
 324      * <li>{@code YEAR_OF_ERA}
 325      * <li>{@code YEAR}
 326      * <li>{@code ERA}
 327      * </ul>
 328      * All other {@code ChronoField} instances will return false.
 329      * <p>
 330      * If the field is not a {@code ChronoField}, then the result of this method
 331      * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
 332      * passing {@code this} as the argument.
 333      * Whether the field is supported is determined by the field.
 334      *
 335      * @param field  the field to check, null returns false
 336      * @return true if the field is supported on this year-month, false if not
 337      */
 338     @Override
 339     public boolean isSupported(TemporalField field) {
 340         if (field instanceof ChronoField) {
 341             return field == YEAR || field == MONTH_OF_YEAR ||
 342                     field == PROLEPTIC_MONTH || field == YEAR_OF_ERA || field == ERA;
 343         }
 344         return field != null && field.isSupportedBy(this);
 345     }
 346 
 347     /**




































 348      * Gets the range of valid values for the specified field.
 349      * <p>
 350      * The range object expresses the minimum and maximum valid values for a field.
 351      * This year-month is used to enhance the accuracy of the returned range.
 352      * If it is not possible to return the range, because the field is not supported
 353      * or for some other reason, an exception is thrown.
 354      * <p>
 355      * If the field is a {@link ChronoField} then the query is implemented here.
 356      * The {@link #isSupported(TemporalField) supported fields} will return
 357      * appropriate range instances.
 358      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
 359      * <p>
 360      * If the field is not a {@code ChronoField}, then the result of this method
 361      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
 362      * passing {@code this} as the argument.
 363      * Whether the range can be obtained is determined by the field.
 364      *
 365      * @param field  the field to query the range for, not null
 366      * @return the range of valid values for the field, not null
 367      * @throws DateTimeException if the range for the field cannot be obtained


 423      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
 424      * passing {@code this} as the argument. Whether the value can be obtained,
 425      * and what the value represents, is determined by the field.
 426      *
 427      * @param field  the field to get, not null
 428      * @return the value for the field
 429      * @throws DateTimeException if a value for the field cannot be obtained
 430      * @throws UnsupportedTemporalTypeException if the field is not supported
 431      * @throws ArithmeticException if numeric overflow occurs
 432      */
 433     @Override
 434     public long getLong(TemporalField field) {
 435         if (field instanceof ChronoField) {
 436             switch ((ChronoField) field) {
 437                 case MONTH_OF_YEAR: return month;
 438                 case PROLEPTIC_MONTH: return getProlepticMonth();
 439                 case YEAR_OF_ERA: return (year < 1 ? 1 - year : year);
 440                 case YEAR: return year;
 441                 case ERA: return (year < 1 ? 0 : 1);
 442             }
 443             throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
 444         }
 445         return field.getFrom(this);
 446     }
 447 
 448     private long getProlepticMonth() {
 449         return (year * 12L + month - 1);
 450     }
 451 
 452     //-----------------------------------------------------------------------
 453     /**
 454      * Gets the year field.
 455      * <p>
 456      * This method returns the primitive {@code int} value for the year.
 457      * <p>
 458      * The year returned by this method is proleptic as per {@code get(YEAR)}.
 459      *
 460      * @return the year, from MIN_YEAR to MAX_YEAR
 461      */
 462     public int getYear() {
 463         return year;


 622      *
 623      * @param field  the field to set in the result, not null
 624      * @param newValue  the new value of the field in the result
 625      * @return a {@code YearMonth} based on {@code this} with the specified field set, not null
 626      * @throws DateTimeException if the field cannot be set
 627      * @throws UnsupportedTemporalTypeException if the field is not supported
 628      * @throws ArithmeticException if numeric overflow occurs
 629      */
 630     @Override
 631     public YearMonth with(TemporalField field, long newValue) {
 632         if (field instanceof ChronoField) {
 633             ChronoField f = (ChronoField) field;
 634             f.checkValidValue(newValue);
 635             switch (f) {
 636                 case MONTH_OF_YEAR: return withMonth((int) newValue);
 637                 case PROLEPTIC_MONTH: return plusMonths(newValue - getProlepticMonth());
 638                 case YEAR_OF_ERA: return withYear((int) (year < 1 ? 1 - newValue : newValue));
 639                 case YEAR: return withYear((int) newValue);
 640                 case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year));
 641             }
 642             throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
 643         }
 644         return field.adjustInto(this, newValue);
 645     }
 646 
 647     //-----------------------------------------------------------------------
 648     /**
 649      * Returns a copy of this {@code YearMonth} with the year altered.
 650      * <p>
 651      * This instance is immutable and unaffected by this method call.
 652      *
 653      * @param year  the year to set in the returned year-month, from MIN_YEAR to MAX_YEAR
 654      * @return a {@code YearMonth} based on this year-month with the requested year, not null
 655      * @throws DateTimeException if the year value is invalid
 656      */
 657     public YearMonth withYear(int year) {
 658         YEAR.checkValidValue(year);
 659         return with(year, month);
 660     }
 661 
 662     /**


 744      * This instance is immutable and unaffected by this method call.
 745      *
 746      * @param amountToAdd  the amount of the unit to add to the result, may be negative
 747      * @param unit  the unit of the amount to add, not null
 748      * @return a {@code YearMonth} based on this year-month with the specified amount added, not null
 749      * @throws DateTimeException if the addition cannot be made
 750      * @throws UnsupportedTemporalTypeException if the unit is not supported
 751      * @throws ArithmeticException if numeric overflow occurs
 752      */
 753     @Override
 754     public YearMonth plus(long amountToAdd, TemporalUnit unit) {
 755         if (unit instanceof ChronoUnit) {
 756             switch ((ChronoUnit) unit) {
 757                 case MONTHS: return plusMonths(amountToAdd);
 758                 case YEARS: return plusYears(amountToAdd);
 759                 case DECADES: return plusYears(Math.multiplyExact(amountToAdd, 10));
 760                 case CENTURIES: return plusYears(Math.multiplyExact(amountToAdd, 100));
 761                 case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000));
 762                 case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd));
 763             }
 764             throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
 765         }
 766         return unit.addTo(this, amountToAdd);
 767     }
 768 
 769     /**
 770      * Returns a copy of this year-month with the specified period in years added.
 771      * <p>
 772      * This instance is immutable and unaffected by this method call.
 773      *
 774      * @param yearsToAdd  the years to add, may be negative
 775      * @return a {@code YearMonth} based on this year-month with the years added, not null
 776      * @throws DateTimeException if the result exceeds the supported range
 777      */
 778     public YearMonth plusYears(long yearsToAdd) {
 779         if (yearsToAdd == 0) {
 780             return this;
 781         }
 782         int newYear = YEAR.checkValidIntValue(year + yearsToAdd);  // safe overflow
 783         return with(newYear, month);
 784     }


 935      * @throws DateTimeException if unable to make the adjustment
 936      * @throws ArithmeticException if numeric overflow occurs
 937      */
 938     @Override
 939     public Temporal adjustInto(Temporal temporal) {
 940         if (Chronology.from(temporal).equals(IsoChronology.INSTANCE) == false) {
 941             throw new DateTimeException("Adjustment only supported on ISO date-time");
 942         }
 943         return temporal.with(PROLEPTIC_MONTH, getProlepticMonth());
 944     }
 945 
 946     /**
 947      * Calculates the amount of time until another year-month in terms of the specified unit.
 948      * <p>
 949      * This calculates the amount of time between two {@code YearMonth}
 950      * objects in terms of a single {@code TemporalUnit}.
 951      * The start and end points are {@code this} and the specified year-month.
 952      * The result will be negative if the end is before the start.
 953      * The {@code Temporal} passed to this method must be a {@code YearMonth}.
 954      * For example, the period in years between two year-months can be calculated
 955      * using {@code startYearMonth.periodUntil(endYearMonth, YEARS)}.
 956      * <p>
 957      * The calculation returns a whole number, representing the number of
 958      * complete units between the two year-months.
 959      * For example, the period in decades between 2012-06 and 2032-05
 960      * will only be one decade as it is one month short of two decades.
 961      * <p>
 962      * There are two equivalent ways of using this method.
 963      * The first is to invoke this method.
 964      * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
 965      * <pre>
 966      *   // these two lines are equivalent
 967      *   amount = start.periodUntil(end, MONTHS);
 968      *   amount = MONTHS.between(start, end);
 969      * </pre>
 970      * The choice should be made based on which makes the code more readable.
 971      * <p>
 972      * The calculation is implemented in this method for {@link ChronoUnit}.
 973      * The units {@code MONTHS}, {@code YEARS}, {@code DECADES},
 974      * {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS} are supported.
 975      * Other {@code ChronoUnit} values will throw an exception.
 976      * <p>
 977      * If the unit is not a {@code ChronoUnit}, then the result of this method
 978      * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
 979      * passing {@code this} as the first argument and the input temporal as
 980      * the second argument.
 981      * <p>
 982      * This instance is immutable and unaffected by this method call.
 983      *
 984      * @param endYearMonth  the end year-month, which must be a {@code YearMonth}, not null
 985      * @param unit  the unit to measure the amount in, not null
 986      * @return the amount of time between this year-month and the end year-month
 987      * @throws DateTimeException if the amount cannot be calculated
 988      * @throws UnsupportedTemporalTypeException if the unit is not supported
 989      * @throws ArithmeticException if numeric overflow occurs
 990      */
 991     @Override
 992     public long periodUntil(Temporal endYearMonth, TemporalUnit unit) {
 993         if (endYearMonth instanceof YearMonth == false) {
 994             Objects.requireNonNull(endYearMonth, "endYearMonth");
 995             throw new DateTimeException("Unable to calculate amount as objects are of two different types");
 996         }
 997         YearMonth end = (YearMonth) endYearMonth;
 998         if (unit instanceof ChronoUnit) {
 999             long monthsUntil = end.getProlepticMonth() - getProlepticMonth();  // no overflow
1000             switch ((ChronoUnit) unit) {
1001                 case MONTHS: return monthsUntil;
1002                 case YEARS: return monthsUntil / 12;
1003                 case DECADES: return monthsUntil / 120;
1004                 case CENTURIES: return monthsUntil / 1200;
1005                 case MILLENNIA: return monthsUntil / 12000;
1006                 case ERAS: return end.getLong(ERA) - getLong(ERA);
1007             }
1008             throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
1009         }
1010         return unit.between(this, endYearMonth);
1011     }
1012 
1013     /**
1014      * Formats this year-month using the specified formatter.
1015      * <p>
1016      * This year-month will be passed to the formatter to produce a string.
1017      *
1018      * @param formatter  the formatter to use, not null
1019      * @return the formatted year-month string, not null
1020      * @throws DateTimeException if an error occurs during printing
1021      */
1022     public String format(DateTimeFormatter formatter) {
1023         Objects.requireNonNull(formatter, "formatter");
1024         return formatter.format(this);
1025     }
1026 
1027     //-----------------------------------------------------------------------
1028     /**




  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.ERA;
  65 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
  66 import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
  67 import static java.time.temporal.ChronoField.YEAR;
  68 import static java.time.temporal.ChronoField.YEAR_OF_ERA;
  69 import static java.time.temporal.ChronoUnit.CENTURIES;
  70 import static java.time.temporal.ChronoUnit.DECADES;
  71 import static java.time.temporal.ChronoUnit.ERAS;
  72 import static java.time.temporal.ChronoUnit.MILLENNIA;
  73 import static java.time.temporal.ChronoUnit.MONTHS;
  74 import static java.time.temporal.ChronoUnit.YEARS;
  75 
  76 import java.io.DataInput;
  77 import java.io.DataOutput;
  78 import java.io.IOException;
  79 import java.io.InvalidObjectException;
  80 import java.io.ObjectStreamException;
  81 import java.io.Serializable;
  82 import java.time.chrono.Chronology;
  83 import java.time.chrono.IsoChronology;
  84 import java.time.format.DateTimeFormatter;
  85 import java.time.format.DateTimeFormatterBuilder;
  86 import java.time.format.DateTimeParseException;
  87 import java.time.format.SignStyle;
  88 import java.time.temporal.ChronoField;
  89 import java.time.temporal.ChronoUnit;
  90 import java.time.temporal.Temporal;
  91 import java.time.temporal.TemporalAccessor;
  92 import java.time.temporal.TemporalAdjuster;
  93 import java.time.temporal.TemporalAmount;
  94 import java.time.temporal.TemporalField;


 301     /**
 302      * Returns a copy of this year-month with the new year and month, checking
 303      * to see if a new object is in fact required.
 304      *
 305      * @param newYear  the year to represent, validated from MIN_YEAR to MAX_YEAR
 306      * @param newMonth  the month-of-year to represent, validated not null
 307      * @return the year-month, not null
 308      */
 309     private YearMonth with(int newYear, int newMonth) {
 310         if (year == newYear && month == newMonth) {
 311             return this;
 312         }
 313         return new YearMonth(newYear, newMonth);
 314     }
 315 
 316     //-----------------------------------------------------------------------
 317     /**
 318      * Checks if the specified field is supported.
 319      * <p>
 320      * This checks if this year-month can be queried for the specified field.
 321      * If false, then calling the {@link #range(TemporalField) range},
 322      * {@link #get(TemporalField) get} and {@link #with(TemporalField, long)}
 323      * methods will throw an exception.
 324      * <p>
 325      * If the field is a {@link ChronoField} then the query is implemented here.
 326      * The supported fields are:
 327      * <ul>
 328      * <li>{@code MONTH_OF_YEAR}
 329      * <li>{@code PROLEPTIC_MONTH}
 330      * <li>{@code YEAR_OF_ERA}
 331      * <li>{@code YEAR}
 332      * <li>{@code ERA}
 333      * </ul>
 334      * All other {@code ChronoField} instances will return false.
 335      * <p>
 336      * If the field is not a {@code ChronoField}, then the result of this method
 337      * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
 338      * passing {@code this} as the argument.
 339      * Whether the field is supported is determined by the field.
 340      *
 341      * @param field  the field to check, null returns false
 342      * @return true if the field is supported on this year-month, false if not
 343      */
 344     @Override
 345     public boolean isSupported(TemporalField field) {
 346         if (field instanceof ChronoField) {
 347             return field == YEAR || field == MONTH_OF_YEAR ||
 348                     field == PROLEPTIC_MONTH || field == YEAR_OF_ERA || field == ERA;
 349         }
 350         return field != null && field.isSupportedBy(this);
 351     }
 352 
 353     /**
 354      * Checks if the specified unit is supported.
 355      * <p>
 356      * This checks if the specified unit can be added to, or subtracted from, this date-time.
 357      * If false, then calling the {@link #plus(long, TemporalUnit)} and
 358      * {@link #minus(long, TemporalUnit) minus} methods will throw an exception.
 359      * <p>
 360      * If the unit is a {@link ChronoUnit} then the query is implemented here.
 361      * The supported units are:
 362      * <ul>
 363      * <li>{@code MONTHS}
 364      * <li>{@code YEARS}
 365      * <li>{@code DECADES}
 366      * <li>{@code CENTURIES}
 367      * <li>{@code MILLENNIA}
 368      * <li>{@code ERAS}
 369      * </ul>
 370      * All other {@code ChronoUnit} instances will return false.
 371      * <p>
 372      * If the unit is not a {@code ChronoUnit}, then the result of this method
 373      * is obtained by invoking {@code TemporalUnit.isSupportedBy(Temporal)}
 374      * passing {@code this} as the argument.
 375      * Whether the unit is supported is determined by the unit.
 376      *
 377      * @param unit  the unit to check, null returns false
 378      * @return true if the unit can be added/subtracted, false if not
 379      */
 380     @Override
 381     public boolean isSupported(TemporalUnit unit) {
 382         if (unit instanceof ChronoUnit) {
 383             return unit == MONTHS || unit == YEARS || unit == DECADES || unit == CENTURIES || unit == MILLENNIA || unit == ERAS;
 384         }
 385         return unit != null && unit.isSupportedBy(this);
 386     }
 387 
 388     //-----------------------------------------------------------------------
 389     /**
 390      * Gets the range of valid values for the specified field.
 391      * <p>
 392      * The range object expresses the minimum and maximum valid values for a field.
 393      * This year-month is used to enhance the accuracy of the returned range.
 394      * If it is not possible to return the range, because the field is not supported
 395      * or for some other reason, an exception is thrown.
 396      * <p>
 397      * If the field is a {@link ChronoField} then the query is implemented here.
 398      * The {@link #isSupported(TemporalField) supported fields} will return
 399      * appropriate range instances.
 400      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
 401      * <p>
 402      * If the field is not a {@code ChronoField}, then the result of this method
 403      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
 404      * passing {@code this} as the argument.
 405      * Whether the range can be obtained is determined by the field.
 406      *
 407      * @param field  the field to query the range for, not null
 408      * @return the range of valid values for the field, not null
 409      * @throws DateTimeException if the range for the field cannot be obtained


 465      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
 466      * passing {@code this} as the argument. Whether the value can be obtained,
 467      * and what the value represents, is determined by the field.
 468      *
 469      * @param field  the field to get, not null
 470      * @return the value for the field
 471      * @throws DateTimeException if a value for the field cannot be obtained
 472      * @throws UnsupportedTemporalTypeException if the field is not supported
 473      * @throws ArithmeticException if numeric overflow occurs
 474      */
 475     @Override
 476     public long getLong(TemporalField field) {
 477         if (field instanceof ChronoField) {
 478             switch ((ChronoField) field) {
 479                 case MONTH_OF_YEAR: return month;
 480                 case PROLEPTIC_MONTH: return getProlepticMonth();
 481                 case YEAR_OF_ERA: return (year < 1 ? 1 - year : year);
 482                 case YEAR: return year;
 483                 case ERA: return (year < 1 ? 0 : 1);
 484             }
 485             throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
 486         }
 487         return field.getFrom(this);
 488     }
 489 
 490     private long getProlepticMonth() {
 491         return (year * 12L + month - 1);
 492     }
 493 
 494     //-----------------------------------------------------------------------
 495     /**
 496      * Gets the year field.
 497      * <p>
 498      * This method returns the primitive {@code int} value for the year.
 499      * <p>
 500      * The year returned by this method is proleptic as per {@code get(YEAR)}.
 501      *
 502      * @return the year, from MIN_YEAR to MAX_YEAR
 503      */
 504     public int getYear() {
 505         return year;


 664      *
 665      * @param field  the field to set in the result, not null
 666      * @param newValue  the new value of the field in the result
 667      * @return a {@code YearMonth} based on {@code this} with the specified field set, not null
 668      * @throws DateTimeException if the field cannot be set
 669      * @throws UnsupportedTemporalTypeException if the field is not supported
 670      * @throws ArithmeticException if numeric overflow occurs
 671      */
 672     @Override
 673     public YearMonth with(TemporalField field, long newValue) {
 674         if (field instanceof ChronoField) {
 675             ChronoField f = (ChronoField) field;
 676             f.checkValidValue(newValue);
 677             switch (f) {
 678                 case MONTH_OF_YEAR: return withMonth((int) newValue);
 679                 case PROLEPTIC_MONTH: return plusMonths(newValue - getProlepticMonth());
 680                 case YEAR_OF_ERA: return withYear((int) (year < 1 ? 1 - newValue : newValue));
 681                 case YEAR: return withYear((int) newValue);
 682                 case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year));
 683             }
 684             throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
 685         }
 686         return field.adjustInto(this, newValue);
 687     }
 688 
 689     //-----------------------------------------------------------------------
 690     /**
 691      * Returns a copy of this {@code YearMonth} with the year altered.
 692      * <p>
 693      * This instance is immutable and unaffected by this method call.
 694      *
 695      * @param year  the year to set in the returned year-month, from MIN_YEAR to MAX_YEAR
 696      * @return a {@code YearMonth} based on this year-month with the requested year, not null
 697      * @throws DateTimeException if the year value is invalid
 698      */
 699     public YearMonth withYear(int year) {
 700         YEAR.checkValidValue(year);
 701         return with(year, month);
 702     }
 703 
 704     /**


 786      * This instance is immutable and unaffected by this method call.
 787      *
 788      * @param amountToAdd  the amount of the unit to add to the result, may be negative
 789      * @param unit  the unit of the amount to add, not null
 790      * @return a {@code YearMonth} based on this year-month with the specified amount added, not null
 791      * @throws DateTimeException if the addition cannot be made
 792      * @throws UnsupportedTemporalTypeException if the unit is not supported
 793      * @throws ArithmeticException if numeric overflow occurs
 794      */
 795     @Override
 796     public YearMonth plus(long amountToAdd, TemporalUnit unit) {
 797         if (unit instanceof ChronoUnit) {
 798             switch ((ChronoUnit) unit) {
 799                 case MONTHS: return plusMonths(amountToAdd);
 800                 case YEARS: return plusYears(amountToAdd);
 801                 case DECADES: return plusYears(Math.multiplyExact(amountToAdd, 10));
 802                 case CENTURIES: return plusYears(Math.multiplyExact(amountToAdd, 100));
 803                 case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000));
 804                 case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd));
 805             }
 806             throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
 807         }
 808         return unit.addTo(this, amountToAdd);
 809     }
 810 
 811     /**
 812      * Returns a copy of this year-month with the specified period in years added.
 813      * <p>
 814      * This instance is immutable and unaffected by this method call.
 815      *
 816      * @param yearsToAdd  the years to add, may be negative
 817      * @return a {@code YearMonth} based on this year-month with the years added, not null
 818      * @throws DateTimeException if the result exceeds the supported range
 819      */
 820     public YearMonth plusYears(long yearsToAdd) {
 821         if (yearsToAdd == 0) {
 822             return this;
 823         }
 824         int newYear = YEAR.checkValidIntValue(year + yearsToAdd);  // safe overflow
 825         return with(newYear, month);
 826     }


 977      * @throws DateTimeException if unable to make the adjustment
 978      * @throws ArithmeticException if numeric overflow occurs
 979      */
 980     @Override
 981     public Temporal adjustInto(Temporal temporal) {
 982         if (Chronology.from(temporal).equals(IsoChronology.INSTANCE) == false) {
 983             throw new DateTimeException("Adjustment only supported on ISO date-time");
 984         }
 985         return temporal.with(PROLEPTIC_MONTH, getProlepticMonth());
 986     }
 987 
 988     /**
 989      * Calculates the amount of time until another year-month in terms of the specified unit.
 990      * <p>
 991      * This calculates the amount of time between two {@code YearMonth}
 992      * objects in terms of a single {@code TemporalUnit}.
 993      * The start and end points are {@code this} and the specified year-month.
 994      * The result will be negative if the end is before the start.
 995      * The {@code Temporal} passed to this method must be a {@code YearMonth}.
 996      * For example, the period in years between two year-months can be calculated
 997      * using {@code startYearMonth.until(endYearMonth, YEARS)}.
 998      * <p>
 999      * The calculation returns a whole number, representing the number of
1000      * complete units between the two year-months.
1001      * For example, the period in decades between 2012-06 and 2032-05
1002      * will only be one decade as it is one month short of two decades.
1003      * <p>
1004      * There are two equivalent ways of using this method.
1005      * The first is to invoke this method.
1006      * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
1007      * <pre>
1008      *   // these two lines are equivalent
1009      *   amount = start.until(end, MONTHS);
1010      *   amount = MONTHS.between(start, end);
1011      * </pre>
1012      * The choice should be made based on which makes the code more readable.
1013      * <p>
1014      * The calculation is implemented in this method for {@link ChronoUnit}.
1015      * The units {@code MONTHS}, {@code YEARS}, {@code DECADES},
1016      * {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS} are supported.
1017      * Other {@code ChronoUnit} values will throw an exception.
1018      * <p>
1019      * If the unit is not a {@code ChronoUnit}, then the result of this method
1020      * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
1021      * passing {@code this} as the first argument and the input temporal as
1022      * the second argument.
1023      * <p>
1024      * This instance is immutable and unaffected by this method call.
1025      *
1026      * @param endYearMonth  the end year-month, which must be a {@code YearMonth}, not null
1027      * @param unit  the unit to measure the amount in, not null
1028      * @return the amount of time between this year-month and the end year-month
1029      * @throws DateTimeException if the amount cannot be calculated
1030      * @throws UnsupportedTemporalTypeException if the unit is not supported
1031      * @throws ArithmeticException if numeric overflow occurs
1032      */
1033     @Override
1034     public long until(Temporal endYearMonth, TemporalUnit unit) {
1035         if (endYearMonth instanceof YearMonth == false) {
1036             Objects.requireNonNull(endYearMonth, "endYearMonth");
1037             throw new DateTimeException("Unable to calculate amount as objects are of two different types");
1038         }
1039         YearMonth end = (YearMonth) endYearMonth;
1040         if (unit instanceof ChronoUnit) {
1041             long monthsUntil = end.getProlepticMonth() - getProlepticMonth();  // no overflow
1042             switch ((ChronoUnit) unit) {
1043                 case MONTHS: return monthsUntil;
1044                 case YEARS: return monthsUntil / 12;
1045                 case DECADES: return monthsUntil / 120;
1046                 case CENTURIES: return monthsUntil / 1200;
1047                 case MILLENNIA: return monthsUntil / 12000;
1048                 case ERAS: return end.getLong(ERA) - getLong(ERA);
1049             }
1050             throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
1051         }
1052         return unit.between(this, endYearMonth);
1053     }
1054 
1055     /**
1056      * Formats this year-month using the specified formatter.
1057      * <p>
1058      * This year-month will be passed to the formatter to produce a string.
1059      *
1060      * @param formatter  the formatter to use, not null
1061      * @return the formatted year-month string, not null
1062      * @throws DateTimeException if an error occurs during printing
1063      */
1064     public String format(DateTimeFormatter formatter) {
1065         Objects.requireNonNull(formatter, "formatter");
1066         return formatter.format(this);
1067     }
1068 
1069     //-----------------------------------------------------------------------
1070     /**