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

Print this page

        

*** 57,67 **** * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ ! package java.time.temporal; import static java.time.temporal.ChronoField.EPOCH_MONTH; import static java.time.temporal.ChronoField.ERA; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static java.time.temporal.ChronoField.YEAR; --- 57,67 ---- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ ! package java.time; import static java.time.temporal.ChronoField.EPOCH_MONTH; import static java.time.temporal.ChronoField.ERA; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static java.time.temporal.ChronoField.YEAR;
*** 72,90 **** import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectStreamException; import java.io.Serializable; ! import java.time.Clock; ! import java.time.DateTimeException; ! import java.time.LocalDate; ! import java.time.Month; ! import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeParseException; import java.time.format.SignStyle; import java.util.Objects; /** * A year-month in the ISO-8601 calendar system, such as {@code 2007-12}. * <p> --- 72,98 ---- import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectStreamException; import java.io.Serializable; ! import java.time.chrono.Chronology; ! import java.time.chrono.IsoChronology; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeParseException; import java.time.format.SignStyle; + import java.time.temporal.ChronoField; + import java.time.temporal.ChronoUnit; + import java.time.temporal.Queries; + import java.time.temporal.Temporal; + import java.time.temporal.TemporalAccessor; + import java.time.temporal.TemporalAdjuster; + import java.time.temporal.TemporalAmount; + import java.time.temporal.TemporalField; + import java.time.temporal.TemporalQuery; + import java.time.temporal.TemporalUnit; + import java.time.temporal.ValueRange; import java.util.Objects; /** * A year-month in the ISO-8601 calendar system, such as {@code 2007-12}. * <p>
*** 210,221 **** //----------------------------------------------------------------------- /** * Obtains an instance of {@code YearMonth} from a temporal object. * <p> ! * A {@code TemporalAccessor} represents some form of date and time information. ! * This factory converts the arbitrary temporal object to an instance of {@code YearMonth}. * <p> * The conversion extracts the {@link ChronoField#YEAR YEAR} and * {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} fields. * The extraction is only permitted if the temporal object has an ISO * chronology, or can be converted to a {@code LocalDate}. --- 218,230 ---- //----------------------------------------------------------------------- /** * Obtains an instance of {@code YearMonth} from a temporal object. * <p> ! * This obtains a year-month based on the specified temporal. ! * A {@code TemporalAccessor} represents an arbitrary set of date and time information, ! * which this factory converts to an instance of {@code YearMonth}. * <p> * The conversion extracts the {@link ChronoField#YEAR YEAR} and * {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} fields. * The extraction is only permitted if the temporal object has an ISO * chronology, or can be converted to a {@code LocalDate}.
*** 230,240 **** public static YearMonth from(TemporalAccessor temporal) { if (temporal instanceof YearMonth) { return (YearMonth) temporal; } try { ! if (ISOChrono.INSTANCE.equals(Chrono.from(temporal)) == false) { temporal = LocalDate.from(temporal); } return of(temporal.get(YEAR), temporal.get(MONTH_OF_YEAR)); } catch (DateTimeException ex) { throw new DateTimeException("Unable to obtain YearMonth from TemporalAccessor: " + temporal.getClass(), ex); --- 239,249 ---- public static YearMonth from(TemporalAccessor temporal) { if (temporal instanceof YearMonth) { return (YearMonth) temporal; } try { ! if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) { temporal = LocalDate.from(temporal); } return of(temporal.get(YEAR), temporal.get(MONTH_OF_YEAR)); } catch (DateTimeException ex) { throw new DateTimeException("Unable to obtain YearMonth from TemporalAccessor: " + temporal.getClass(), ex);
*** 306,317 **** * This checks if this year-month can be queried for the specified field. * If false, then calling the {@link #range(TemporalField) range} and * {@link #get(TemporalField) get} methods will throw an exception. * <p> * If the field is a {@link ChronoField} then the query is implemented here. - * The {@link #isSupported(TemporalField) supported fields} will return valid - * values based on this date-time. * The supported fields are: * <ul> * <li>{@code MONTH_OF_YEAR} * <li>{@code EPOCH_MONTH} * <li>{@code YEAR_OF_ERA} --- 315,324 ----
*** 319,329 **** * <li>{@code ERA} * </ul> * All other {@code ChronoField} instances will return false. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)} * passing {@code this} as the argument. * Whether the field is supported is determined by the field. * * @param field the field to check, null returns false * @return true if the field is supported on this year-month, false if not --- 326,336 ---- * <li>{@code ERA} * </ul> * All other {@code ChronoField} instances will return false. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)} * passing {@code this} as the argument. * Whether the field is supported is determined by the field. * * @param field the field to check, null returns false * @return true if the field is supported on this year-month, false if not
*** 332,342 **** public boolean isSupported(TemporalField field) { if (field instanceof ChronoField) { return field == YEAR || field == MONTH_OF_YEAR || field == EPOCH_MONTH || field == YEAR_OF_ERA || field == ERA; } ! return field != null && field.doIsSupported(this); } /** * Gets the range of valid values for the specified field. * <p> --- 339,349 ---- public boolean isSupported(TemporalField field) { if (field instanceof ChronoField) { return field == YEAR || field == MONTH_OF_YEAR || field == EPOCH_MONTH || field == YEAR_OF_ERA || field == ERA; } ! return field != null && field.isSupportedBy(this); } /** * Gets the range of valid values for the specified field. * <p>
*** 349,359 **** * The {@link #isSupported(TemporalField) supported fields} will return * appropriate range instances. * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)} * passing {@code this} as the argument. * Whether the range can be obtained is determined by the field. * * @param field the field to query the range for, not null * @return the range of valid values for the field, not null --- 356,366 ---- * The {@link #isSupported(TemporalField) supported fields} will return * appropriate range instances. * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)} * passing {@code this} as the argument. * Whether the range can be obtained is determined by the field. * * @param field the field to query the range for, not null * @return the range of valid values for the field, not null
*** 380,390 **** * values based on this year-month, except {@code EPOCH_MONTH} which is too * large to fit in an {@code int} and throw a {@code DateTimeException}. * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)} * passing {@code this} as the argument. Whether the value can be obtained, * and what the value represents, is determined by the field. * * @param field the field to get, not null * @return the value for the field --- 387,397 ---- * values based on this year-month, except {@code EPOCH_MONTH} which is too * large to fit in an {@code int} and throw a {@code DateTimeException}. * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} * passing {@code this} as the argument. Whether the value can be obtained, * and what the value represents, is determined by the field. * * @param field the field to get, not null * @return the value for the field
*** 407,417 **** * The {@link #isSupported(TemporalField) supported fields} will return valid * values based on this year-month. * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)} * passing {@code this} as the argument. Whether the value can be obtained, * and what the value represents, is determined by the field. * * @param field the field to get, not null * @return the value for the field --- 414,424 ---- * The {@link #isSupported(TemporalField) supported fields} will return valid * values based on this year-month. * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} * passing {@code this} as the argument. Whether the value can be obtained, * and what the value represents, is determined by the field. * * @param field the field to get, not null * @return the value for the field
*** 428,438 **** case YEAR: return year; case ERA: return (year < 1 ? 0 : 1); } throw new DateTimeException("Unsupported field: " + field.getName()); } ! return field.doGet(this); } private long getEpochMonth() { return ((year - 1970) * 12L) + (month - 1); } --- 435,445 ---- case YEAR: return year; case ERA: return (year < 1 ? 0 : 1); } throw new DateTimeException("Unsupported field: " + field.getName()); } ! return field.getFrom(this); } private long getEpochMonth() { return ((year - 1970) * 12L) + (month - 1); }
*** 450,467 **** --- 457,489 ---- public int getYear() { return year; } /** + * Gets the month-of-year field from 1 to 12. + * <p> + * This method returns the month as an {@code int} from 1 to 12. + * Application code is frequently clearer if the enum {@link Month} + * is used by calling {@link #getMonth()}. + * + * @return the month-of-year, from 1 to 12 + * @see #getMonth() + */ + public int getMonthValue() { + return month; + } + + /** * Gets the month-of-year field using the {@code Month} enum. * <p> * This method returns the enum {@link Month} for the month. * This avoids confusion as to what {@code int} values mean. * If you need access to the primitive {@code int} value then the enum * provides the {@link Month#getValue() int value}. * * @return the month-of-year, not null + * @see #getMonthValue() */ public Month getMonth() { return Month.of(month); }
*** 483,493 **** * This is historically inaccurate, but is correct for the ISO-8601 standard. * * @return true if the year is leap, false otherwise */ public boolean isLeapYear() { ! return ISOChrono.INSTANCE.isLeapYear(year); } /** * Checks if the day-of-month is valid for this year-month. * <p> --- 505,515 ---- * This is historically inaccurate, but is correct for the ISO-8601 standard. * * @return true if the year is leap, false otherwise */ public boolean isLeapYear() { ! return IsoChronology.INSTANCE.isLeapYear(year); } /** * Checks if the day-of-month is valid for this year-month. * <p>
*** 526,536 **** //----------------------------------------------------------------------- /** * Returns an adjusted copy of this year-month. * <p> ! * This returns a new {@code YearMonth}, based on this one, with the year-month adjusted. * The adjustment takes place using the specified adjuster strategy object. * Read the documentation of the adjuster to understand what adjustment will be made. * <p> * A simple adjuster might simply set the one of the fields, such as the year field. * A more complex adjuster might set the year-month to the next month that --- 548,558 ---- //----------------------------------------------------------------------- /** * Returns an adjusted copy of this year-month. * <p> ! * This returns a {@code YearMonth}, based on this one, with the year-month adjusted. * The adjustment takes place using the specified adjuster strategy object. * Read the documentation of the adjuster to understand what adjustment will be made. * <p> * A simple adjuster might simply set the one of the fields, such as the year field. * A more complex adjuster might set the year-month to the next month that
*** 553,563 **** } /** * Returns a copy of this year-month with the specified field set to a new value. * <p> ! * This returns a new {@code YearMonth}, based on this one, with the value * for the specified field changed. * This can be used to change any supported field, such as the year or month. * If it is not possible to set the value, because the field is not supported or for * some other reason, an exception is thrown. * <p> --- 575,585 ---- } /** * Returns a copy of this year-month with the specified field set to a new value. * <p> ! * This returns a {@code YearMonth}, based on this one, with the value * for the specified field changed. * This can be used to change any supported field, such as the year or month. * If it is not possible to set the value, because the field is not supported or for * some other reason, an exception is thrown. * <p>
*** 585,595 **** * then a {@code DateTimeException} will be thrown. * <p> * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.doWith(Temporal, long)} * passing {@code this} as the argument. In this case, the field determines * whether and how to adjust the instant. * <p> * This instance is immutable and unaffected by this method call. * --- 607,617 ---- * then a {@code DateTimeException} will be thrown. * <p> * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)} * passing {@code this} as the argument. In this case, the field determines * whether and how to adjust the instant. * <p> * This instance is immutable and unaffected by this method call. *
*** 611,621 **** case YEAR: return withYear((int) newValue); case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year)); } throw new DateTimeException("Unsupported field: " + field.getName()); } ! return field.doWith(this, newValue); } //----------------------------------------------------------------------- /** * Returns a copy of this {@code YearMonth} with the year altered. --- 633,643 ---- case YEAR: return withYear((int) newValue); case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year)); } throw new DateTimeException("Unsupported field: " + field.getName()); } ! return field.adjustInto(this, newValue); } //----------------------------------------------------------------------- /** * Returns a copy of this {@code YearMonth} with the year altered.
*** 645,678 **** return with(year, month); } //----------------------------------------------------------------------- /** ! * Returns a copy of this year-month with the specified period added. * <p> ! * This method returns a new year-month based on this year-month with the specified period added. ! * The adder is typically {@link java.time.Period} but may be any other type implementing ! * the {@link TemporalAdder} interface. ! * The calculation is delegated to the specified adjuster, which typically calls ! * back to {@link #plus(long, TemporalUnit)}. * <p> * This instance is immutable and unaffected by this method call. * ! * @param adder the adder to use, not null * @return a {@code YearMonth} based on this year-month with the addition made, not null * @throws DateTimeException if the addition cannot be made * @throws ArithmeticException if numeric overflow occurs */ @Override ! public YearMonth plus(TemporalAdder adder) { ! return (YearMonth) adder.addTo(this); } /** ! * {@inheritDoc} ! * @throws DateTimeException {@inheritDoc} ! * @throws ArithmeticException {@inheritDoc} */ @Override public YearMonth plus(long amountToAdd, TemporalUnit unit) { if (unit instanceof ChronoUnit) { switch ((ChronoUnit) unit) { --- 667,749 ---- return with(year, month); } //----------------------------------------------------------------------- /** ! * Returns a copy of this year-month with the specified amount added. * <p> ! * This returns a {@code YearMonth}, based on this one, with the specified amount added. ! * The amount is typically {@link Period} but may be any other type implementing ! * the {@link TemporalAmount} interface. ! * <p> ! * The calculation is delegated to the amount object by calling ! * {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free ! * to implement the addition in any way it wishes, however it typically ! * calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation ! * of the amount implementation to determine if it can be successfully added. * <p> * This instance is immutable and unaffected by this method call. * ! * @param amountToAdd the amount to add, not null * @return a {@code YearMonth} based on this year-month with the addition made, not null * @throws DateTimeException if the addition cannot be made * @throws ArithmeticException if numeric overflow occurs */ @Override ! public YearMonth plus(TemporalAmount amountToAdd) { ! return (YearMonth) amountToAdd.addTo(this); } /** ! * Returns a copy of this year-month with the specified amount added. ! * <p> ! * This returns a {@code YearMonth}, based on this one, with the amount ! * in terms of the unit added. If it is not possible to add the amount, because the ! * unit is not supported or for some other reason, an exception is thrown. ! * <p> ! * If the field is a {@link ChronoUnit} then the addition is implemented here. ! * The supported fields behave as follows: ! * <ul> ! * <li>{@code MONTHS} - ! * Returns a {@code YearMonth} with the specified number of months added. ! * This is equivalent to {@link #plusMonths(long)}. ! * <li>{@code YEARS} - ! * Returns a {@code YearMonth} with the specified number of years added. ! * This is equivalent to {@link #plusYears(long)}. ! * <li>{@code DECADES} - ! * Returns a {@code YearMonth} with the specified number of decades added. ! * This is equivalent to calling {@link #plusYears(long)} with the amount ! * multiplied by 10. ! * <li>{@code CENTURIES} - ! * Returns a {@code YearMonth} with the specified number of centuries added. ! * This is equivalent to calling {@link #plusYears(long)} with the amount ! * multiplied by 100. ! * <li>{@code MILLENNIA} - ! * Returns a {@code YearMonth} with the specified number of millennia added. ! * This is equivalent to calling {@link #plusYears(long)} with the amount ! * multiplied by 1,000. ! * <li>{@code ERAS} - ! * Returns a {@code YearMonth} with the specified number of eras added. ! * Only two eras are supported so the amount must be one, zero or minus one. ! * If the amount is non-zero then the year is changed such that the year-of-era ! * is unchanged. ! * </ul> ! * <p> ! * All other {@code ChronoUnit} instances will throw a {@code DateTimeException}. ! * <p> ! * If the field is not a {@code ChronoUnit}, then the result of this method ! * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)} ! * passing {@code this} as the argument. In this case, the unit determines ! * whether and how to perform the addition. ! * <p> ! * This instance is immutable and unaffected by this method call. ! * ! * @param amountToAdd the amount of the unit to add to the result, may be negative ! * @param unit the unit of the amount to add, not null ! * @return a {@code YearMonth} based on this year-month with the specified amount added, not null ! * @throws DateTimeException if the addition cannot be made ! * @throws ArithmeticException if numeric overflow occurs */ @Override public YearMonth plus(long amountToAdd, TemporalUnit unit) { if (unit instanceof ChronoUnit) { switch ((ChronoUnit) unit) {
*** 683,693 **** case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000)); case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd)); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } ! return unit.doPlus(this, amountToAdd); } /** * Returns a copy of this year-month with the specified period in years added. * <p> --- 754,764 ---- case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000)); case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd)); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } ! return unit.addTo(this, amountToAdd); } /** * Returns a copy of this year-month with the specified period in years added. * <p>
*** 725,758 **** return with(newYear, newMonth); } //----------------------------------------------------------------------- /** ! * Returns a copy of this year-month with the specified period subtracted. * <p> ! * This method returns a new year-month based on this year-month with the specified period subtracted. ! * The subtractor is typically {@link java.time.Period} but may be any other type implementing ! * the {@link TemporalSubtractor} interface. ! * The calculation is delegated to the specified adjuster, which typically calls ! * back to {@link #minus(long, TemporalUnit)}. * <p> * This instance is immutable and unaffected by this method call. * ! * @param subtractor the subtractor to use, not null * @return a {@code YearMonth} based on this year-month with the subtraction made, not null * @throws DateTimeException if the subtraction cannot be made * @throws ArithmeticException if numeric overflow occurs */ @Override ! public YearMonth minus(TemporalSubtractor subtractor) { ! return (YearMonth) subtractor.subtractFrom(this); } /** ! * {@inheritDoc} ! * @throws DateTimeException {@inheritDoc} ! * @throws ArithmeticException {@inheritDoc} */ @Override public YearMonth minus(long amountToSubtract, TemporalUnit unit) { return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit)); } --- 796,846 ---- return with(newYear, newMonth); } //----------------------------------------------------------------------- /** ! * Returns a copy of this year-month with the specified amount subtracted. * <p> ! * This returns a {@code YearMonth}, based on this one, with the specified amount subtracted. ! * The amount is typically {@link Period} but may be any other type implementing ! * the {@link TemporalAmount} interface. ! * <p> ! * The calculation is delegated to the amount object by calling ! * {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free ! * to implement the subtraction in any way it wishes, however it typically ! * calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation ! * of the amount implementation to determine if it can be successfully subtracted. * <p> * This instance is immutable and unaffected by this method call. * ! * @param amountToSubtract the amount to subtract, not null * @return a {@code YearMonth} based on this year-month with the subtraction made, not null * @throws DateTimeException if the subtraction cannot be made * @throws ArithmeticException if numeric overflow occurs */ @Override ! public YearMonth minus(TemporalAmount amountToSubtract) { ! return (YearMonth) amountToSubtract.subtractFrom(this); } /** ! * Returns a copy of this year-month with the specified amount subtracted. ! * <p> ! * This returns a {@code YearMonth}, based on this one, with the amount ! * in terms of the unit subtracted. If it is not possible to subtract the amount, ! * because the unit is not supported or for some other reason, an exception is thrown. ! * <p> ! * This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated. ! * See that method for a full description of how addition, and thus subtraction, works. ! * <p> ! * This instance is immutable and unaffected by this method call. ! * ! * @param amountToSubtract the amount of the unit to subtract from the result, may be negative ! * @param unit the unit of the amount to subtract, not null ! * @return a {@code YearMonth} based on this year-month with the specified amount subtracted, not null ! * @throws DateTimeException if the subtraction cannot be made ! * @throws ArithmeticException if numeric overflow occurs */ @Override public YearMonth minus(long amountToSubtract, TemporalUnit unit) { return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit)); }
*** 803,814 **** * @throws ArithmeticException if numeric overflow occurs (defined by the query) */ @SuppressWarnings("unchecked") @Override public <R> R query(TemporalQuery<R> query) { ! if (query == Queries.chrono()) { ! return (R) ISOChrono.INSTANCE; } else if (query == Queries.precision()) { return (R) MONTHS; } return Temporal.super.query(query); } --- 891,902 ---- * @throws ArithmeticException if numeric overflow occurs (defined by the query) */ @SuppressWarnings("unchecked") @Override public <R> R query(TemporalQuery<R> query) { ! if (query == Queries.chronology()) { ! return (R) IsoChronology.INSTANCE; } else if (query == Queries.precision()) { return (R) MONTHS; } return Temporal.super.query(query); }
*** 839,849 **** * @throws DateTimeException if unable to make the adjustment * @throws ArithmeticException if numeric overflow occurs */ @Override public Temporal adjustInto(Temporal temporal) { ! if (Chrono.from(temporal).equals(ISOChrono.INSTANCE) == false) { throw new DateTimeException("Adjustment only supported on ISO date-time"); } return temporal.with(EPOCH_MONTH, getEpochMonth()); } --- 927,937 ---- * @throws DateTimeException if unable to make the adjustment * @throws ArithmeticException if numeric overflow occurs */ @Override public Temporal adjustInto(Temporal temporal) { ! if (Chronology.from(temporal).equals(IsoChronology.INSTANCE) == false) { throw new DateTimeException("Adjustment only supported on ISO date-time"); } return temporal.with(EPOCH_MONTH, getEpochMonth()); }
*** 861,878 **** * The calculation returns a whole number, representing the number of * complete units between the two year-months. * For example, the period in decades between 2012-06 and 2032-05 * will only be one decade as it is one month short of two decades. * <p> ! * This method operates in association with {@link TemporalUnit#between}. ! * The result of this method is a {@code long} representing the amount of ! * the specified unit. By contrast, the result of {@code between} is an ! * object that can be used directly in addition/subtraction: * <pre> ! * long period = start.periodUntil(end, YEARS); // this method ! * dateTime.plus(YEARS.between(start, end)); // use in plus/minus * </pre> * <p> * The calculation is implemented in this method for {@link ChronoUnit}. * The units {@code MONTHS}, {@code YEARS}, {@code DECADES}, * {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS} are supported. * Other {@code ChronoUnit} values will throw an exception. --- 949,967 ---- * The calculation returns a whole number, representing the number of * complete units between the two year-months. * For example, the period in decades between 2012-06 and 2032-05 * will only be one decade as it is one month short of two decades. * <p> ! * There are two equivalent ways of using this method. ! * The first is to invoke this method. ! * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}: * <pre> ! * // these two lines are equivalent ! * amount = start.periodUntil(end, MONTHS); ! * amount = MONTHS.between(start, end); * </pre> + * The choice should be made based on which makes the code more readable. * <p> * The calculation is implemented in this method for {@link ChronoUnit}. * The units {@code MONTHS}, {@code YEARS}, {@code DECADES}, * {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS} are supported. * Other {@code ChronoUnit} values will throw an exception.
*** 907,942 **** case MILLENNIA: return monthsUntil / 12000; case ERAS: return end.getLong(ERA) - getLong(ERA); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } ! return unit.between(this, endYearMonth).getAmount(); } //----------------------------------------------------------------------- /** ! * Returns a date formed from this year-month at the specified day-of-month. * <p> - * This combines this year-month and the specified day-of-month to form a {@code LocalDate}. * The day-of-month value must be valid for the year-month. * <p> * This method can be used as part of a chain to produce a date: * <pre> * LocalDate date = year.atMonth(month).atDay(day); * </pre> - * <p> - * This instance is immutable and unaffected by this method call. * * @param dayOfMonth the day-of-month to use, from 1 to 31 * @return the date formed from this year-month and the specified day, not null ! * @throws DateTimeException when the day is invalid for the year-month * @see #isValidDay(int) */ public LocalDate atDay(int dayOfMonth) { return LocalDate.of(year, month, dayOfMonth); } //----------------------------------------------------------------------- /** * Compares this year-month to another year-month. * <p> * The comparison is based first on the value of the year, then on the value of the month. --- 996,1048 ---- case MILLENNIA: return monthsUntil / 12000; case ERAS: return end.getLong(ERA) - getLong(ERA); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } ! return unit.between(this, endYearMonth); } //----------------------------------------------------------------------- /** ! * Combines this year-month with a day-of-month to create a {@code LocalDate}. ! * <p> ! * This returns a {@code LocalDate} formed from this year-month and the specified day-of-month. * <p> * The day-of-month value must be valid for the year-month. * <p> * This method can be used as part of a chain to produce a date: * <pre> * LocalDate date = year.atMonth(month).atDay(day); * </pre> * * @param dayOfMonth the day-of-month to use, from 1 to 31 * @return the date formed from this year-month and the specified day, not null ! * @throws DateTimeException if the day is invalid for the year-month * @see #isValidDay(int) */ public LocalDate atDay(int dayOfMonth) { return LocalDate.of(year, month, dayOfMonth); } + /** + * Returns a {@code LocalDate} at the end of the month. + * <p> + * This returns a {@code LocalDate} based on this year-month. + * The day-of-month is set to the last valid day of the month, taking + * into account leap years. + * <p> + * This method can be used as part of a chain to produce a date: + * <pre> + * LocalDate date = year.atMonth(month).atEndOfMonth(); + * </pre> + * + * @return the last valid date of this year-month, not null + */ + public LocalDate atEndOfMonth() { + return LocalDate.of(year, month, lengthOfMonth()); + } + //----------------------------------------------------------------------- /** * Compares this year-month to another year-month. * <p> * The comparison is based first on the value of the year, then on the value of the month.
*** 1033,1059 **** /** * Outputs this year-month as a {@code String} using the formatter. * <p> * This year-month will be passed to the formatter ! * {@link DateTimeFormatter#print(TemporalAccessor) print method}. * * @param formatter the formatter to use, not null * @return the formatted year-month string, not null * @throws DateTimeException if an error occurs during printing */ public String toString(DateTimeFormatter formatter) { Objects.requireNonNull(formatter, "formatter"); ! return formatter.print(this); } //----------------------------------------------------------------------- /** * Writes the object using a * <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>. * <pre> ! * out.writeByte(5); // identifies this as a Year * out.writeInt(year); * out.writeByte(month); * </pre> * * @return the instance of {@code Ser}, not null --- 1139,1165 ---- /** * Outputs this year-month as a {@code String} using the formatter. * <p> * This year-month will be passed to the formatter ! * {@link DateTimeFormatter#format(TemporalAccessor) format method}. * * @param formatter the formatter to use, not null * @return the formatted year-month string, not null * @throws DateTimeException if an error occurs during printing */ public String toString(DateTimeFormatter formatter) { Objects.requireNonNull(formatter, "formatter"); ! return formatter.format(this); } //----------------------------------------------------------------------- /** * Writes the object using a * <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>. * <pre> ! * out.writeByte(12); // identifies this as a YearMonth * out.writeInt(year); * out.writeByte(month); * </pre> * * @return the instance of {@code Ser}, not null