Path: blob/master/src/java.base/share/classes/java/time/LocalDate.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.LocalTime.SECONDS_PER_DAY;64import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH;65import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR;66import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH;67import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR;68import static java.time.temporal.ChronoField.DAY_OF_MONTH;69import static java.time.temporal.ChronoField.DAY_OF_YEAR;70import static java.time.temporal.ChronoField.EPOCH_DAY;71import static java.time.temporal.ChronoField.ERA;72import static java.time.temporal.ChronoField.MONTH_OF_YEAR;73import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;74import static java.time.temporal.ChronoField.YEAR;7576import java.io.DataInput;77import java.io.DataOutput;78import java.io.IOException;79import java.io.InvalidObjectException;80import java.io.ObjectInputStream;81import java.io.Serializable;82import java.time.chrono.ChronoLocalDate;83import java.time.chrono.IsoEra;84import java.time.chrono.IsoChronology;85import java.time.format.DateTimeFormatter;86import java.time.format.DateTimeParseException;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.time.zone.ZoneOffsetTransition;100import java.time.zone.ZoneRules;101import java.util.Objects;102import java.util.stream.LongStream;103import java.util.stream.Stream;104105/**106* A date without a time-zone in the ISO-8601 calendar system,107* such as {@code 2007-12-03}.108* <p>109* {@code LocalDate} is an immutable date-time object that represents a date,110* often viewed as year-month-day. Other date fields, such as day-of-year,111* day-of-week and week-of-year, can also be accessed.112* For example, the value "2nd October 2007" can be stored in a {@code LocalDate}.113* <p>114* This class does not store or represent a time or time-zone.115* Instead, it is a description of the date, as used for birthdays.116* It cannot represent an instant on the time-line without additional information117* such as an offset or time-zone.118* <p>119* The ISO-8601 calendar system is the modern civil calendar system used today120* in most of the world. It is equivalent to the proleptic Gregorian calendar121* system, in which today's rules for leap years are applied for all time.122* For most applications written today, the ISO-8601 rules are entirely suitable.123* However, any application that makes use of historical dates, and requires them124* to be accurate will find the ISO-8601 approach unsuitable.125* <p>126* This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>127* class; programmers should treat instances that are128* {@linkplain #equals(Object) equal} as interchangeable and should not129* use instances for synchronization, or unpredictable behavior may130* occur. For example, in a future release, synchronization may fail.131* The {@code equals} method should be used for comparisons.132*133* @implSpec134* This class is immutable and thread-safe.135*136* @since 1.8137*/138@jdk.internal.ValueBased139public final class LocalDate140implements Temporal, TemporalAdjuster, ChronoLocalDate, Serializable {141142/**143* The minimum supported {@code LocalDate}, '-999999999-01-01'.144* This could be used by an application as a "far past" date.145*/146public static final LocalDate MIN = LocalDate.of(Year.MIN_VALUE, 1, 1);147/**148* The maximum supported {@code LocalDate}, '+999999999-12-31'.149* This could be used by an application as a "far future" date.150*/151public static final LocalDate MAX = LocalDate.of(Year.MAX_VALUE, 12, 31);152/**153* The epoch year {@code LocalDate}, '1970-01-01'.154*/155public static final LocalDate EPOCH = LocalDate.of(1970, 1, 1);156157/**158* Serialization version.159*/160@java.io.Serial161private static final long serialVersionUID = 2942565459149668126L;162/**163* The number of days in a 400 year cycle.164*/165private static final int DAYS_PER_CYCLE = 146097;166/**167* The number of days from year zero to year 1970.168* There are five 400 year cycles from year zero to 2000.169* There are 7 leap years from 1970 to 2000.170*/171static final long DAYS_0000_TO_1970 = (DAYS_PER_CYCLE * 5L) - (30L * 365L + 7L);172173/**174* The year.175*/176private final int year;177/**178* The month-of-year.179*/180private final short month;181/**182* The day-of-month.183*/184private final short day;185186//-----------------------------------------------------------------------187/**188* Obtains the current date from the system clock in the default time-zone.189* <p>190* This will query the {@link Clock#systemDefaultZone() system clock} in the default191* time-zone to obtain the current date.192* <p>193* Using this method will prevent the ability to use an alternate clock for testing194* because the clock is hard-coded.195*196* @return the current date using the system clock and default time-zone, not null197*/198public static LocalDate now() {199return now(Clock.systemDefaultZone());200}201202/**203* Obtains the current date from the system clock in the specified time-zone.204* <p>205* This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date.206* Specifying the time-zone avoids dependence on the default time-zone.207* <p>208* Using this method will prevent the ability to use an alternate clock for testing209* because the clock is hard-coded.210*211* @param zone the zone ID to use, not null212* @return the current date using the system clock, not null213*/214public static LocalDate now(ZoneId zone) {215return now(Clock.system(zone));216}217218/**219* Obtains the current date from the specified clock.220* <p>221* This will query the specified clock to obtain the current date - today.222* Using this method allows the use of an alternate clock for testing.223* The alternate clock may be introduced using {@link Clock dependency injection}.224*225* @param clock the clock to use, not null226* @return the current date, not null227*/228public static LocalDate now(Clock clock) {229Objects.requireNonNull(clock, "clock");230final Instant now = clock.instant(); // called once231return ofInstant(now, clock.getZone());232}233234//-----------------------------------------------------------------------235/**236* Obtains an instance of {@code LocalDate} from a year, month and day.237* <p>238* This returns a {@code LocalDate} with the specified year, month and day-of-month.239* The day must be valid for the year and month, otherwise an exception will be thrown.240*241* @param year the year to represent, from MIN_YEAR to MAX_YEAR242* @param month the month-of-year to represent, not null243* @param dayOfMonth the day-of-month to represent, from 1 to 31244* @return the local date, not null245* @throws DateTimeException if the value of any field is out of range,246* or if the day-of-month is invalid for the month-year247*/248public static LocalDate of(int year, Month month, int dayOfMonth) {249YEAR.checkValidValue(year);250Objects.requireNonNull(month, "month");251DAY_OF_MONTH.checkValidValue(dayOfMonth);252return create(year, month.getValue(), dayOfMonth);253}254255/**256* Obtains an instance of {@code LocalDate} from a year, month and day.257* <p>258* This returns a {@code LocalDate} with the specified year, month and day-of-month.259* The day must be valid for the year and month, otherwise an exception will be thrown.260*261* @param year the year to represent, from MIN_YEAR to MAX_YEAR262* @param month the month-of-year to represent, from 1 (January) to 12 (December)263* @param dayOfMonth the day-of-month to represent, from 1 to 31264* @return the local date, not null265* @throws DateTimeException if the value of any field is out of range,266* or if the day-of-month is invalid for the month-year267*/268public static LocalDate of(int year, int month, int dayOfMonth) {269YEAR.checkValidValue(year);270MONTH_OF_YEAR.checkValidValue(month);271DAY_OF_MONTH.checkValidValue(dayOfMonth);272return create(year, month, dayOfMonth);273}274275//-----------------------------------------------------------------------276/**277* Obtains an instance of {@code LocalDate} from a year and day-of-year.278* <p>279* This returns a {@code LocalDate} with the specified year and day-of-year.280* The day-of-year must be valid for the year, otherwise an exception will be thrown.281*282* @param year the year to represent, from MIN_YEAR to MAX_YEAR283* @param dayOfYear the day-of-year to represent, from 1 to 366284* @return the local date, not null285* @throws DateTimeException if the value of any field is out of range,286* or if the day-of-year is invalid for the year287*/288public static LocalDate ofYearDay(int year, int dayOfYear) {289YEAR.checkValidValue(year);290DAY_OF_YEAR.checkValidValue(dayOfYear);291boolean leap = IsoChronology.INSTANCE.isLeapYear(year);292if (dayOfYear == 366 && leap == false) {293throw new DateTimeException("Invalid date 'DayOfYear 366' as '" + year + "' is not a leap year");294}295Month moy = Month.of((dayOfYear - 1) / 31 + 1);296int monthEnd = moy.firstDayOfYear(leap) + moy.length(leap) - 1;297if (dayOfYear > monthEnd) {298moy = moy.plus(1);299}300int dom = dayOfYear - moy.firstDayOfYear(leap) + 1;301return new LocalDate(year, moy.getValue(), dom);302}303304//-----------------------------------------------------------------------305/**306* Obtains an instance of {@code LocalDate} from an {@code Instant} and zone ID.307* <p>308* This creates a local date based on the specified instant.309* First, the offset from UTC/Greenwich is obtained using the zone ID and instant,310* which is simple as there is only one valid offset for each instant.311* Then, the instant and offset are used to calculate the local date.312*313* @param instant the instant to create the date from, not null314* @param zone the time-zone, which may be an offset, not null315* @return the local date, not null316* @throws DateTimeException if the result exceeds the supported range317* @since 9318*/319public static LocalDate ofInstant(Instant instant, ZoneId zone) {320Objects.requireNonNull(instant, "instant");321Objects.requireNonNull(zone, "zone");322ZoneRules rules = zone.getRules();323ZoneOffset offset = rules.getOffset(instant);324long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();325long localEpochDay = Math.floorDiv(localSecond, SECONDS_PER_DAY);326return ofEpochDay(localEpochDay);327}328329//-----------------------------------------------------------------------330/**331* Obtains an instance of {@code LocalDate} from the epoch day count.332* <p>333* This returns a {@code LocalDate} with the specified epoch-day.334* The {@link ChronoField#EPOCH_DAY EPOCH_DAY} is a simple incrementing count335* of days where day 0 is 1970-01-01. Negative numbers represent earlier days.336*337* @param epochDay the Epoch Day to convert, based on the epoch 1970-01-01338* @return the local date, not null339* @throws DateTimeException if the epoch day exceeds the supported date range340*/341public static LocalDate ofEpochDay(long epochDay) {342EPOCH_DAY.checkValidValue(epochDay);343long zeroDay = epochDay + DAYS_0000_TO_1970;344// find the march-based year345zeroDay -= 60; // adjust to 0000-03-01 so leap day is at end of four year cycle346long adjust = 0;347if (zeroDay < 0) {348// adjust negative years to positive for calculation349long adjustCycles = (zeroDay + 1) / DAYS_PER_CYCLE - 1;350adjust = adjustCycles * 400;351zeroDay += -adjustCycles * DAYS_PER_CYCLE;352}353long yearEst = (400 * zeroDay + 591) / DAYS_PER_CYCLE;354long doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400);355if (doyEst < 0) {356// fix estimate357yearEst--;358doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400);359}360yearEst += adjust; // reset any negative year361int marchDoy0 = (int) doyEst;362363// convert march-based values back to january-based364int marchMonth0 = (marchDoy0 * 5 + 2) / 153;365int month = (marchMonth0 + 2) % 12 + 1;366int dom = marchDoy0 - (marchMonth0 * 306 + 5) / 10 + 1;367yearEst += marchMonth0 / 10;368369// check year now we are certain it is correct370int year = YEAR.checkValidIntValue(yearEst);371return new LocalDate(year, month, dom);372}373374//-----------------------------------------------------------------------375/**376* Obtains an instance of {@code LocalDate} from a temporal object.377* <p>378* This obtains a local date based on the specified temporal.379* A {@code TemporalAccessor} represents an arbitrary set of date and time information,380* which this factory converts to an instance of {@code LocalDate}.381* <p>382* The conversion uses the {@link TemporalQueries#localDate()} query, which relies383* on extracting the {@link ChronoField#EPOCH_DAY EPOCH_DAY} field.384* <p>385* This method matches the signature of the functional interface {@link TemporalQuery}386* allowing it to be used as a query via method reference, {@code LocalDate::from}.387*388* @param temporal the temporal object to convert, not null389* @return the local date, not null390* @throws DateTimeException if unable to convert to a {@code LocalDate}391*/392public static LocalDate from(TemporalAccessor temporal) {393Objects.requireNonNull(temporal, "temporal");394LocalDate date = temporal.query(TemporalQueries.localDate());395if (date == null) {396throw new DateTimeException("Unable to obtain LocalDate from TemporalAccessor: " +397temporal + " of type " + temporal.getClass().getName());398}399return date;400}401402//-----------------------------------------------------------------------403/**404* Obtains an instance of {@code LocalDate} from a text string such as {@code 2007-12-03}.405* <p>406* The string must represent a valid date and is parsed using407* {@link java.time.format.DateTimeFormatter#ISO_LOCAL_DATE}.408*409* @param text the text to parse such as "2007-12-03", not null410* @return the parsed local date, not null411* @throws DateTimeParseException if the text cannot be parsed412*/413public static LocalDate parse(CharSequence text) {414return parse(text, DateTimeFormatter.ISO_LOCAL_DATE);415}416417/**418* Obtains an instance of {@code LocalDate} from a text string using a specific formatter.419* <p>420* The text is parsed using the formatter, returning a date.421*422* @param text the text to parse, not null423* @param formatter the formatter to use, not null424* @return the parsed local date, not null425* @throws DateTimeParseException if the text cannot be parsed426*/427public static LocalDate parse(CharSequence text, DateTimeFormatter formatter) {428Objects.requireNonNull(formatter, "formatter");429return formatter.parse(text, LocalDate::from);430}431432//-----------------------------------------------------------------------433/**434* Creates a local date from the year, month and day fields.435*436* @param year the year to represent, validated from MIN_YEAR to MAX_YEAR437* @param month the month-of-year to represent, from 1 to 12, validated438* @param dayOfMonth the day-of-month to represent, validated from 1 to 31439* @return the local date, not null440* @throws DateTimeException if the day-of-month is invalid for the month-year441*/442private static LocalDate create(int year, int month, int dayOfMonth) {443if (dayOfMonth > 28) {444int dom = 31;445switch (month) {446case 2:447dom = (IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);448break;449case 4:450case 6:451case 9:452case 11:453dom = 30;454break;455}456if (dayOfMonth > dom) {457if (dayOfMonth == 29) {458throw new DateTimeException("Invalid date 'February 29' as '" + year + "' is not a leap year");459} else {460throw new DateTimeException("Invalid date '" + Month.of(month).name() + " " + dayOfMonth + "'");461}462}463}464return new LocalDate(year, month, dayOfMonth);465}466467/**468* Resolves the date, resolving days past the end of month.469*470* @param year the year to represent, validated from MIN_YEAR to MAX_YEAR471* @param month the month-of-year to represent, validated from 1 to 12472* @param day the day-of-month to represent, validated from 1 to 31473* @return the resolved date, not null474*/475private static LocalDate resolvePreviousValid(int year, int month, int day) {476switch (month) {477case 2:478day = Math.min(day, IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);479break;480case 4:481case 6:482case 9:483case 11:484day = Math.min(day, 30);485break;486}487return new LocalDate(year, month, day);488}489490/**491* Constructor, previously validated.492*493* @param year the year to represent, from MIN_YEAR to MAX_YEAR494* @param month the month-of-year to represent, not null495* @param dayOfMonth the day-of-month to represent, valid for year-month, from 1 to 31496*/497private LocalDate(int year, int month, int dayOfMonth) {498this.year = year;499this.month = (short) month;500this.day = (short) dayOfMonth;501}502503//-----------------------------------------------------------------------504/**505* Checks if the specified field is supported.506* <p>507* This checks if this date can be queried for the specified field.508* If false, then calling the {@link #range(TemporalField) range},509* {@link #get(TemporalField) get} and {@link #with(TemporalField, long)}510* methods will throw an exception.511* <p>512* If the field is a {@link ChronoField} then the query is implemented here.513* The supported fields are:514* <ul>515* <li>{@code DAY_OF_WEEK}516* <li>{@code ALIGNED_DAY_OF_WEEK_IN_MONTH}517* <li>{@code ALIGNED_DAY_OF_WEEK_IN_YEAR}518* <li>{@code DAY_OF_MONTH}519* <li>{@code DAY_OF_YEAR}520* <li>{@code EPOCH_DAY}521* <li>{@code ALIGNED_WEEK_OF_MONTH}522* <li>{@code ALIGNED_WEEK_OF_YEAR}523* <li>{@code MONTH_OF_YEAR}524* <li>{@code PROLEPTIC_MONTH}525* <li>{@code YEAR_OF_ERA}526* <li>{@code YEAR}527* <li>{@code ERA}528* </ul>529* All other {@code ChronoField} instances will return false.530* <p>531* If the field is not a {@code ChronoField}, then the result of this method532* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}533* passing {@code this} as the argument.534* Whether the field is supported is determined by the field.535*536* @param field the field to check, null returns false537* @return true if the field is supported on this date, false if not538*/539@Override // override for Javadoc540public boolean isSupported(TemporalField field) {541return ChronoLocalDate.super.isSupported(field);542}543544/**545* Checks if the specified unit is supported.546* <p>547* This checks if the specified unit can be added to, or subtracted from, this date.548* If false, then calling the {@link #plus(long, TemporalUnit)} and549* {@link #minus(long, TemporalUnit) minus} methods will throw an exception.550* <p>551* If the unit is a {@link ChronoUnit} then the query is implemented here.552* The supported units are:553* <ul>554* <li>{@code DAYS}555* <li>{@code WEEKS}556* <li>{@code MONTHS}557* <li>{@code YEARS}558* <li>{@code DECADES}559* <li>{@code CENTURIES}560* <li>{@code MILLENNIA}561* <li>{@code ERAS}562* </ul>563* All other {@code ChronoUnit} instances will return false.564* <p>565* If the unit is not a {@code ChronoUnit}, then the result of this method566* is obtained by invoking {@code TemporalUnit.isSupportedBy(Temporal)}567* passing {@code this} as the argument.568* Whether the unit is supported is determined by the unit.569*570* @param unit the unit to check, null returns false571* @return true if the unit can be added/subtracted, false if not572*/573@Override // override for Javadoc574public boolean isSupported(TemporalUnit unit) {575return ChronoLocalDate.super.isSupported(unit);576}577578//-----------------------------------------------------------------------579/**580* Gets the range of valid values for the specified field.581* <p>582* The range object expresses the minimum and maximum valid values for a field.583* This date is used to enhance the accuracy of the returned range.584* If it is not possible to return the range, because the field is not supported585* or for some other reason, an exception is thrown.586* <p>587* If the field is a {@link ChronoField} then the query is implemented here.588* The {@link #isSupported(TemporalField) supported fields} will return589* appropriate range instances.590* All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.591* <p>592* If the field is not a {@code ChronoField}, then the result of this method593* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}594* passing {@code this} as the argument.595* Whether the range can be obtained is determined by the field.596*597* @param field the field to query the range for, not null598* @return the range of valid values for the field, not null599* @throws DateTimeException if the range for the field cannot be obtained600* @throws UnsupportedTemporalTypeException if the field is not supported601*/602@Override603public ValueRange range(TemporalField field) {604if (field instanceof ChronoField chronoField) {605if (chronoField.isDateBased()) {606switch (chronoField) {607case DAY_OF_MONTH: return ValueRange.of(1, lengthOfMonth());608case DAY_OF_YEAR: return ValueRange.of(1, lengthOfYear());609case ALIGNED_WEEK_OF_MONTH: return ValueRange.of(1, getMonth() == Month.FEBRUARY && isLeapYear() == false ? 4 : 5);610case YEAR_OF_ERA:611return (getYear() <= 0 ? ValueRange.of(1, Year.MAX_VALUE + 1) : ValueRange.of(1, Year.MAX_VALUE));612}613return field.range();614}615throw new UnsupportedTemporalTypeException("Unsupported field: " + field);616}617return field.rangeRefinedBy(this);618}619620/**621* Gets the value of the specified field from this date as an {@code int}.622* <p>623* This queries this date for the value of the specified field.624* The returned value will always be within the valid range of values for the field.625* If it is not possible to return the value, because the field is not supported626* or for some other reason, an exception is thrown.627* <p>628* If the field is a {@link ChronoField} then the query is implemented here.629* The {@link #isSupported(TemporalField) supported fields} will return valid630* values based on this date, except {@code EPOCH_DAY} and {@code PROLEPTIC_MONTH}631* which are too large to fit in an {@code int} and throw an {@code UnsupportedTemporalTypeException}.632* All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.633* <p>634* If the field is not a {@code ChronoField}, then the result of this method635* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}636* passing {@code this} as the argument. Whether the value can be obtained,637* and what the value represents, is determined by the field.638*639* @param field the field to get, not null640* @return the value for the field641* @throws DateTimeException if a value for the field cannot be obtained or642* the value is outside the range of valid values for the field643* @throws UnsupportedTemporalTypeException if the field is not supported or644* the range of values exceeds an {@code int}645* @throws ArithmeticException if numeric overflow occurs646*/647@Override // override for Javadoc and performance648public int get(TemporalField field) {649if (field instanceof ChronoField) {650return get0(field);651}652return ChronoLocalDate.super.get(field);653}654655/**656* Gets the value of the specified field from this date as a {@code long}.657* <p>658* This queries this date for the value of the specified field.659* If it is not possible to return the value, because the field is not supported660* or for some other reason, an exception is thrown.661* <p>662* If the field is a {@link ChronoField} then the query is implemented here.663* The {@link #isSupported(TemporalField) supported fields} will return valid664* values based on this date.665* All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.666* <p>667* If the field is not a {@code ChronoField}, then the result of this method668* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}669* passing {@code this} as the argument. Whether the value can be obtained,670* and what the value represents, is determined by the field.671*672* @param field the field to get, not null673* @return the value for the field674* @throws DateTimeException if a value for the field cannot be obtained675* @throws UnsupportedTemporalTypeException if the field is not supported676* @throws ArithmeticException if numeric overflow occurs677*/678@Override679public long getLong(TemporalField field) {680if (field instanceof ChronoField) {681if (field == EPOCH_DAY) {682return toEpochDay();683}684if (field == PROLEPTIC_MONTH) {685return getProlepticMonth();686}687return get0(field);688}689return field.getFrom(this);690}691692private int get0(TemporalField field) {693switch ((ChronoField) field) {694case DAY_OF_WEEK: return getDayOfWeek().getValue();695case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((day - 1) % 7) + 1;696case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1;697case DAY_OF_MONTH: return day;698case DAY_OF_YEAR: return getDayOfYear();699case EPOCH_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'EpochDay' for get() method, use getLong() instead");700case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1;701case ALIGNED_WEEK_OF_YEAR: return ((getDayOfYear() - 1) / 7) + 1;702case MONTH_OF_YEAR: return month;703case PROLEPTIC_MONTH: throw new UnsupportedTemporalTypeException("Invalid field 'ProlepticMonth' for get() method, use getLong() instead");704case YEAR_OF_ERA: return (year >= 1 ? year : 1 - year);705case YEAR: return year;706case ERA: return (year >= 1 ? 1 : 0);707}708throw new UnsupportedTemporalTypeException("Unsupported field: " + field);709}710711private long getProlepticMonth() {712return (year * 12L + month - 1);713}714715//-----------------------------------------------------------------------716/**717* Gets the chronology of this date, which is the ISO calendar system.718* <p>719* The {@code Chronology} represents the calendar system in use.720* The ISO-8601 calendar system is the modern civil calendar system used today721* in most of the world. It is equivalent to the proleptic Gregorian calendar722* system, in which today's rules for leap years are applied for all time.723*724* @return the ISO chronology, not null725*/726@Override727public IsoChronology getChronology() {728return IsoChronology.INSTANCE;729}730731/**732* Gets the era applicable at this date.733* <p>734* The official ISO-8601 standard does not define eras, however {@code IsoChronology} does.735* It defines two eras, 'CE' from year one onwards and 'BCE' from year zero backwards.736* Since dates before the Julian-Gregorian cutover are not in line with history,737* the cutover between 'BCE' and 'CE' is also not aligned with the commonly used738* eras, often referred to using 'BC' and 'AD'.739* <p>740* Users of this class should typically ignore this method as it exists primarily741* to fulfill the {@link ChronoLocalDate} contract where it is necessary to support742* the Japanese calendar system.743*744* @return the IsoEra applicable at this date, not null745*/746@Override // override for Javadoc747public IsoEra getEra() {748return (getYear() >= 1 ? IsoEra.CE : IsoEra.BCE);749}750751/**752* Gets the year field.753* <p>754* This method returns the primitive {@code int} value for the year.755* <p>756* The year returned by this method is proleptic as per {@code get(YEAR)}.757* To obtain the year-of-era, use {@code get(YEAR_OF_ERA)}.758*759* @return the year, from MIN_YEAR to MAX_YEAR760*/761public int getYear() {762return year;763}764765/**766* Gets the month-of-year field from 1 to 12.767* <p>768* This method returns the month as an {@code int} from 1 to 12.769* Application code is frequently clearer if the enum {@link Month}770* is used by calling {@link #getMonth()}.771*772* @return the month-of-year, from 1 to 12773* @see #getMonth()774*/775public int getMonthValue() {776return month;777}778779/**780* Gets the month-of-year field using the {@code Month} enum.781* <p>782* This method returns the enum {@link Month} for the month.783* This avoids confusion as to what {@code int} values mean.784* If you need access to the primitive {@code int} value then the enum785* provides the {@link Month#getValue() int value}.786*787* @return the month-of-year, not null788* @see #getMonthValue()789*/790public Month getMonth() {791return Month.of(month);792}793794/**795* Gets the day-of-month field.796* <p>797* This method returns the primitive {@code int} value for the day-of-month.798*799* @return the day-of-month, from 1 to 31800*/801public int getDayOfMonth() {802return day;803}804805/**806* Gets the day-of-year field.807* <p>808* This method returns the primitive {@code int} value for the day-of-year.809*810* @return the day-of-year, from 1 to 365, or 366 in a leap year811*/812public int getDayOfYear() {813return getMonth().firstDayOfYear(isLeapYear()) + day - 1;814}815816/**817* Gets the day-of-week field, which is an enum {@code DayOfWeek}.818* <p>819* This method returns the enum {@link DayOfWeek} for the day-of-week.820* This avoids confusion as to what {@code int} values mean.821* If you need access to the primitive {@code int} value then the enum822* provides the {@link DayOfWeek#getValue() int value}.823* <p>824* Additional information can be obtained from the {@code DayOfWeek}.825* This includes textual names of the values.826*827* @return the day-of-week, not null828*/829public DayOfWeek getDayOfWeek() {830int dow0 = Math.floorMod(toEpochDay() + 3, 7);831return DayOfWeek.of(dow0 + 1);832}833834//-----------------------------------------------------------------------835/**836* Checks if the year is a leap year, according to the ISO proleptic837* calendar system rules.838* <p>839* This method applies the current rules for leap years across the whole time-line.840* In general, a year is a leap year if it is divisible by four without841* remainder. However, years divisible by 100, are not leap years, with842* the exception of years divisible by 400 which are.843* <p>844* For example, 1904 is a leap year it is divisible by 4.845* 1900 was not a leap year as it is divisible by 100, however 2000 was a846* leap year as it is divisible by 400.847* <p>848* The calculation is proleptic - applying the same rules into the far future and far past.849* This is historically inaccurate, but is correct for the ISO-8601 standard.850*851* @return true if the year is leap, false otherwise852*/853@Override // override for Javadoc and performance854public boolean isLeapYear() {855return IsoChronology.INSTANCE.isLeapYear(year);856}857858/**859* Returns the length of the month represented by this date.860* <p>861* This returns the length of the month in days.862* For example, a date in January would return 31.863*864* @return the length of the month in days865*/866@Override867public int lengthOfMonth() {868switch (month) {869case 2:870return (isLeapYear() ? 29 : 28);871case 4:872case 6:873case 9:874case 11:875return 30;876default:877return 31;878}879}880881/**882* Returns the length of the year represented by this date.883* <p>884* This returns the length of the year in days, either 365 or 366.885*886* @return 366 if the year is leap, 365 otherwise887*/888@Override // override for Javadoc and performance889public int lengthOfYear() {890return (isLeapYear() ? 366 : 365);891}892893//-----------------------------------------------------------------------894/**895* Returns an adjusted copy of this date.896* <p>897* This returns a {@code LocalDate}, based on this one, with the date adjusted.898* The adjustment takes place using the specified adjuster strategy object.899* Read the documentation of the adjuster to understand what adjustment will be made.900* <p>901* A simple adjuster might simply set the one of the fields, such as the year field.902* A more complex adjuster might set the date to the last day of the month.903* <p>904* A selection of common adjustments is provided in905* {@link java.time.temporal.TemporalAdjusters TemporalAdjusters}.906* These include finding the "last day of the month" and "next Wednesday".907* Key date-time classes also implement the {@code TemporalAdjuster} interface,908* such as {@link Month} and {@link java.time.MonthDay MonthDay}.909* The adjuster is responsible for handling special cases, such as the varying910* lengths of month and leap years.911* <p>912* For example this code returns a date on the last day of July:913* <pre>914* import static java.time.Month.*;915* import static java.time.temporal.TemporalAdjusters.*;916*917* result = localDate.with(JULY).with(lastDayOfMonth());918* </pre>919* <p>920* The result of this method is obtained by invoking the921* {@link TemporalAdjuster#adjustInto(Temporal)} method on the922* specified adjuster passing {@code this} as the argument.923* <p>924* This instance is immutable and unaffected by this method call.925*926* @param adjuster the adjuster to use, not null927* @return a {@code LocalDate} based on {@code this} with the adjustment made, not null928* @throws DateTimeException if the adjustment cannot be made929* @throws ArithmeticException if numeric overflow occurs930*/931@Override932public LocalDate with(TemporalAdjuster adjuster) {933// optimizations934if (adjuster instanceof LocalDate) {935return (LocalDate) adjuster;936}937return (LocalDate) adjuster.adjustInto(this);938}939940/**941* Returns a copy of this date with the specified field set to a new value.942* <p>943* This returns a {@code LocalDate}, based on this one, with the value944* for the specified field changed.945* This can be used to change any supported field, such as the year, month or day-of-month.946* If it is not possible to set the value, because the field is not supported or for947* some other reason, an exception is thrown.948* <p>949* In some cases, changing the specified field can cause the resulting date to become invalid,950* such as changing the month from 31st January to February would make the day-of-month invalid.951* In cases like this, the field is responsible for resolving the date. Typically it will choose952* the previous valid date, which would be the last valid day of February in this example.953* <p>954* If the field is a {@link ChronoField} then the adjustment is implemented here.955* The supported fields behave as follows:956* <ul>957* <li>{@code DAY_OF_WEEK} -958* Returns a {@code LocalDate} with the specified day-of-week.959* The date is adjusted up to 6 days forward or backward within the boundary960* of a Monday to Sunday week.961* <li>{@code ALIGNED_DAY_OF_WEEK_IN_MONTH} -962* Returns a {@code LocalDate} with the specified aligned-day-of-week.963* The date is adjusted to the specified month-based aligned-day-of-week.964* Aligned weeks are counted such that the first week of a given month starts965* on the first day of that month.966* This may cause the date to be moved up to 6 days into the following month.967* <li>{@code ALIGNED_DAY_OF_WEEK_IN_YEAR} -968* Returns a {@code LocalDate} with the specified aligned-day-of-week.969* The date is adjusted to the specified year-based aligned-day-of-week.970* Aligned weeks are counted such that the first week of a given year starts971* on the first day of that year.972* This may cause the date to be moved up to 6 days into the following year.973* <li>{@code DAY_OF_MONTH} -974* Returns a {@code LocalDate} with the specified day-of-month.975* The month and year will be unchanged. If the day-of-month is invalid for the976* year and month, then a {@code DateTimeException} is thrown.977* <li>{@code DAY_OF_YEAR} -978* Returns a {@code LocalDate} with the specified day-of-year.979* The year will be unchanged. If the day-of-year is invalid for the980* year, then a {@code DateTimeException} is thrown.981* <li>{@code EPOCH_DAY} -982* Returns a {@code LocalDate} with the specified epoch-day.983* This completely replaces the date and is equivalent to {@link #ofEpochDay(long)}.984* <li>{@code ALIGNED_WEEK_OF_MONTH} -985* Returns a {@code LocalDate} with the specified aligned-week-of-month.986* Aligned weeks are counted such that the first week of a given month starts987* on the first day of that month.988* This adjustment moves the date in whole week chunks to match the specified week.989* The result will have the same day-of-week as this date.990* This may cause the date to be moved into the following month.991* <li>{@code ALIGNED_WEEK_OF_YEAR} -992* Returns a {@code LocalDate} with the specified aligned-week-of-year.993* Aligned weeks are counted such that the first week of a given year starts994* on the first day of that year.995* This adjustment moves the date in whole week chunks to match the specified week.996* The result will have the same day-of-week as this date.997* This may cause the date to be moved into the following year.998* <li>{@code MONTH_OF_YEAR} -999* Returns a {@code LocalDate} with the specified month-of-year.1000* The year will be unchanged. The day-of-month will also be unchanged,1001* unless it would be invalid for the new month and year. In that case, the1002* day-of-month is adjusted to the maximum valid value for the new month and year.1003* <li>{@code PROLEPTIC_MONTH} -1004* Returns a {@code LocalDate} with the specified proleptic-month.1005* The day-of-month will be unchanged, unless it would be invalid for the new month1006* and year. In that case, the day-of-month is adjusted to the maximum valid value1007* for the new month and year.1008* <li>{@code YEAR_OF_ERA} -1009* Returns a {@code LocalDate} with the specified year-of-era.1010* The era and month will be unchanged. The day-of-month will also be unchanged,1011* unless it would be invalid for the new month and year. In that case, the1012* day-of-month is adjusted to the maximum valid value for the new month and year.1013* <li>{@code YEAR} -1014* Returns a {@code LocalDate} with the specified year.1015* The month will be unchanged. The day-of-month will also be unchanged,1016* unless it would be invalid for the new month and year. In that case, the1017* day-of-month is adjusted to the maximum valid value for the new month and year.1018* <li>{@code ERA} -1019* Returns a {@code LocalDate} with the specified era.1020* The year-of-era and month will be unchanged. The day-of-month will also be unchanged,1021* unless it would be invalid for the new month and year. In that case, the1022* day-of-month is adjusted to the maximum valid value for the new month and year.1023* </ul>1024* <p>1025* In all cases, if the new value is outside the valid range of values for the field1026* then a {@code DateTimeException} will be thrown.1027* <p>1028* All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.1029* <p>1030* If the field is not a {@code ChronoField}, then the result of this method1031* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}1032* passing {@code this} as the argument. In this case, the field determines1033* whether and how to adjust the instant.1034* <p>1035* This instance is immutable and unaffected by this method call.1036*1037* @param field the field to set in the result, not null1038* @param newValue the new value of the field in the result1039* @return a {@code LocalDate} based on {@code this} with the specified field set, not null1040* @throws DateTimeException if the field cannot be set1041* @throws UnsupportedTemporalTypeException if the field is not supported1042* @throws ArithmeticException if numeric overflow occurs1043*/1044@Override1045public LocalDate with(TemporalField field, long newValue) {1046if (field instanceof ChronoField chronoField) {1047chronoField.checkValidValue(newValue);1048switch (chronoField) {1049case DAY_OF_WEEK: return plusDays(newValue - getDayOfWeek().getValue());1050case ALIGNED_DAY_OF_WEEK_IN_MONTH: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_MONTH));1051case ALIGNED_DAY_OF_WEEK_IN_YEAR: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_YEAR));1052case DAY_OF_MONTH: return withDayOfMonth((int) newValue);1053case DAY_OF_YEAR: return withDayOfYear((int) newValue);1054case EPOCH_DAY: return LocalDate.ofEpochDay(newValue);1055case ALIGNED_WEEK_OF_MONTH: return plusWeeks(newValue - getLong(ALIGNED_WEEK_OF_MONTH));1056case ALIGNED_WEEK_OF_YEAR: return plusWeeks(newValue - getLong(ALIGNED_WEEK_OF_YEAR));1057case MONTH_OF_YEAR: return withMonth((int) newValue);1058case PROLEPTIC_MONTH: return plusMonths(newValue - getProlepticMonth());1059case YEAR_OF_ERA: return withYear((int) (year >= 1 ? newValue : 1 - newValue));1060case YEAR: return withYear((int) newValue);1061case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year));1062}1063throw new UnsupportedTemporalTypeException("Unsupported field: " + field);1064}1065return field.adjustInto(this, newValue);1066}10671068//-----------------------------------------------------------------------1069/**1070* Returns a copy of this {@code LocalDate} with the year altered.1071* <p>1072* If the day-of-month is invalid for the year, it will be changed to the last valid day of the month.1073* <p>1074* This instance is immutable and unaffected by this method call.1075*1076* @param year the year to set in the result, from MIN_YEAR to MAX_YEAR1077* @return a {@code LocalDate} based on this date with the requested year, not null1078* @throws DateTimeException if the year value is invalid1079*/1080public LocalDate withYear(int year) {1081if (this.year == year) {1082return this;1083}1084YEAR.checkValidValue(year);1085return resolvePreviousValid(year, month, day);1086}10871088/**1089* Returns a copy of this {@code LocalDate} with the month-of-year altered.1090* <p>1091* If the day-of-month is invalid for the year, it will be changed to the last valid day of the month.1092* <p>1093* This instance is immutable and unaffected by this method call.1094*1095* @param month the month-of-year to set in the result, from 1 (January) to 12 (December)1096* @return a {@code LocalDate} based on this date with the requested month, not null1097* @throws DateTimeException if the month-of-year value is invalid1098*/1099public LocalDate withMonth(int month) {1100if (this.month == month) {1101return this;1102}1103MONTH_OF_YEAR.checkValidValue(month);1104return resolvePreviousValid(year, month, day);1105}11061107/**1108* Returns a copy of this {@code LocalDate} with the day-of-month altered.1109* <p>1110* If the resulting date is invalid, an exception is thrown.1111* <p>1112* This instance is immutable and unaffected by this method call.1113*1114* @param dayOfMonth the day-of-month to set in the result, from 1 to 28-311115* @return a {@code LocalDate} based on this date with the requested day, not null1116* @throws DateTimeException if the day-of-month value is invalid,1117* or if the day-of-month is invalid for the month-year1118*/1119public LocalDate withDayOfMonth(int dayOfMonth) {1120if (this.day == dayOfMonth) {1121return this;1122}1123return of(year, month, dayOfMonth);1124}11251126/**1127* Returns a copy of this {@code LocalDate} with the day-of-year altered.1128* <p>1129* If the resulting date is invalid, an exception is thrown.1130* <p>1131* This instance is immutable and unaffected by this method call.1132*1133* @param dayOfYear the day-of-year to set in the result, from 1 to 365-3661134* @return a {@code LocalDate} based on this date with the requested day, not null1135* @throws DateTimeException if the day-of-year value is invalid,1136* or if the day-of-year is invalid for the year1137*/1138public LocalDate withDayOfYear(int dayOfYear) {1139if (this.getDayOfYear() == dayOfYear) {1140return this;1141}1142return ofYearDay(year, dayOfYear);1143}11441145//-----------------------------------------------------------------------1146/**1147* Returns a copy of this date with the specified amount added.1148* <p>1149* This returns a {@code LocalDate}, based on this one, with the specified amount added.1150* The amount is typically {@link Period} but may be any other type implementing1151* the {@link TemporalAmount} interface.1152* <p>1153* The calculation is delegated to the amount object by calling1154* {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free1155* to implement the addition in any way it wishes, however it typically1156* calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation1157* of the amount implementation to determine if it can be successfully added.1158* <p>1159* This instance is immutable and unaffected by this method call.1160*1161* @param amountToAdd the amount to add, not null1162* @return a {@code LocalDate} based on this date with the addition made, not null1163* @throws DateTimeException if the addition cannot be made1164* @throws ArithmeticException if numeric overflow occurs1165*/1166@Override1167public LocalDate plus(TemporalAmount amountToAdd) {1168if (amountToAdd instanceof Period periodToAdd) {1169return plusMonths(periodToAdd.toTotalMonths()).plusDays(periodToAdd.getDays());1170}1171Objects.requireNonNull(amountToAdd, "amountToAdd");1172return (LocalDate) amountToAdd.addTo(this);1173}11741175/**1176* Returns a copy of this date with the specified amount added.1177* <p>1178* This returns a {@code LocalDate}, based on this one, with the amount1179* in terms of the unit added. If it is not possible to add the amount, because the1180* unit is not supported or for some other reason, an exception is thrown.1181* <p>1182* In some cases, adding the amount can cause the resulting date to become invalid.1183* For example, adding one month to 31st January would result in 31st February.1184* In cases like this, the unit is responsible for resolving the date.1185* Typically it will choose the previous valid date, which would be the last valid1186* day of February in this example.1187* <p>1188* If the field is a {@link ChronoUnit} then the addition is implemented here.1189* The supported fields behave as follows:1190* <ul>1191* <li>{@code DAYS} -1192* Returns a {@code LocalDate} with the specified number of days added.1193* This is equivalent to {@link #plusDays(long)}.1194* <li>{@code WEEKS} -1195* Returns a {@code LocalDate} with the specified number of weeks added.1196* This is equivalent to {@link #plusWeeks(long)} and uses a 7 day week.1197* <li>{@code MONTHS} -1198* Returns a {@code LocalDate} with the specified number of months added.1199* This is equivalent to {@link #plusMonths(long)}.1200* The day-of-month will be unchanged unless it would be invalid for the new1201* month and year. In that case, the day-of-month is adjusted to the maximum1202* valid value for the new month and year.1203* <li>{@code YEARS} -1204* Returns a {@code LocalDate} with the specified number of years added.1205* This is equivalent to {@link #plusYears(long)}.1206* The day-of-month will be unchanged unless it would be invalid for the new1207* month and year. In that case, the day-of-month is adjusted to the maximum1208* valid value for the new month and year.1209* <li>{@code DECADES} -1210* Returns a {@code LocalDate} with the specified number of decades added.1211* This is equivalent to calling {@link #plusYears(long)} with the amount1212* multiplied by 10.1213* The day-of-month will be unchanged unless it would be invalid for the new1214* month and year. In that case, the day-of-month is adjusted to the maximum1215* valid value for the new month and year.1216* <li>{@code CENTURIES} -1217* Returns a {@code LocalDate} with the specified number of centuries added.1218* This is equivalent to calling {@link #plusYears(long)} with the amount1219* multiplied by 100.1220* The day-of-month will be unchanged unless it would be invalid for the new1221* month and year. In that case, the day-of-month is adjusted to the maximum1222* valid value for the new month and year.1223* <li>{@code MILLENNIA} -1224* Returns a {@code LocalDate} with the specified number of millennia added.1225* This is equivalent to calling {@link #plusYears(long)} with the amount1226* multiplied by 1,000.1227* The day-of-month will be unchanged unless it would be invalid for the new1228* month and year. In that case, the day-of-month is adjusted to the maximum1229* valid value for the new month and year.1230* <li>{@code ERAS} -1231* Returns a {@code LocalDate} with the specified number of eras added.1232* Only two eras are supported so the amount must be one, zero or minus one.1233* If the amount is non-zero then the year is changed such that the year-of-era1234* is unchanged.1235* The day-of-month will be unchanged unless it would be invalid for the new1236* month and year. In that case, the day-of-month is adjusted to the maximum1237* valid value for the new month and year.1238* </ul>1239* <p>1240* All other {@code ChronoUnit} instances will throw an {@code UnsupportedTemporalTypeException}.1241* <p>1242* If the field is not a {@code ChronoUnit}, then the result of this method1243* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}1244* passing {@code this} as the argument. In this case, the unit determines1245* whether and how to perform the addition.1246* <p>1247* This instance is immutable and unaffected by this method call.1248*1249* @param amountToAdd the amount of the unit to add to the result, may be negative1250* @param unit the unit of the amount to add, not null1251* @return a {@code LocalDate} based on this date with the specified amount added, not null1252* @throws DateTimeException if the addition cannot be made1253* @throws UnsupportedTemporalTypeException if the unit is not supported1254* @throws ArithmeticException if numeric overflow occurs1255*/1256@Override1257public LocalDate plus(long amountToAdd, TemporalUnit unit) {1258if (unit instanceof ChronoUnit chronoUnit) {1259switch (chronoUnit) {1260case DAYS: return plusDays(amountToAdd);1261case WEEKS: return plusWeeks(amountToAdd);1262case MONTHS: return plusMonths(amountToAdd);1263case YEARS: return plusYears(amountToAdd);1264case DECADES: return plusYears(Math.multiplyExact(amountToAdd, 10));1265case CENTURIES: return plusYears(Math.multiplyExact(amountToAdd, 100));1266case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000));1267case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd));1268}1269throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);1270}1271return unit.addTo(this, amountToAdd);1272}12731274//-----------------------------------------------------------------------1275/**1276* Returns a copy of this {@code LocalDate} with the specified number of years added.1277* <p>1278* This method adds the specified amount to the years field in three steps:1279* <ol>1280* <li>Add the input years to the year field</li>1281* <li>Check if the resulting date would be invalid</li>1282* <li>Adjust the day-of-month to the last valid day if necessary</li>1283* </ol>1284* <p>1285* For example, 2008-02-29 (leap year) plus one year would result in the1286* invalid date 2009-02-29 (standard year). Instead of returning an invalid1287* result, the last valid day of the month, 2009-02-28, is selected instead.1288* <p>1289* This instance is immutable and unaffected by this method call.1290*1291* @param yearsToAdd the years to add, may be negative1292* @return a {@code LocalDate} based on this date with the years added, not null1293* @throws DateTimeException if the result exceeds the supported date range1294*/1295public LocalDate plusYears(long yearsToAdd) {1296if (yearsToAdd == 0) {1297return this;1298}1299int newYear = YEAR.checkValidIntValue(year + yearsToAdd); // safe overflow1300return resolvePreviousValid(newYear, month, day);1301}13021303/**1304* Returns a copy of this {@code LocalDate} with the specified number of months added.1305* <p>1306* This method adds the specified amount to the months field in three steps:1307* <ol>1308* <li>Add the input months to the month-of-year field</li>1309* <li>Check if the resulting date would be invalid</li>1310* <li>Adjust the day-of-month to the last valid day if necessary</li>1311* </ol>1312* <p>1313* For example, 2007-03-31 plus one month would result in the invalid date1314* 2007-04-31. Instead of returning an invalid result, the last valid day1315* of the month, 2007-04-30, is selected instead.1316* <p>1317* This instance is immutable and unaffected by this method call.1318*1319* @param monthsToAdd the months to add, may be negative1320* @return a {@code LocalDate} based on this date with the months added, not null1321* @throws DateTimeException if the result exceeds the supported date range1322*/1323public LocalDate plusMonths(long monthsToAdd) {1324if (monthsToAdd == 0) {1325return this;1326}1327long monthCount = year * 12L + (month - 1);1328long calcMonths = monthCount + monthsToAdd; // safe overflow1329int newYear = YEAR.checkValidIntValue(Math.floorDiv(calcMonths, 12));1330int newMonth = Math.floorMod(calcMonths, 12) + 1;1331return resolvePreviousValid(newYear, newMonth, day);1332}13331334/**1335* Returns a copy of this {@code LocalDate} with the specified number of weeks added.1336* <p>1337* This method adds the specified amount in weeks to the days field incrementing1338* the month and year fields as necessary to ensure the result remains valid.1339* The result is only invalid if the maximum/minimum year is exceeded.1340* <p>1341* For example, 2008-12-31 plus one week would result in 2009-01-07.1342* <p>1343* This instance is immutable and unaffected by this method call.1344*1345* @param weeksToAdd the weeks to add, may be negative1346* @return a {@code LocalDate} based on this date with the weeks added, not null1347* @throws DateTimeException if the result exceeds the supported date range1348*/1349public LocalDate plusWeeks(long weeksToAdd) {1350return plusDays(Math.multiplyExact(weeksToAdd, 7));1351}13521353/**1354* Returns a copy of this {@code LocalDate} with the specified number of days added.1355* <p>1356* This method adds the specified amount to the days field incrementing the1357* month and year fields as necessary to ensure the result remains valid.1358* The result is only invalid if the maximum/minimum year is exceeded.1359* <p>1360* For example, 2008-12-31 plus one day would result in 2009-01-01.1361* <p>1362* This instance is immutable and unaffected by this method call.1363*1364* @param daysToAdd the days to add, may be negative1365* @return a {@code LocalDate} based on this date with the days added, not null1366* @throws DateTimeException if the result exceeds the supported date range1367*/1368public LocalDate plusDays(long daysToAdd) {1369if (daysToAdd == 0) {1370return this;1371}1372long dom = day + daysToAdd;1373if (dom > 0) {1374if (dom <= 28) {1375return new LocalDate(year, month, (int) dom);1376} else if (dom <= 59) { // 59th Jan is 28th Feb, 59th Feb is 31st Mar1377long monthLen = lengthOfMonth();1378if (dom <= monthLen) {1379return new LocalDate(year, month, (int) dom);1380} else if (month < 12) {1381return new LocalDate(year, month + 1, (int) (dom - monthLen));1382} else {1383YEAR.checkValidValue(year + 1);1384return new LocalDate(year + 1, 1, (int) (dom - monthLen));1385}1386}1387}13881389long mjDay = Math.addExact(toEpochDay(), daysToAdd);1390return LocalDate.ofEpochDay(mjDay);1391}13921393//-----------------------------------------------------------------------1394/**1395* Returns a copy of this date with the specified amount subtracted.1396* <p>1397* This returns a {@code LocalDate}, based on this one, with the specified amount subtracted.1398* The amount is typically {@link Period} but may be any other type implementing1399* the {@link TemporalAmount} interface.1400* <p>1401* The calculation is delegated to the amount object by calling1402* {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free1403* to implement the subtraction in any way it wishes, however it typically1404* calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation1405* of the amount implementation to determine if it can be successfully subtracted.1406* <p>1407* This instance is immutable and unaffected by this method call.1408*1409* @param amountToSubtract the amount to subtract, not null1410* @return a {@code LocalDate} based on this date with the subtraction made, not null1411* @throws DateTimeException if the subtraction cannot be made1412* @throws ArithmeticException if numeric overflow occurs1413*/1414@Override1415public LocalDate minus(TemporalAmount amountToSubtract) {1416if (amountToSubtract instanceof Period periodToSubtract) {1417return minusMonths(periodToSubtract.toTotalMonths()).minusDays(periodToSubtract.getDays());1418}1419Objects.requireNonNull(amountToSubtract, "amountToSubtract");1420return (LocalDate) amountToSubtract.subtractFrom(this);1421}14221423/**1424* Returns a copy of this date with the specified amount subtracted.1425* <p>1426* This returns a {@code LocalDate}, based on this one, with the amount1427* in terms of the unit subtracted. If it is not possible to subtract the amount,1428* because the unit is not supported or for some other reason, an exception is thrown.1429* <p>1430* This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.1431* See that method for a full description of how addition, and thus subtraction, works.1432* <p>1433* This instance is immutable and unaffected by this method call.1434*1435* @param amountToSubtract the amount of the unit to subtract from the result, may be negative1436* @param unit the unit of the amount to subtract, not null1437* @return a {@code LocalDate} based on this date with the specified amount subtracted, not null1438* @throws DateTimeException if the subtraction cannot be made1439* @throws UnsupportedTemporalTypeException if the unit is not supported1440* @throws ArithmeticException if numeric overflow occurs1441*/1442@Override1443public LocalDate minus(long amountToSubtract, TemporalUnit unit) {1444return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));1445}14461447//-----------------------------------------------------------------------1448/**1449* Returns a copy of this {@code LocalDate} with the specified number of years subtracted.1450* <p>1451* This method subtracts the specified amount from the years field in three steps:1452* <ol>1453* <li>Subtract the input years from the year field</li>1454* <li>Check if the resulting date would be invalid</li>1455* <li>Adjust the day-of-month to the last valid day if necessary</li>1456* </ol>1457* <p>1458* For example, 2008-02-29 (leap year) minus one year would result in the1459* invalid date 2007-02-29 (standard year). Instead of returning an invalid1460* result, the last valid day of the month, 2007-02-28, is selected instead.1461* <p>1462* This instance is immutable and unaffected by this method call.1463*1464* @param yearsToSubtract the years to subtract, may be negative1465* @return a {@code LocalDate} based on this date with the years subtracted, not null1466* @throws DateTimeException if the result exceeds the supported date range1467*/1468public LocalDate minusYears(long yearsToSubtract) {1469return (yearsToSubtract == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-yearsToSubtract));1470}14711472/**1473* Returns a copy of this {@code LocalDate} with the specified number of months subtracted.1474* <p>1475* This method subtracts the specified amount from the months field in three steps:1476* <ol>1477* <li>Subtract the input months from the month-of-year field</li>1478* <li>Check if the resulting date would be invalid</li>1479* <li>Adjust the day-of-month to the last valid day if necessary</li>1480* </ol>1481* <p>1482* For example, 2007-03-31 minus one month would result in the invalid date1483* 2007-02-31. Instead of returning an invalid result, the last valid day1484* of the month, 2007-02-28, is selected instead.1485* <p>1486* This instance is immutable and unaffected by this method call.1487*1488* @param monthsToSubtract the months to subtract, may be negative1489* @return a {@code LocalDate} based on this date with the months subtracted, not null1490* @throws DateTimeException if the result exceeds the supported date range1491*/1492public LocalDate minusMonths(long monthsToSubtract) {1493return (monthsToSubtract == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-monthsToSubtract));1494}14951496/**1497* Returns a copy of this {@code LocalDate} with the specified number of weeks subtracted.1498* <p>1499* This method subtracts the specified amount in weeks from the days field decrementing1500* the month and year fields as necessary to ensure the result remains valid.1501* The result is only invalid if the maximum/minimum year is exceeded.1502* <p>1503* For example, 2009-01-07 minus one week would result in 2008-12-31.1504* <p>1505* This instance is immutable and unaffected by this method call.1506*1507* @param weeksToSubtract the weeks to subtract, may be negative1508* @return a {@code LocalDate} based on this date with the weeks subtracted, not null1509* @throws DateTimeException if the result exceeds the supported date range1510*/1511public LocalDate minusWeeks(long weeksToSubtract) {1512return (weeksToSubtract == Long.MIN_VALUE ? plusWeeks(Long.MAX_VALUE).plusWeeks(1) : plusWeeks(-weeksToSubtract));1513}15141515/**1516* Returns a copy of this {@code LocalDate} with the specified number of days subtracted.1517* <p>1518* This method subtracts the specified amount from the days field decrementing the1519* month and year fields as necessary to ensure the result remains valid.1520* The result is only invalid if the maximum/minimum year is exceeded.1521* <p>1522* For example, 2009-01-01 minus one day would result in 2008-12-31.1523* <p>1524* This instance is immutable and unaffected by this method call.1525*1526* @param daysToSubtract the days to subtract, may be negative1527* @return a {@code LocalDate} based on this date with the days subtracted, not null1528* @throws DateTimeException if the result exceeds the supported date range1529*/1530public LocalDate minusDays(long daysToSubtract) {1531return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));1532}15331534//-----------------------------------------------------------------------1535/**1536* Queries this date using the specified query.1537* <p>1538* This queries this date using the specified query strategy object.1539* The {@code TemporalQuery} object defines the logic to be used to1540* obtain the result. Read the documentation of the query to understand1541* what the result of this method will be.1542* <p>1543* The result of this method is obtained by invoking the1544* {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the1545* specified query passing {@code this} as the argument.1546*1547* @param <R> the type of the result1548* @param query the query to invoke, not null1549* @return the query result, null may be returned (defined by the query)1550* @throws DateTimeException if unable to query (defined by the query)1551* @throws ArithmeticException if numeric overflow occurs (defined by the query)1552*/1553@SuppressWarnings("unchecked")1554@Override1555public <R> R query(TemporalQuery<R> query) {1556if (query == TemporalQueries.localDate()) {1557return (R) this;1558}1559return ChronoLocalDate.super.query(query);1560}15611562/**1563* Adjusts the specified temporal object to have the same date as this object.1564* <p>1565* This returns a temporal object of the same observable type as the input1566* with the date changed to be the same as this.1567* <p>1568* The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}1569* passing {@link ChronoField#EPOCH_DAY} as the field.1570* <p>1571* In most cases, it is clearer to reverse the calling pattern by using1572* {@link Temporal#with(TemporalAdjuster)}:1573* <pre>1574* // these two lines are equivalent, but the second approach is recommended1575* temporal = thisLocalDate.adjustInto(temporal);1576* temporal = temporal.with(thisLocalDate);1577* </pre>1578* <p>1579* This instance is immutable and unaffected by this method call.1580*1581* @param temporal the target object to be adjusted, not null1582* @return the adjusted object, not null1583* @throws DateTimeException if unable to make the adjustment1584* @throws ArithmeticException if numeric overflow occurs1585*/1586@Override // override for Javadoc1587public Temporal adjustInto(Temporal temporal) {1588return ChronoLocalDate.super.adjustInto(temporal);1589}15901591/**1592* Calculates the amount of time until another date in terms of the specified unit.1593* <p>1594* This calculates the amount of time between two {@code LocalDate}1595* objects in terms of a single {@code TemporalUnit}.1596* The start and end points are {@code this} and the specified date.1597* The result will be negative if the end is before the start.1598* The {@code Temporal} passed to this method is converted to a1599* {@code LocalDate} using {@link #from(TemporalAccessor)}.1600* For example, the amount in days between two dates can be calculated1601* using {@code startDate.until(endDate, DAYS)}.1602* <p>1603* The calculation returns a whole number, representing the number of1604* complete units between the two dates.1605* For example, the amount in months between 2012-06-15 and 2012-08-141606* will only be one month as it is one day short of two months.1607* <p>1608* There are two equivalent ways of using this method.1609* The first is to invoke this method.1610* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:1611* <pre>1612* // these two lines are equivalent1613* amount = start.until(end, MONTHS);1614* amount = MONTHS.between(start, end);1615* </pre>1616* The choice should be made based on which makes the code more readable.1617* <p>1618* The calculation is implemented in this method for {@link ChronoUnit}.1619* The units {@code DAYS}, {@code WEEKS}, {@code MONTHS}, {@code YEARS},1620* {@code DECADES}, {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS}1621* are supported. Other {@code ChronoUnit} values will throw an exception.1622* <p>1623* If the unit is not a {@code ChronoUnit}, then the result of this method1624* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}1625* passing {@code this} as the first argument and the converted input temporal1626* as the second argument.1627* <p>1628* This instance is immutable and unaffected by this method call.1629*1630* @param endExclusive the end date, exclusive, which is converted to a {@code LocalDate}, not null1631* @param unit the unit to measure the amount in, not null1632* @return the amount of time between this date and the end date1633* @throws DateTimeException if the amount cannot be calculated, or the end1634* temporal cannot be converted to a {@code LocalDate}1635* @throws UnsupportedTemporalTypeException if the unit is not supported1636* @throws ArithmeticException if numeric overflow occurs1637*/1638@Override1639public long until(Temporal endExclusive, TemporalUnit unit) {1640LocalDate end = LocalDate.from(endExclusive);1641if (unit instanceof ChronoUnit) {1642switch ((ChronoUnit) unit) {1643case DAYS: return daysUntil(end);1644case WEEKS: return daysUntil(end) / 7;1645case MONTHS: return monthsUntil(end);1646case YEARS: return monthsUntil(end) / 12;1647case DECADES: return monthsUntil(end) / 120;1648case CENTURIES: return monthsUntil(end) / 1200;1649case MILLENNIA: return monthsUntil(end) / 12000;1650case ERAS: return end.getLong(ERA) - getLong(ERA);1651}1652throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);1653}1654return unit.between(this, end);1655}16561657long daysUntil(LocalDate end) {1658return end.toEpochDay() - toEpochDay(); // no overflow1659}16601661private long monthsUntil(LocalDate end) {1662long packed1 = getProlepticMonth() * 32L + getDayOfMonth(); // no overflow1663long packed2 = end.getProlepticMonth() * 32L + end.getDayOfMonth(); // no overflow1664return (packed2 - packed1) / 32;1665}16661667/**1668* Calculates the period between this date and another date as a {@code Period}.1669* <p>1670* This calculates the period between two dates in terms of years, months and days.1671* The start and end points are {@code this} and the specified date.1672* The result will be negative if the end is before the start.1673* The negative sign will be the same in each of year, month and day.1674* <p>1675* The calculation is performed using the ISO calendar system.1676* If necessary, the input date will be converted to ISO.1677* <p>1678* The start date is included, but the end date is not.1679* The period is calculated by removing complete months, then calculating1680* the remaining number of days, adjusting to ensure that both have the same sign.1681* The number of months is then normalized into years and months based on a 12 month year.1682* A month is considered to be complete if the end day-of-month is greater1683* than or equal to the start day-of-month.1684* For example, from {@code 2010-01-15} to {@code 2011-03-18} is "1 year, 2 months and 3 days".1685* <p>1686* There are two equivalent ways of using this method.1687* The first is to invoke this method.1688* The second is to use {@link Period#between(LocalDate, LocalDate)}:1689* <pre>1690* // these two lines are equivalent1691* period = start.until(end);1692* period = Period.between(start, end);1693* </pre>1694* The choice should be made based on which makes the code more readable.1695*1696* @param endDateExclusive the end date, exclusive, which may be in any chronology, not null1697* @return the period between this date and the end date, not null1698*/1699@Override1700public Period until(ChronoLocalDate endDateExclusive) {1701LocalDate end = LocalDate.from(endDateExclusive);1702long totalMonths = end.getProlepticMonth() - this.getProlepticMonth(); // safe1703int days = end.day - this.day;1704if (totalMonths > 0 && days < 0) {1705totalMonths--;1706LocalDate calcDate = this.plusMonths(totalMonths);1707days = (int) (end.toEpochDay() - calcDate.toEpochDay()); // safe1708} else if (totalMonths < 0 && days > 0) {1709totalMonths++;1710days -= end.lengthOfMonth();1711}1712long years = totalMonths / 12; // safe1713int months = (int) (totalMonths % 12); // safe1714return Period.of(Math.toIntExact(years), months, days);1715}17161717/**1718* Returns a sequential ordered stream of dates. The returned stream starts from this date1719* (inclusive) and goes to {@code endExclusive} (exclusive) by an incremental step of 1 day.1720* <p>1721* This method is equivalent to {@code datesUntil(endExclusive, Period.ofDays(1))}.1722*1723* @param endExclusive the end date, exclusive, not null1724* @return a sequential {@code Stream} for the range of {@code LocalDate} values1725* @throws IllegalArgumentException if end date is before this date1726* @since 91727*/1728public Stream<LocalDate> datesUntil(LocalDate endExclusive) {1729long end = endExclusive.toEpochDay();1730long start = toEpochDay();1731if (end < start) {1732throw new IllegalArgumentException(endExclusive + " < " + this);1733}1734return LongStream.range(start, end).mapToObj(LocalDate::ofEpochDay);1735}17361737/**1738* Returns a sequential ordered stream of dates by given incremental step. The returned stream1739* starts from this date (inclusive) and goes to {@code endExclusive} (exclusive).1740* <p>1741* The n-th date which appears in the stream is equal to {@code this.plus(step.multipliedBy(n))}1742* (but the result of step multiplication never overflows). For example, if this date is1743* {@code 2015-01-31}, the end date is {@code 2015-05-01} and the step is 1 month, then the1744* stream contains {@code 2015-01-31}, {@code 2015-02-28}, {@code 2015-03-31}, and1745* {@code 2015-04-30}.1746*1747* @param endExclusive the end date, exclusive, not null1748* @param step the non-zero, non-negative {@code Period} which represents the step.1749* @return a sequential {@code Stream} for the range of {@code LocalDate} values1750* @throws IllegalArgumentException if step is zero, or {@code step.getDays()} and1751* {@code step.toTotalMonths()} have opposite sign, or end date is before this date1752* and step is positive, or end date is after this date and step is negative1753* @since 91754*/1755public Stream<LocalDate> datesUntil(LocalDate endExclusive, Period step) {1756if (step.isZero()) {1757throw new IllegalArgumentException("step is zero");1758}1759long end = endExclusive.toEpochDay();1760long start = toEpochDay();1761long until = end - start;1762long months = step.toTotalMonths();1763long days = step.getDays();1764if ((months < 0 && days > 0) || (months > 0 && days < 0)) {1765throw new IllegalArgumentException("period months and days are of opposite sign");1766}1767if (until == 0) {1768return Stream.empty();1769}1770int sign = months > 0 || days > 0 ? 1 : -1;1771if (sign < 0 ^ until < 0) {1772throw new IllegalArgumentException(endExclusive + (sign < 0 ? " > " : " < ") + this);1773}1774if (months == 0) {1775long steps = (until - sign) / days; // non-negative1776return LongStream.rangeClosed(0, steps).mapToObj(1777n -> LocalDate.ofEpochDay(start + n * days));1778}1779// 48699/1600 = 365.2425/12, no overflow, non-negative result1780long steps = until * 1600 / (months * 48699 + days * 1600) + 1;1781long addMonths = months * steps;1782long addDays = days * steps;1783long maxAddMonths = months > 0 ? MAX.getProlepticMonth() - getProlepticMonth()1784: getProlepticMonth() - MIN.getProlepticMonth();1785// adjust steps estimation1786if (addMonths * sign > maxAddMonths1787|| (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) {1788steps--;1789addMonths -= months;1790addDays -= days;1791if (addMonths * sign > maxAddMonths1792|| (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) {1793steps--;1794}1795}1796return LongStream.rangeClosed(0, steps).mapToObj(1797n -> this.plusMonths(months * n).plusDays(days * n));1798}17991800/**1801* Formats this date using the specified formatter.1802* <p>1803* This date will be passed to the formatter to produce a string.1804*1805* @param formatter the formatter to use, not null1806* @return the formatted date string, not null1807* @throws DateTimeException if an error occurs during printing1808*/1809@Override // override for Javadoc and performance1810public String format(DateTimeFormatter formatter) {1811Objects.requireNonNull(formatter, "formatter");1812return formatter.format(this);1813}18141815//-----------------------------------------------------------------------1816/**1817* Combines this date with a time to create a {@code LocalDateTime}.1818* <p>1819* This returns a {@code LocalDateTime} formed from this date at the specified time.1820* All possible combinations of date and time are valid.1821*1822* @param time the time to combine with, not null1823* @return the local date-time formed from this date and the specified time, not null1824*/1825@Override1826public LocalDateTime atTime(LocalTime time) {1827return LocalDateTime.of(this, time);1828}18291830/**1831* Combines this date with a time to create a {@code LocalDateTime}.1832* <p>1833* This returns a {@code LocalDateTime} formed from this date at the1834* specified hour and minute.1835* The seconds and nanosecond fields will be set to zero.1836* The individual time fields must be within their valid range.1837* All possible combinations of date and time are valid.1838*1839* @param hour the hour-of-day to use, from 0 to 231840* @param minute the minute-of-hour to use, from 0 to 591841* @return the local date-time formed from this date and the specified time, not null1842* @throws DateTimeException if the value of any field is out of range1843*/1844public LocalDateTime atTime(int hour, int minute) {1845return atTime(LocalTime.of(hour, minute));1846}18471848/**1849* Combines this date with a time to create a {@code LocalDateTime}.1850* <p>1851* This returns a {@code LocalDateTime} formed from this date at the1852* specified hour, minute and second.1853* The nanosecond field will be set to zero.1854* The individual time fields must be within their valid range.1855* All possible combinations of date and time are valid.1856*1857* @param hour the hour-of-day to use, from 0 to 231858* @param minute the minute-of-hour to use, from 0 to 591859* @param second the second-of-minute to represent, from 0 to 591860* @return the local date-time formed from this date and the specified time, not null1861* @throws DateTimeException if the value of any field is out of range1862*/1863public LocalDateTime atTime(int hour, int minute, int second) {1864return atTime(LocalTime.of(hour, minute, second));1865}18661867/**1868* Combines this date with a time to create a {@code LocalDateTime}.1869* <p>1870* This returns a {@code LocalDateTime} formed from this date at the1871* specified hour, minute, second and nanosecond.1872* The individual time fields must be within their valid range.1873* All possible combinations of date and time are valid.1874*1875* @param hour the hour-of-day to use, from 0 to 231876* @param minute the minute-of-hour to use, from 0 to 591877* @param second the second-of-minute to represent, from 0 to 591878* @param nanoOfSecond the nano-of-second to represent, from 0 to 999,999,9991879* @return the local date-time formed from this date and the specified time, not null1880* @throws DateTimeException if the value of any field is out of range1881*/1882public LocalDateTime atTime(int hour, int minute, int second, int nanoOfSecond) {1883return atTime(LocalTime.of(hour, minute, second, nanoOfSecond));1884}18851886/**1887* Combines this date with an offset time to create an {@code OffsetDateTime}.1888* <p>1889* This returns an {@code OffsetDateTime} formed from this date at the specified time.1890* All possible combinations of date and time are valid.1891*1892* @param time the time to combine with, not null1893* @return the offset date-time formed from this date and the specified time, not null1894*/1895public OffsetDateTime atTime(OffsetTime time) {1896return OffsetDateTime.of(LocalDateTime.of(this, time.toLocalTime()), time.getOffset());1897}18981899/**1900* Combines this date with the time of midnight to create a {@code LocalDateTime}1901* at the start of this date.1902* <p>1903* This returns a {@code LocalDateTime} formed from this date at the time of1904* midnight, 00:00, at the start of this date.1905*1906* @return the local date-time of midnight at the start of this date, not null1907*/1908public LocalDateTime atStartOfDay() {1909return LocalDateTime.of(this, LocalTime.MIDNIGHT);1910}19111912/**1913* Returns a zoned date-time from this date at the earliest valid time according1914* to the rules in the time-zone.1915* <p>1916* Time-zone rules, such as daylight savings, mean that not every local date-time1917* is valid for the specified zone, thus the local date-time may not be midnight.1918* <p>1919* In most cases, there is only one valid offset for a local date-time.1920* In the case of an overlap, there are two valid offsets, and the earlier one is used,1921* corresponding to the first occurrence of midnight on the date.1922* In the case of a gap, the zoned date-time will represent the instant just after the gap.1923* <p>1924* If the zone ID is a {@link ZoneOffset}, then the result always has a time of midnight.1925* <p>1926* To convert to a specific time in a given time-zone call {@link #atTime(LocalTime)}1927* followed by {@link LocalDateTime#atZone(ZoneId)}.1928*1929* @param zone the zone ID to use, not null1930* @return the zoned date-time formed from this date and the earliest valid time for the zone, not null1931*/1932public ZonedDateTime atStartOfDay(ZoneId zone) {1933Objects.requireNonNull(zone, "zone");1934// need to handle case where there is a gap from 11:30 to 00:301935// standard ZDT factory would result in 01:00 rather than 00:301936LocalDateTime ldt = atTime(LocalTime.MIDNIGHT);1937if (!(zone instanceof ZoneOffset)) {1938ZoneRules rules = zone.getRules();1939ZoneOffsetTransition trans = rules.getTransition(ldt);1940if (trans != null && trans.isGap()) {1941ldt = trans.getDateTimeAfter();1942}1943}1944return ZonedDateTime.of(ldt, zone);1945}19461947//-----------------------------------------------------------------------1948@Override1949public long toEpochDay() {1950long y = year;1951long m = month;1952long total = 0;1953total += 365 * y;1954if (y >= 0) {1955total += (y + 3) / 4 - (y + 99) / 100 + (y + 399) / 400;1956} else {1957total -= y / -4 - y / -100 + y / -400;1958}1959total += ((367 * m - 362) / 12);1960total += day - 1;1961if (m > 2) {1962total--;1963if (isLeapYear() == false) {1964total--;1965}1966}1967return total - DAYS_0000_TO_1970;1968}19691970/**1971* Converts this {@code LocalDate} to the number of seconds since the epoch1972* of 1970-01-01T00:00:00Z.1973* <p>1974* This combines this local date with the specified time and1975* offset to calculate the epoch-second value, which is the1976* number of elapsed seconds from 1970-01-01T00:00:00Z.1977* Instants on the time-line after the epoch are positive, earlier1978* are negative.1979*1980* @param time the local time, not null1981* @param offset the zone offset, not null1982* @return the number of seconds since the epoch of 1970-01-01T00:00:00Z, may be negative1983* @since 91984*/1985public long toEpochSecond(LocalTime time, ZoneOffset offset) {1986Objects.requireNonNull(time, "time");1987Objects.requireNonNull(offset, "offset");1988long secs = toEpochDay() * SECONDS_PER_DAY + time.toSecondOfDay();1989secs -= offset.getTotalSeconds();1990return secs;1991}19921993//-----------------------------------------------------------------------1994/**1995* Compares this date to another date.1996* <p>1997* The comparison is primarily based on the date, from earliest to latest.1998* It is "consistent with equals", as defined by {@link Comparable}.1999* <p>2000* If all the dates being compared are instances of {@code LocalDate},2001* then the comparison will be entirely based on the date.2002* If some dates being compared are in different chronologies, then the2003* chronology is also considered, see {@link java.time.chrono.ChronoLocalDate#compareTo}.2004*2005* @param other the other date to compare to, not null2006* @return the comparator value, negative if less, positive if greater2007*/2008@Override // override for Javadoc and performance2009public int compareTo(ChronoLocalDate other) {2010if (other instanceof LocalDate) {2011return compareTo0((LocalDate) other);2012}2013return ChronoLocalDate.super.compareTo(other);2014}20152016int compareTo0(LocalDate otherDate) {2017int cmp = (year - otherDate.year);2018if (cmp == 0) {2019cmp = (month - otherDate.month);2020if (cmp == 0) {2021cmp = (day - otherDate.day);2022}2023}2024return cmp;2025}20262027/**2028* Checks if this date is after the specified date.2029* <p>2030* This checks to see if this date represents a point on the2031* local time-line after the other date.2032* <pre>2033* LocalDate a = LocalDate.of(2012, 6, 30);2034* LocalDate b = LocalDate.of(2012, 7, 1);2035* a.isAfter(b) == false2036* a.isAfter(a) == false2037* b.isAfter(a) == true2038* </pre>2039* <p>2040* This method only considers the position of the two dates on the local time-line.2041* It does not take into account the chronology, or calendar system.2042* This is different from the comparison in {@link #compareTo(ChronoLocalDate)},2043* but is the same approach as {@link ChronoLocalDate#timeLineOrder()}.2044*2045* @param other the other date to compare to, not null2046* @return true if this date is after the specified date2047*/2048@Override // override for Javadoc and performance2049public boolean isAfter(ChronoLocalDate other) {2050if (other instanceof LocalDate) {2051return compareTo0((LocalDate) other) > 0;2052}2053return ChronoLocalDate.super.isAfter(other);2054}20552056/**2057* Checks if this date is before the specified date.2058* <p>2059* This checks to see if this date represents a point on the2060* local time-line before the other date.2061* <pre>2062* LocalDate a = LocalDate.of(2012, 6, 30);2063* LocalDate b = LocalDate.of(2012, 7, 1);2064* a.isBefore(b) == true2065* a.isBefore(a) == false2066* b.isBefore(a) == false2067* </pre>2068* <p>2069* This method only considers the position of the two dates on the local time-line.2070* It does not take into account the chronology, or calendar system.2071* This is different from the comparison in {@link #compareTo(ChronoLocalDate)},2072* but is the same approach as {@link ChronoLocalDate#timeLineOrder()}.2073*2074* @param other the other date to compare to, not null2075* @return true if this date is before the specified date2076*/2077@Override // override for Javadoc and performance2078public boolean isBefore(ChronoLocalDate other) {2079if (other instanceof LocalDate) {2080return compareTo0((LocalDate) other) < 0;2081}2082return ChronoLocalDate.super.isBefore(other);2083}20842085/**2086* Checks if this date is equal to the specified date.2087* <p>2088* This checks to see if this date represents the same point on the2089* local time-line as the other date.2090* <pre>2091* LocalDate a = LocalDate.of(2012, 6, 30);2092* LocalDate b = LocalDate.of(2012, 7, 1);2093* a.isEqual(b) == false2094* a.isEqual(a) == true2095* b.isEqual(a) == false2096* </pre>2097* <p>2098* This method only considers the position of the two dates on the local time-line.2099* It does not take into account the chronology, or calendar system.2100* This is different from the comparison in {@link #compareTo(ChronoLocalDate)}2101* but is the same approach as {@link ChronoLocalDate#timeLineOrder()}.2102*2103* @param other the other date to compare to, not null2104* @return true if this date is equal to the specified date2105*/2106@Override // override for Javadoc and performance2107public boolean isEqual(ChronoLocalDate other) {2108if (other instanceof LocalDate) {2109return compareTo0((LocalDate) other) == 0;2110}2111return ChronoLocalDate.super.isEqual(other);2112}21132114//-----------------------------------------------------------------------2115/**2116* Checks if this date is equal to another date.2117* <p>2118* Compares this {@code LocalDate} with another ensuring that the date is the same.2119* <p>2120* Only objects of type {@code LocalDate} are compared, other types return false.2121* To compare the dates of two {@code TemporalAccessor} instances, including dates2122* in two different chronologies, use {@link ChronoField#EPOCH_DAY} as a comparator.2123*2124* @param obj the object to check, null returns false2125* @return true if this is equal to the other date2126*/2127@Override2128public boolean equals(Object obj) {2129if (this == obj) {2130return true;2131}2132if (obj instanceof LocalDate) {2133return compareTo0((LocalDate) obj) == 0;2134}2135return false;2136}21372138/**2139* A hash code for this date.2140*2141* @return a suitable hash code2142*/2143@Override2144public int hashCode() {2145int yearValue = year;2146int monthValue = month;2147int dayValue = day;2148return (yearValue & 0xFFFFF800) ^ ((yearValue << 11) + (monthValue << 6) + (dayValue));2149}21502151//-----------------------------------------------------------------------2152/**2153* Outputs this date as a {@code String}, such as {@code 2007-12-03}.2154* <p>2155* The output will be in the ISO-8601 format {@code uuuu-MM-dd}.2156*2157* @return a string representation of this date, not null2158*/2159@Override2160public String toString() {2161int yearValue = year;2162int monthValue = month;2163int dayValue = day;2164int absYear = Math.abs(yearValue);2165StringBuilder buf = new StringBuilder(10);2166if (absYear < 1000) {2167if (yearValue < 0) {2168buf.append(yearValue - 10000).deleteCharAt(1);2169} else {2170buf.append(yearValue + 10000).deleteCharAt(0);2171}2172} else {2173if (yearValue > 9999) {2174buf.append('+');2175}2176buf.append(yearValue);2177}2178return buf.append(monthValue < 10 ? "-0" : "-")2179.append(monthValue)2180.append(dayValue < 10 ? "-0" : "-")2181.append(dayValue)2182.toString();2183}21842185//-----------------------------------------------------------------------2186/**2187* Writes the object using a2188* <a href="{@docRoot}/serialized-form.html#java.time.Ser">dedicated serialized form</a>.2189* @serialData2190* <pre>2191* out.writeByte(3); // identifies a LocalDate2192* out.writeInt(year);2193* out.writeByte(month);2194* out.writeByte(day);2195* </pre>2196*2197* @return the instance of {@code Ser}, not null2198*/2199@java.io.Serial2200private Object writeReplace() {2201return new Ser(Ser.LOCAL_DATE_TYPE, this);2202}22032204/**2205* Defend against malicious streams.2206*2207* @param s the stream to read2208* @throws InvalidObjectException always2209*/2210@java.io.Serial2211private void readObject(ObjectInputStream s) throws InvalidObjectException {2212throw new InvalidObjectException("Deserialization via serialization delegate");2213}22142215void writeExternal(DataOutput out) throws IOException {2216out.writeInt(year);2217out.writeByte(month);2218out.writeByte(day);2219}22202221static LocalDate readExternal(DataInput in) throws IOException {2222int year = in.readInt();2223int month = in.readByte();2224int dayOfMonth = in.readByte();2225return LocalDate.of(year, month, dayOfMonth);2226}22272228}222922302231