Path: blob/master/src/java.base/share/classes/java/time/YearMonth.java
41152 views
/*1* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* This file is available under and governed by the GNU General Public27* License version 2 only, as published by the Free Software Foundation.28* However, the following notice accompanied the original version of this29* file:30*31* Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos32*33* All rights reserved.34*35* Redistribution and use in source and binary forms, with or without36* modification, are permitted provided that the following conditions are met:37*38* * Redistributions of source code must retain the above copyright notice,39* this list of conditions and the following disclaimer.40*41* * Redistributions in binary form must reproduce the above copyright notice,42* this list of conditions and the following disclaimer in the documentation43* and/or other materials provided with the distribution.44*45* * Neither the name of JSR-310 nor the names of its contributors46* may be used to endorse or promote products derived from this software47* without specific prior written permission.48*49* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS50* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT51* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR52* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR53* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,54* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,55* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR56* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF57* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING58* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS59* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.60*/61package java.time;6263import static java.time.temporal.ChronoField.ERA;64import static java.time.temporal.ChronoField.MONTH_OF_YEAR;65import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;66import static java.time.temporal.ChronoField.YEAR;67import static java.time.temporal.ChronoField.YEAR_OF_ERA;68import static java.time.temporal.ChronoUnit.CENTURIES;69import static java.time.temporal.ChronoUnit.DECADES;70import static java.time.temporal.ChronoUnit.ERAS;71import static java.time.temporal.ChronoUnit.MILLENNIA;72import static java.time.temporal.ChronoUnit.MONTHS;73import static java.time.temporal.ChronoUnit.YEARS;7475import java.io.DataInput;76import java.io.DataOutput;77import java.io.IOException;78import java.io.InvalidObjectException;79import java.io.ObjectInputStream;80import java.io.Serializable;81import java.time.chrono.Chronology;82import java.time.chrono.IsoChronology;83import java.time.format.DateTimeFormatter;84import java.time.format.DateTimeFormatterBuilder;85import java.time.format.DateTimeParseException;86import java.time.format.SignStyle;87import java.time.temporal.ChronoField;88import java.time.temporal.ChronoUnit;89import java.time.temporal.Temporal;90import java.time.temporal.TemporalAccessor;91import java.time.temporal.TemporalAdjuster;92import java.time.temporal.TemporalAmount;93import java.time.temporal.TemporalField;94import java.time.temporal.TemporalQueries;95import java.time.temporal.TemporalQuery;96import java.time.temporal.TemporalUnit;97import java.time.temporal.UnsupportedTemporalTypeException;98import java.time.temporal.ValueRange;99import java.util.Objects;100101/**102* A year-month in the ISO-8601 calendar system, such as {@code 2007-12}.103* <p>104* {@code YearMonth} is an immutable date-time object that represents the combination105* of a year and month. Any field that can be derived from a year and month, such as106* quarter-of-year, can be obtained.107* <p>108* This class does not store or represent a day, time or time-zone.109* For example, the value "October 2007" can be stored in a {@code YearMonth}.110* <p>111* The ISO-8601 calendar system is the modern civil calendar system used today112* in most of the world. It is equivalent to the proleptic Gregorian calendar113* system, in which today's rules for leap years are applied for all time.114* For most applications written today, the ISO-8601 rules are entirely suitable.115* However, any application that makes use of historical dates, and requires them116* to be accurate will find the ISO-8601 approach unsuitable.117* <p>118* This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>119* class; programmers should treat instances that are120* {@linkplain #equals(Object) equal} as interchangeable and should not121* use instances for synchronization, or unpredictable behavior may122* occur. For example, in a future release, synchronization may fail.123* The {@code equals} method should be used for comparisons.124*125* @implSpec126* This class is immutable and thread-safe.127*128* @since 1.8129*/130@jdk.internal.ValueBased131public final class YearMonth132implements Temporal, TemporalAdjuster, Comparable<YearMonth>, Serializable {133134/**135* Serialization version.136*/137@java.io.Serial138private static final long serialVersionUID = 4183400860270640070L;139/**140* Parser.141*/142private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder()143.appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)144.appendLiteral('-')145.appendValue(MONTH_OF_YEAR, 2)146.toFormatter();147148/**149* The year.150*/151private final int year;152/**153* The month-of-year, not null.154*/155private final int month;156157//-----------------------------------------------------------------------158/**159* Obtains the current year-month from the system clock in the default time-zone.160* <p>161* This will query the {@link Clock#systemDefaultZone() system clock} in the default162* time-zone to obtain the current year-month.163* <p>164* Using this method will prevent the ability to use an alternate clock for testing165* because the clock is hard-coded.166*167* @return the current year-month using the system clock and default time-zone, not null168*/169public static YearMonth now() {170return now(Clock.systemDefaultZone());171}172173/**174* Obtains the current year-month from the system clock in the specified time-zone.175* <p>176* This will query the {@link Clock#system(ZoneId) system clock} to obtain the current year-month.177* Specifying the time-zone avoids dependence on the default time-zone.178* <p>179* Using this method will prevent the ability to use an alternate clock for testing180* because the clock is hard-coded.181*182* @param zone the zone ID to use, not null183* @return the current year-month using the system clock, not null184*/185public static YearMonth now(ZoneId zone) {186return now(Clock.system(zone));187}188189/**190* Obtains the current year-month from the specified clock.191* <p>192* This will query the specified clock to obtain the current year-month.193* Using this method allows the use of an alternate clock for testing.194* The alternate clock may be introduced using {@link Clock dependency injection}.195*196* @param clock the clock to use, not null197* @return the current year-month, not null198*/199public static YearMonth now(Clock clock) {200final LocalDate now = LocalDate.now(clock); // called once201return YearMonth.of(now.getYear(), now.getMonth());202}203204//-----------------------------------------------------------------------205/**206* Obtains an instance of {@code YearMonth} from a year and month.207*208* @param year the year to represent, from MIN_YEAR to MAX_YEAR209* @param month the month-of-year to represent, not null210* @return the year-month, not null211* @throws DateTimeException if the year value is invalid212*/213public static YearMonth of(int year, Month month) {214Objects.requireNonNull(month, "month");215return of(year, month.getValue());216}217218/**219* Obtains an instance of {@code YearMonth} from a year and month.220*221* @param year the year to represent, from MIN_YEAR to MAX_YEAR222* @param month the month-of-year to represent, from 1 (January) to 12 (December)223* @return the year-month, not null224* @throws DateTimeException if either field value is invalid225*/226public static YearMonth of(int year, int month) {227YEAR.checkValidValue(year);228MONTH_OF_YEAR.checkValidValue(month);229return new YearMonth(year, month);230}231232//-----------------------------------------------------------------------233/**234* Obtains an instance of {@code YearMonth} from a temporal object.235* <p>236* This obtains a year-month based on the specified temporal.237* A {@code TemporalAccessor} represents an arbitrary set of date and time information,238* which this factory converts to an instance of {@code YearMonth}.239* <p>240* The conversion extracts the {@link ChronoField#YEAR YEAR} and241* {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} fields.242* The extraction is only permitted if the temporal object has an ISO243* chronology, or can be converted to a {@code LocalDate}.244* <p>245* This method matches the signature of the functional interface {@link TemporalQuery}246* allowing it to be used as a query via method reference, {@code YearMonth::from}.247*248* @param temporal the temporal object to convert, not null249* @return the year-month, not null250* @throws DateTimeException if unable to convert to a {@code YearMonth}251*/252public static YearMonth from(TemporalAccessor temporal) {253if (temporal instanceof YearMonth) {254return (YearMonth) temporal;255}256Objects.requireNonNull(temporal, "temporal");257try {258if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) {259temporal = LocalDate.from(temporal);260}261return of(temporal.get(YEAR), temporal.get(MONTH_OF_YEAR));262} catch (DateTimeException ex) {263throw new DateTimeException("Unable to obtain YearMonth from TemporalAccessor: " +264temporal + " of type " + temporal.getClass().getName(), ex);265}266}267268//-----------------------------------------------------------------------269/**270* Obtains an instance of {@code YearMonth} from a text string such as {@code 2007-12}.271* <p>272* The string must represent a valid year-month.273* The format must be {@code uuuu-MM}.274* Years outside the range 0000 to 9999 must be prefixed by the plus or minus symbol.275*276* @param text the text to parse such as "2007-12", not null277* @return the parsed year-month, not null278* @throws DateTimeParseException if the text cannot be parsed279*/280public static YearMonth parse(CharSequence text) {281return parse(text, PARSER);282}283284/**285* Obtains an instance of {@code YearMonth} from a text string using a specific formatter.286* <p>287* The text is parsed using the formatter, returning a year-month.288*289* @param text the text to parse, not null290* @param formatter the formatter to use, not null291* @return the parsed year-month, not null292* @throws DateTimeParseException if the text cannot be parsed293*/294public static YearMonth parse(CharSequence text, DateTimeFormatter formatter) {295Objects.requireNonNull(formatter, "formatter");296return formatter.parse(text, YearMonth::from);297}298299//-----------------------------------------------------------------------300/**301* Constructor.302*303* @param year the year to represent, validated from MIN_YEAR to MAX_YEAR304* @param month the month-of-year to represent, validated from 1 (January) to 12 (December)305*/306private YearMonth(int year, int month) {307this.year = year;308this.month = month;309}310311/**312* Returns a copy of this year-month with the new year and month, checking313* to see if a new object is in fact required.314*315* @param newYear the year to represent, validated from MIN_YEAR to MAX_YEAR316* @param newMonth the month-of-year to represent, validated not null317* @return the year-month, not null318*/319private YearMonth with(int newYear, int newMonth) {320if (year == newYear && month == newMonth) {321return this;322}323return new YearMonth(newYear, newMonth);324}325326//-----------------------------------------------------------------------327/**328* Checks if the specified field is supported.329* <p>330* This checks if this year-month can be queried for the specified field.331* If false, then calling the {@link #range(TemporalField) range},332* {@link #get(TemporalField) get} and {@link #with(TemporalField, long)}333* methods will throw an exception.334* <p>335* If the field is a {@link ChronoField} then the query is implemented here.336* The supported fields are:337* <ul>338* <li>{@code MONTH_OF_YEAR}339* <li>{@code PROLEPTIC_MONTH}340* <li>{@code YEAR_OF_ERA}341* <li>{@code YEAR}342* <li>{@code ERA}343* </ul>344* All other {@code ChronoField} instances will return false.345* <p>346* If the field is not a {@code ChronoField}, then the result of this method347* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}348* passing {@code this} as the argument.349* Whether the field is supported is determined by the field.350*351* @param field the field to check, null returns false352* @return true if the field is supported on this year-month, false if not353*/354@Override355public boolean isSupported(TemporalField field) {356if (field instanceof ChronoField) {357return field == YEAR || field == MONTH_OF_YEAR ||358field == PROLEPTIC_MONTH || field == YEAR_OF_ERA || field == ERA;359}360return field != null && field.isSupportedBy(this);361}362363/**364* Checks if the specified unit is supported.365* <p>366* This checks if the specified unit can be added to, or subtracted from, this year-month.367* If false, then calling the {@link #plus(long, TemporalUnit)} and368* {@link #minus(long, TemporalUnit) minus} methods will throw an exception.369* <p>370* If the unit is a {@link ChronoUnit} then the query is implemented here.371* The supported units are:372* <ul>373* <li>{@code MONTHS}374* <li>{@code YEARS}375* <li>{@code DECADES}376* <li>{@code CENTURIES}377* <li>{@code MILLENNIA}378* <li>{@code ERAS}379* </ul>380* All other {@code ChronoUnit} instances will return false.381* <p>382* If the unit is not a {@code ChronoUnit}, then the result of this method383* is obtained by invoking {@code TemporalUnit.isSupportedBy(Temporal)}384* passing {@code this} as the argument.385* Whether the unit is supported is determined by the unit.386*387* @param unit the unit to check, null returns false388* @return true if the unit can be added/subtracted, false if not389*/390@Override391public boolean isSupported(TemporalUnit unit) {392if (unit instanceof ChronoUnit) {393return unit == MONTHS || unit == YEARS || unit == DECADES || unit == CENTURIES || unit == MILLENNIA || unit == ERAS;394}395return unit != null && unit.isSupportedBy(this);396}397398//-----------------------------------------------------------------------399/**400* Gets the range of valid values for the specified field.401* <p>402* The range object expresses the minimum and maximum valid values for a field.403* This year-month is used to enhance the accuracy of the returned range.404* If it is not possible to return the range, because the field is not supported405* or for some other reason, an exception is thrown.406* <p>407* If the field is a {@link ChronoField} then the query is implemented here.408* The {@link #isSupported(TemporalField) supported fields} will return409* appropriate range instances.410* All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.411* <p>412* If the field is not a {@code ChronoField}, then the result of this method413* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}414* passing {@code this} as the argument.415* Whether the range can be obtained is determined by the field.416*417* @param field the field to query the range for, not null418* @return the range of valid values for the field, not null419* @throws DateTimeException if the range for the field cannot be obtained420* @throws UnsupportedTemporalTypeException if the field is not supported421*/422@Override423public ValueRange range(TemporalField field) {424if (field == YEAR_OF_ERA) {425return (getYear() <= 0 ? ValueRange.of(1, Year.MAX_VALUE + 1) : ValueRange.of(1, Year.MAX_VALUE));426}427return Temporal.super.range(field);428}429430/**431* Gets the value of the specified field from this year-month as an {@code int}.432* <p>433* This queries this year-month for the value of the specified field.434* The returned value will always be within the valid range of values for the field.435* If it is not possible to return the value, because the field is not supported436* or for some other reason, an exception is thrown.437* <p>438* If the field is a {@link ChronoField} then the query is implemented here.439* The {@link #isSupported(TemporalField) supported fields} will return valid440* values based on this year-month, except {@code PROLEPTIC_MONTH} which is too441* large to fit in an {@code int} and throw a {@code DateTimeException}.442* All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.443* <p>444* If the field is not a {@code ChronoField}, then the result of this method445* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}446* passing {@code this} as the argument. Whether the value can be obtained,447* and what the value represents, is determined by the field.448*449* @param field the field to get, not null450* @return the value for the field451* @throws DateTimeException if a value for the field cannot be obtained or452* the value is outside the range of valid values for the field453* @throws UnsupportedTemporalTypeException if the field is not supported or454* the range of values exceeds an {@code int}455* @throws ArithmeticException if numeric overflow occurs456*/457@Override // override for Javadoc458public int get(TemporalField field) {459return range(field).checkValidIntValue(getLong(field), field);460}461462/**463* Gets the value of the specified field from this year-month as a {@code long}.464* <p>465* This queries this year-month for the value of the specified field.466* If it is not possible to return the value, because the field is not supported467* or for some other reason, an exception is thrown.468* <p>469* If the field is a {@link ChronoField} then the query is implemented here.470* The {@link #isSupported(TemporalField) supported fields} will return valid471* values based on this year-month.472* All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.473* <p>474* If the field is not a {@code ChronoField}, then the result of this method475* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}476* passing {@code this} as the argument. Whether the value can be obtained,477* and what the value represents, is determined by the field.478*479* @param field the field to get, not null480* @return the value for the field481* @throws DateTimeException if a value for the field cannot be obtained482* @throws UnsupportedTemporalTypeException if the field is not supported483* @throws ArithmeticException if numeric overflow occurs484*/485@Override486public long getLong(TemporalField field) {487if (field instanceof ChronoField chronoField) {488switch (chronoField) {489case MONTH_OF_YEAR: return month;490case PROLEPTIC_MONTH: return getProlepticMonth();491case YEAR_OF_ERA: return (year < 1 ? 1 - year : year);492case YEAR: return year;493case ERA: return (year < 1 ? 0 : 1);494}495throw new UnsupportedTemporalTypeException("Unsupported field: " + field);496}497return field.getFrom(this);498}499500private long getProlepticMonth() {501return (year * 12L + month - 1);502}503504//-----------------------------------------------------------------------505/**506* Gets the year field.507* <p>508* This method returns the primitive {@code int} value for the year.509* <p>510* The year returned by this method is proleptic as per {@code get(YEAR)}.511*512* @return the year, from MIN_YEAR to MAX_YEAR513*/514public int getYear() {515return year;516}517518/**519* Gets the month-of-year field from 1 to 12.520* <p>521* This method returns the month as an {@code int} from 1 to 12.522* Application code is frequently clearer if the enum {@link Month}523* is used by calling {@link #getMonth()}.524*525* @return the month-of-year, from 1 to 12526* @see #getMonth()527*/528public int getMonthValue() {529return month;530}531532/**533* Gets the month-of-year field using the {@code Month} enum.534* <p>535* This method returns the enum {@link Month} for the month.536* This avoids confusion as to what {@code int} values mean.537* If you need access to the primitive {@code int} value then the enum538* provides the {@link Month#getValue() int value}.539*540* @return the month-of-year, not null541* @see #getMonthValue()542*/543public Month getMonth() {544return Month.of(month);545}546547//-----------------------------------------------------------------------548/**549* Checks if the year is a leap year, according to the ISO proleptic550* calendar system rules.551* <p>552* This method applies the current rules for leap years across the whole time-line.553* In general, a year is a leap year if it is divisible by four without554* remainder. However, years divisible by 100, are not leap years, with555* the exception of years divisible by 400 which are.556* <p>557* For example, 1904 is a leap year it is divisible by 4.558* 1900 was not a leap year as it is divisible by 100, however 2000 was a559* leap year as it is divisible by 400.560* <p>561* The calculation is proleptic - applying the same rules into the far future and far past.562* This is historically inaccurate, but is correct for the ISO-8601 standard.563*564* @return true if the year is leap, false otherwise565*/566public boolean isLeapYear() {567return IsoChronology.INSTANCE.isLeapYear(year);568}569570/**571* Checks if the day-of-month is valid for this year-month.572* <p>573* This method checks whether this year and month and the input day form574* a valid date.575*576* @param dayOfMonth the day-of-month to validate, from 1 to 31, invalid value returns false577* @return true if the day is valid for this year-month578*/579public boolean isValidDay(int dayOfMonth) {580return dayOfMonth >= 1 && dayOfMonth <= lengthOfMonth();581}582583/**584* Returns the length of the month, taking account of the year.585* <p>586* This returns the length of the month in days.587* For example, a date in January would return 31.588*589* @return the length of the month in days, from 28 to 31590*/591public int lengthOfMonth() {592return getMonth().length(isLeapYear());593}594595/**596* Returns the length of the year.597* <p>598* This returns the length of the year in days, either 365 or 366.599*600* @return 366 if the year is leap, 365 otherwise601*/602public int lengthOfYear() {603return (isLeapYear() ? 366 : 365);604}605606//-----------------------------------------------------------------------607/**608* Returns an adjusted copy of this year-month.609* <p>610* This returns a {@code YearMonth}, based on this one, with the year-month adjusted.611* The adjustment takes place using the specified adjuster strategy object.612* Read the documentation of the adjuster to understand what adjustment will be made.613* <p>614* A simple adjuster might simply set the one of the fields, such as the year field.615* A more complex adjuster might set the year-month to the next month that616* Halley's comet will pass the Earth.617* <p>618* The result of this method is obtained by invoking the619* {@link TemporalAdjuster#adjustInto(Temporal)} method on the620* specified adjuster passing {@code this} as the argument.621* <p>622* This instance is immutable and unaffected by this method call.623*624* @param adjuster the adjuster to use, not null625* @return a {@code YearMonth} based on {@code this} with the adjustment made, not null626* @throws DateTimeException if the adjustment cannot be made627* @throws ArithmeticException if numeric overflow occurs628*/629@Override630public YearMonth with(TemporalAdjuster adjuster) {631return (YearMonth) adjuster.adjustInto(this);632}633634/**635* Returns a copy of this year-month with the specified field set to a new value.636* <p>637* This returns a {@code YearMonth}, based on this one, with the value638* for the specified field changed.639* This can be used to change any supported field, such as the year or month.640* If it is not possible to set the value, because the field is not supported or for641* some other reason, an exception is thrown.642* <p>643* If the field is a {@link ChronoField} then the adjustment is implemented here.644* The supported fields behave as follows:645* <ul>646* <li>{@code MONTH_OF_YEAR} -647* Returns a {@code YearMonth} with the specified month-of-year.648* The year will be unchanged.649* <li>{@code PROLEPTIC_MONTH} -650* Returns a {@code YearMonth} with the specified proleptic-month.651* This completely replaces the year and month of this object.652* <li>{@code YEAR_OF_ERA} -653* Returns a {@code YearMonth} with the specified year-of-era654* The month and era will be unchanged.655* <li>{@code YEAR} -656* Returns a {@code YearMonth} with the specified year.657* The month will be unchanged.658* <li>{@code ERA} -659* Returns a {@code YearMonth} with the specified era.660* The month and year-of-era will be unchanged.661* </ul>662* <p>663* In all cases, if the new value is outside the valid range of values for the field664* then a {@code DateTimeException} will be thrown.665* <p>666* All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.667* <p>668* If the field is not a {@code ChronoField}, then the result of this method669* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}670* passing {@code this} as the argument. In this case, the field determines671* whether and how to adjust the instant.672* <p>673* This instance is immutable and unaffected by this method call.674*675* @param field the field to set in the result, not null676* @param newValue the new value of the field in the result677* @return a {@code YearMonth} based on {@code this} with the specified field set, not null678* @throws DateTimeException if the field cannot be set679* @throws UnsupportedTemporalTypeException if the field is not supported680* @throws ArithmeticException if numeric overflow occurs681*/682@Override683public YearMonth with(TemporalField field, long newValue) {684if (field instanceof ChronoField chronoField) {685chronoField.checkValidValue(newValue);686switch (chronoField) {687case MONTH_OF_YEAR: return withMonth((int) newValue);688case PROLEPTIC_MONTH: return plusMonths(newValue - getProlepticMonth());689case YEAR_OF_ERA: return withYear((int) (year < 1 ? 1 - newValue : newValue));690case YEAR: return withYear((int) newValue);691case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year));692}693throw new UnsupportedTemporalTypeException("Unsupported field: " + field);694}695return field.adjustInto(this, newValue);696}697698//-----------------------------------------------------------------------699/**700* Returns a copy of this {@code YearMonth} with the year altered.701* <p>702* This instance is immutable and unaffected by this method call.703*704* @param year the year to set in the returned year-month, from MIN_YEAR to MAX_YEAR705* @return a {@code YearMonth} based on this year-month with the requested year, not null706* @throws DateTimeException if the year value is invalid707*/708public YearMonth withYear(int year) {709YEAR.checkValidValue(year);710return with(year, month);711}712713/**714* Returns a copy of this {@code YearMonth} with the month-of-year altered.715* <p>716* This instance is immutable and unaffected by this method call.717*718* @param month the month-of-year to set in the returned year-month, from 1 (January) to 12 (December)719* @return a {@code YearMonth} based on this year-month with the requested month, not null720* @throws DateTimeException if the month-of-year value is invalid721*/722public YearMonth withMonth(int month) {723MONTH_OF_YEAR.checkValidValue(month);724return with(year, month);725}726727//-----------------------------------------------------------------------728/**729* Returns a copy of this year-month with the specified amount added.730* <p>731* This returns a {@code YearMonth}, based on this one, with the specified amount added.732* The amount is typically {@link Period} but may be any other type implementing733* the {@link TemporalAmount} interface.734* <p>735* The calculation is delegated to the amount object by calling736* {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free737* to implement the addition in any way it wishes, however it typically738* calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation739* of the amount implementation to determine if it can be successfully added.740* <p>741* This instance is immutable and unaffected by this method call.742*743* @param amountToAdd the amount to add, not null744* @return a {@code YearMonth} based on this year-month with the addition made, not null745* @throws DateTimeException if the addition cannot be made746* @throws ArithmeticException if numeric overflow occurs747*/748@Override749public YearMonth plus(TemporalAmount amountToAdd) {750return (YearMonth) amountToAdd.addTo(this);751}752753/**754* Returns a copy of this year-month with the specified amount added.755* <p>756* This returns a {@code YearMonth}, based on this one, with the amount757* in terms of the unit added. If it is not possible to add the amount, because the758* unit is not supported or for some other reason, an exception is thrown.759* <p>760* If the field is a {@link ChronoUnit} then the addition is implemented here.761* The supported fields behave as follows:762* <ul>763* <li>{@code MONTHS} -764* Returns a {@code YearMonth} with the specified number of months added.765* This is equivalent to {@link #plusMonths(long)}.766* <li>{@code YEARS} -767* Returns a {@code YearMonth} with the specified number of years added.768* This is equivalent to {@link #plusYears(long)}.769* <li>{@code DECADES} -770* Returns a {@code YearMonth} with the specified number of decades added.771* This is equivalent to calling {@link #plusYears(long)} with the amount772* multiplied by 10.773* <li>{@code CENTURIES} -774* Returns a {@code YearMonth} with the specified number of centuries added.775* This is equivalent to calling {@link #plusYears(long)} with the amount776* multiplied by 100.777* <li>{@code MILLENNIA} -778* Returns a {@code YearMonth} with the specified number of millennia added.779* This is equivalent to calling {@link #plusYears(long)} with the amount780* multiplied by 1,000.781* <li>{@code ERAS} -782* Returns a {@code YearMonth} with the specified number of eras added.783* Only two eras are supported so the amount must be one, zero or minus one.784* If the amount is non-zero then the year is changed such that the year-of-era785* is unchanged.786* </ul>787* <p>788* All other {@code ChronoUnit} instances will throw an {@code UnsupportedTemporalTypeException}.789* <p>790* If the field is not a {@code ChronoUnit}, then the result of this method791* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}792* passing {@code this} as the argument. In this case, the unit determines793* whether and how to perform the addition.794* <p>795* This instance is immutable and unaffected by this method call.796*797* @param amountToAdd the amount of the unit to add to the result, may be negative798* @param unit the unit of the amount to add, not null799* @return a {@code YearMonth} based on this year-month with the specified amount added, not null800* @throws DateTimeException if the addition cannot be made801* @throws UnsupportedTemporalTypeException if the unit is not supported802* @throws ArithmeticException if numeric overflow occurs803*/804@Override805public YearMonth plus(long amountToAdd, TemporalUnit unit) {806if (unit instanceof ChronoUnit chronoUnit) {807switch (chronoUnit) {808case MONTHS: return plusMonths(amountToAdd);809case YEARS: return plusYears(amountToAdd);810case DECADES: return plusYears(Math.multiplyExact(amountToAdd, 10));811case CENTURIES: return plusYears(Math.multiplyExact(amountToAdd, 100));812case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000));813case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd));814}815throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);816}817return unit.addTo(this, amountToAdd);818}819820/**821* Returns a copy of this {@code YearMonth} with the specified number of years added.822* <p>823* This instance is immutable and unaffected by this method call.824*825* @param yearsToAdd the years to add, may be negative826* @return a {@code YearMonth} based on this year-month with the years added, not null827* @throws DateTimeException if the result exceeds the supported range828*/829public YearMonth plusYears(long yearsToAdd) {830if (yearsToAdd == 0) {831return this;832}833int newYear = YEAR.checkValidIntValue(year + yearsToAdd); // safe overflow834return with(newYear, month);835}836837/**838* Returns a copy of this {@code YearMonth} with the specified number of months added.839* <p>840* This instance is immutable and unaffected by this method call.841*842* @param monthsToAdd the months to add, may be negative843* @return a {@code YearMonth} based on this year-month with the months added, not null844* @throws DateTimeException if the result exceeds the supported range845*/846public YearMonth plusMonths(long monthsToAdd) {847if (monthsToAdd == 0) {848return this;849}850long monthCount = year * 12L + (month - 1);851long calcMonths = monthCount + monthsToAdd; // safe overflow852int newYear = YEAR.checkValidIntValue(Math.floorDiv(calcMonths, 12));853int newMonth = Math.floorMod(calcMonths, 12) + 1;854return with(newYear, newMonth);855}856857//-----------------------------------------------------------------------858/**859* Returns a copy of this year-month with the specified amount subtracted.860* <p>861* This returns a {@code YearMonth}, based on this one, with the specified amount subtracted.862* The amount is typically {@link Period} but may be any other type implementing863* the {@link TemporalAmount} interface.864* <p>865* The calculation is delegated to the amount object by calling866* {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free867* to implement the subtraction in any way it wishes, however it typically868* calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation869* of the amount implementation to determine if it can be successfully subtracted.870* <p>871* This instance is immutable and unaffected by this method call.872*873* @param amountToSubtract the amount to subtract, not null874* @return a {@code YearMonth} based on this year-month with the subtraction made, not null875* @throws DateTimeException if the subtraction cannot be made876* @throws ArithmeticException if numeric overflow occurs877*/878@Override879public YearMonth minus(TemporalAmount amountToSubtract) {880return (YearMonth) amountToSubtract.subtractFrom(this);881}882883/**884* Returns a copy of this year-month with the specified amount subtracted.885* <p>886* This returns a {@code YearMonth}, based on this one, with the amount887* in terms of the unit subtracted. If it is not possible to subtract the amount,888* because the unit is not supported or for some other reason, an exception is thrown.889* <p>890* This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.891* See that method for a full description of how addition, and thus subtraction, works.892* <p>893* This instance is immutable and unaffected by this method call.894*895* @param amountToSubtract the amount of the unit to subtract from the result, may be negative896* @param unit the unit of the amount to subtract, not null897* @return a {@code YearMonth} based on this year-month with the specified amount subtracted, not null898* @throws DateTimeException if the subtraction cannot be made899* @throws UnsupportedTemporalTypeException if the unit is not supported900* @throws ArithmeticException if numeric overflow occurs901*/902@Override903public YearMonth minus(long amountToSubtract, TemporalUnit unit) {904return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));905}906907/**908* Returns a copy of this {@code YearMonth} with the specified number of years subtracted.909* <p>910* This instance is immutable and unaffected by this method call.911*912* @param yearsToSubtract the years to subtract, may be negative913* @return a {@code YearMonth} based on this year-month with the years subtracted, not null914* @throws DateTimeException if the result exceeds the supported range915*/916public YearMonth minusYears(long yearsToSubtract) {917return (yearsToSubtract == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-yearsToSubtract));918}919920/**921* Returns a copy of this {@code YearMonth} with the specified number of months subtracted.922* <p>923* This instance is immutable and unaffected by this method call.924*925* @param monthsToSubtract the months to subtract, may be negative926* @return a {@code YearMonth} based on this year-month with the months subtracted, not null927* @throws DateTimeException if the result exceeds the supported range928*/929public YearMonth minusMonths(long monthsToSubtract) {930return (monthsToSubtract == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-monthsToSubtract));931}932933//-----------------------------------------------------------------------934/**935* Queries this year-month using the specified query.936* <p>937* This queries this year-month using the specified query strategy object.938* The {@code TemporalQuery} object defines the logic to be used to939* obtain the result. Read the documentation of the query to understand940* what the result of this method will be.941* <p>942* The result of this method is obtained by invoking the943* {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the944* specified query passing {@code this} as the argument.945*946* @param <R> the type of the result947* @param query the query to invoke, not null948* @return the query result, null may be returned (defined by the query)949* @throws DateTimeException if unable to query (defined by the query)950* @throws ArithmeticException if numeric overflow occurs (defined by the query)951*/952@SuppressWarnings("unchecked")953@Override954public <R> R query(TemporalQuery<R> query) {955if (query == TemporalQueries.chronology()) {956return (R) IsoChronology.INSTANCE;957} else if (query == TemporalQueries.precision()) {958return (R) MONTHS;959}960return Temporal.super.query(query);961}962963/**964* Adjusts the specified temporal object to have this year-month.965* <p>966* This returns a temporal object of the same observable type as the input967* with the year and month changed to be the same as this.968* <p>969* The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}970* passing {@link ChronoField#PROLEPTIC_MONTH} as the field.971* If the specified temporal object does not use the ISO calendar system then972* a {@code DateTimeException} is thrown.973* <p>974* In most cases, it is clearer to reverse the calling pattern by using975* {@link Temporal#with(TemporalAdjuster)}:976* <pre>977* // these two lines are equivalent, but the second approach is recommended978* temporal = thisYearMonth.adjustInto(temporal);979* temporal = temporal.with(thisYearMonth);980* </pre>981* <p>982* This instance is immutable and unaffected by this method call.983*984* @param temporal the target object to be adjusted, not null985* @return the adjusted object, not null986* @throws DateTimeException if unable to make the adjustment987* @throws ArithmeticException if numeric overflow occurs988*/989@Override990public Temporal adjustInto(Temporal temporal) {991if (Chronology.from(temporal).equals(IsoChronology.INSTANCE) == false) {992throw new DateTimeException("Adjustment only supported on ISO date-time");993}994return temporal.with(PROLEPTIC_MONTH, getProlepticMonth());995}996997/**998* Calculates the amount of time until another year-month in terms of the specified unit.999* <p>1000* This calculates the amount of time between two {@code YearMonth}1001* objects in terms of a single {@code TemporalUnit}.1002* The start and end points are {@code this} and the specified year-month.1003* The result will be negative if the end is before the start.1004* The {@code Temporal} passed to this method is converted to a1005* {@code YearMonth} using {@link #from(TemporalAccessor)}.1006* For example, the amount in years between two year-months can be calculated1007* using {@code startYearMonth.until(endYearMonth, YEARS)}.1008* <p>1009* The calculation returns a whole number, representing the number of1010* complete units between the two year-months.1011* For example, the amount in decades between 2012-06 and 2032-051012* will only be one decade as it is one month short of two decades.1013* <p>1014* There are two equivalent ways of using this method.1015* The first is to invoke this method.1016* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:1017* <pre>1018* // these two lines are equivalent1019* amount = start.until(end, MONTHS);1020* amount = MONTHS.between(start, end);1021* </pre>1022* The choice should be made based on which makes the code more readable.1023* <p>1024* The calculation is implemented in this method for {@link ChronoUnit}.1025* The units {@code MONTHS}, {@code YEARS}, {@code DECADES},1026* {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS} are supported.1027* Other {@code ChronoUnit} values will throw an exception.1028* <p>1029* If the unit is not a {@code ChronoUnit}, then the result of this method1030* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}1031* passing {@code this} as the first argument and the converted input temporal1032* as the second argument.1033* <p>1034* This instance is immutable and unaffected by this method call.1035*1036* @param endExclusive the end date, exclusive, which is converted to a {@code YearMonth}, not null1037* @param unit the unit to measure the amount in, not null1038* @return the amount of time between this year-month and the end year-month1039* @throws DateTimeException if the amount cannot be calculated, or the end1040* temporal cannot be converted to a {@code YearMonth}1041* @throws UnsupportedTemporalTypeException if the unit is not supported1042* @throws ArithmeticException if numeric overflow occurs1043*/1044@Override1045public long until(Temporal endExclusive, TemporalUnit unit) {1046YearMonth end = YearMonth.from(endExclusive);1047if (unit instanceof ChronoUnit chronoUnit) {1048long monthsUntil = end.getProlepticMonth() - getProlepticMonth(); // no overflow1049switch (chronoUnit) {1050case MONTHS: return monthsUntil;1051case YEARS: return monthsUntil / 12;1052case DECADES: return monthsUntil / 120;1053case CENTURIES: return monthsUntil / 1200;1054case MILLENNIA: return monthsUntil / 12000;1055case ERAS: return end.getLong(ERA) - getLong(ERA);1056}1057throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);1058}1059return unit.between(this, end);1060}10611062/**1063* Formats this year-month using the specified formatter.1064* <p>1065* This year-month will be passed to the formatter to produce a string.1066*1067* @param formatter the formatter to use, not null1068* @return the formatted year-month string, not null1069* @throws DateTimeException if an error occurs during printing1070*/1071public String format(DateTimeFormatter formatter) {1072Objects.requireNonNull(formatter, "formatter");1073return formatter.format(this);1074}10751076//-----------------------------------------------------------------------1077/**1078* Combines this year-month with a day-of-month to create a {@code LocalDate}.1079* <p>1080* This returns a {@code LocalDate} formed from this year-month and the specified day-of-month.1081* <p>1082* The day-of-month value must be valid for the year-month.1083* <p>1084* This method can be used as part of a chain to produce a date:1085* <pre>1086* LocalDate date = year.atMonth(month).atDay(day);1087* </pre>1088*1089* @param dayOfMonth the day-of-month to use, from 1 to 311090* @return the date formed from this year-month and the specified day, not null1091* @throws DateTimeException if the day is invalid for the year-month1092* @see #isValidDay(int)1093*/1094public LocalDate atDay(int dayOfMonth) {1095return LocalDate.of(year, month, dayOfMonth);1096}10971098/**1099* Returns a {@code LocalDate} at the end of the month.1100* <p>1101* This returns a {@code LocalDate} based on this year-month.1102* The day-of-month is set to the last valid day of the month, taking1103* into account leap years.1104* <p>1105* This method can be used as part of a chain to produce a date:1106* <pre>1107* LocalDate date = year.atMonth(month).atEndOfMonth();1108* </pre>1109*1110* @return the last valid date of this year-month, not null1111*/1112public LocalDate atEndOfMonth() {1113return LocalDate.of(year, month, lengthOfMonth());1114}11151116//-----------------------------------------------------------------------1117/**1118* Compares this year-month to another year-month.1119* <p>1120* The comparison is based first on the value of the year, then on the value of the month.1121* It is "consistent with equals", as defined by {@link Comparable}.1122*1123* @param other the other year-month to compare to, not null1124* @return the comparator value, negative if less, positive if greater1125*/1126@Override1127public int compareTo(YearMonth other) {1128int cmp = (year - other.year);1129if (cmp == 0) {1130cmp = (month - other.month);1131}1132return cmp;1133}11341135/**1136* Checks if this year-month is after the specified year-month.1137*1138* @param other the other year-month to compare to, not null1139* @return true if this is after the specified year-month1140*/1141public boolean isAfter(YearMonth other) {1142return compareTo(other) > 0;1143}11441145/**1146* Checks if this year-month is before the specified year-month.1147*1148* @param other the other year-month to compare to, not null1149* @return true if this point is before the specified year-month1150*/1151public boolean isBefore(YearMonth other) {1152return compareTo(other) < 0;1153}11541155//-----------------------------------------------------------------------1156/**1157* Checks if this year-month is equal to another year-month.1158* <p>1159* The comparison is based on the time-line position of the year-months.1160*1161* @param obj the object to check, null returns false1162* @return true if this is equal to the other year-month1163*/1164@Override1165public boolean equals(Object obj) {1166if (this == obj) {1167return true;1168}1169return (obj instanceof YearMonth other)1170&& year == other.year1171&& month == other.month;1172}11731174/**1175* A hash code for this year-month.1176*1177* @return a suitable hash code1178*/1179@Override1180public int hashCode() {1181return year ^ (month << 27);1182}11831184//-----------------------------------------------------------------------1185/**1186* Outputs this year-month as a {@code String}, such as {@code 2007-12}.1187* <p>1188* The output will be in the format {@code uuuu-MM}:1189*1190* @return a string representation of this year-month, not null1191*/1192@Override1193public String toString() {1194int absYear = Math.abs(year);1195StringBuilder buf = new StringBuilder(9);1196if (absYear < 1000) {1197if (year < 0) {1198buf.append(year - 10000).deleteCharAt(1);1199} else {1200buf.append(year + 10000).deleteCharAt(0);1201}1202} else {1203buf.append(year);1204}1205return buf.append(month < 10 ? "-0" : "-")1206.append(month)1207.toString();1208}12091210//-----------------------------------------------------------------------1211/**1212* Writes the object using a1213* <a href="{@docRoot}/serialized-form.html#java.time.Ser">dedicated serialized form</a>.1214* @serialData1215* <pre>1216* out.writeByte(12); // identifies a YearMonth1217* out.writeInt(year);1218* out.writeByte(month);1219* </pre>1220*1221* @return the instance of {@code Ser}, not null1222*/1223@java.io.Serial1224private Object writeReplace() {1225return new Ser(Ser.YEAR_MONTH_TYPE, this);1226}12271228/**1229* Defend against malicious streams.1230*1231* @param s the stream to read1232* @throws InvalidObjectException always1233*/1234@java.io.Serial1235private void readObject(ObjectInputStream s) throws InvalidObjectException {1236throw new InvalidObjectException("Deserialization via serialization delegate");1237}12381239void writeExternal(DataOutput out) throws IOException {1240out.writeInt(year);1241out.writeByte(month);1242}12431244static YearMonth readExternal(DataInput in) throws IOException {1245int year = in.readInt();1246byte month = in.readByte();1247return YearMonth.of(year, month);1248}12491250}125112521253