1 /*
2  * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 /*
27  * This file is available under and governed by the GNU General Public
28  * License version 2 only, as published by the Free Software Foundation.
29  * However, the following notice accompanied the original version of this
30  * file:
31  *
32  * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
33  *
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions are met:
38  *
39  *  * Redistributions of source code must retain the above copyright notice,
40  *    this list of conditions and the following disclaimer.
41  *
42  *  * Redistributions in binary form must reproduce the above copyright notice,
43  *    this list of conditions and the following disclaimer in the documentation
44  *    and/or other materials provided with the distribution.
45  *
46  *  * Neither the name of JSR-310 nor the names of its contributors
47  *    may be used to endorse or promote products derived from this software
48  *    without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
54  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
55  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
56  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
57  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
58  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
59  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  */
62 package java.time;
63 
64 import static java.time.LocalTime.SECONDS_PER_DAY;
65 import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH;
66 import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR;
67 import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH;
68 import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR;
69 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
70 import static java.time.temporal.ChronoField.DAY_OF_YEAR;
71 import static java.time.temporal.ChronoField.EPOCH_DAY;
72 import static java.time.temporal.ChronoField.ERA;
73 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
74 import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
75 import static java.time.temporal.ChronoField.YEAR;
76 
77 import dalvik.annotation.codegen.CovariantReturnType;
78 import java.io.DataInput;
79 import java.io.DataOutput;
80 import java.io.IOException;
81 import java.io.InvalidObjectException;
82 import java.io.ObjectInputStream;
83 import java.io.Serializable;
84 import java.time.chrono.ChronoLocalDate;
85 import java.time.chrono.Era;
86 import java.time.chrono.IsoEra;
87 import java.time.chrono.IsoChronology;
88 import java.time.format.DateTimeFormatter;
89 import java.time.format.DateTimeParseException;
90 import java.time.temporal.ChronoField;
91 import java.time.temporal.ChronoUnit;
92 import java.time.temporal.Temporal;
93 import java.time.temporal.TemporalAccessor;
94 import java.time.temporal.TemporalAdjuster;
95 import java.time.temporal.TemporalAmount;
96 import java.time.temporal.TemporalField;
97 import java.time.temporal.TemporalQueries;
98 import java.time.temporal.TemporalQuery;
99 import java.time.temporal.TemporalUnit;
100 import java.time.temporal.UnsupportedTemporalTypeException;
101 import java.time.temporal.ValueRange;
102 import java.time.zone.ZoneOffsetTransition;
103 import java.time.zone.ZoneRules;
104 import java.util.Objects;
105 import java.util.stream.LongStream;
106 import java.util.stream.Stream;
107 
108 // Android-changed: removed ValueBased paragraph.
109 /**
110  * A date without a time-zone in the ISO-8601 calendar system,
111  * such as {@code 2007-12-03}.
112  * <p>
113  * {@code LocalDate} is an immutable date-time object that represents a date,
114  * often viewed as year-month-day. Other date fields, such as day-of-year,
115  * day-of-week and week-of-year, can also be accessed.
116  * For example, the value "2nd October 2007" can be stored in a {@code LocalDate}.
117  * <p>
118  * This class does not store or represent a time or time-zone.
119  * Instead, it is a description of the date, as used for birthdays.
120  * It cannot represent an instant on the time-line without additional information
121  * such as an offset or time-zone.
122  * <p>
123  * The ISO-8601 calendar system is the modern civil calendar system used today
124  * in most of the world. It is equivalent to the proleptic Gregorian calendar
125  * system, in which today's rules for leap years are applied for all time.
126  * For most applications written today, the ISO-8601 rules are entirely suitable.
127  * However, any application that makes use of historical dates, and requires them
128  * to be accurate will find the ISO-8601 approach unsuitable.
129  *
130  * @implSpec
131  * This class is immutable and thread-safe.
132  *
133  * @since 1.8
134  */
135 public final class LocalDate
136         implements Temporal, TemporalAdjuster, ChronoLocalDate, Serializable {
137 
138     /**
139      * The minimum supported {@code LocalDate}, '-999999999-01-01'.
140      * This could be used by an application as a "far past" date.
141      */
142     public static final LocalDate MIN = LocalDate.of(Year.MIN_VALUE, 1, 1);
143     /**
144      * The maximum supported {@code LocalDate}, '+999999999-12-31'.
145      * This could be used by an application as a "far future" date.
146      */
147     public static final LocalDate MAX = LocalDate.of(Year.MAX_VALUE, 12, 31);
148     /**
149      * The epoch year {@code LocalDate}, '1970-01-01'.
150      */
151     public static final LocalDate EPOCH = LocalDate.of(1970, 1, 1);
152 
153     /**
154      * Serialization version.
155      */
156     @java.io.Serial
157     private static final long serialVersionUID = 2942565459149668126L;
158     /**
159      * The number of days in a 400 year cycle.
160      */
161     private static final int DAYS_PER_CYCLE = 146097;
162     /**
163      * The number of days from year zero to year 1970.
164      * There are five 400 year cycles from year zero to 2000.
165      * There are 7 leap years from 1970 to 2000.
166      */
167     static final long DAYS_0000_TO_1970 = (DAYS_PER_CYCLE * 5L) - (30L * 365L + 7L);
168 
169     /**
170      * The year.
171      */
172     private final int year;
173     /**
174      * The month-of-year.
175      */
176     private final short month;
177     /**
178      * The day-of-month.
179      */
180     private final short day;
181 
182     //-----------------------------------------------------------------------
183     /**
184      * Obtains the current date from the system clock in the default time-zone.
185      * <p>
186      * This will query the {@link Clock#systemDefaultZone() system clock} in the default
187      * time-zone to obtain the current date.
188      * <p>
189      * Using this method will prevent the ability to use an alternate clock for testing
190      * because the clock is hard-coded.
191      *
192      * @return the current date using the system clock and default time-zone, not null
193      */
now()194     public static LocalDate now() {
195         return now(Clock.systemDefaultZone());
196     }
197 
198     /**
199      * Obtains the current date from the system clock in the specified time-zone.
200      * <p>
201      * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date.
202      * Specifying the time-zone avoids dependence on the default time-zone.
203      * <p>
204      * Using this method will prevent the ability to use an alternate clock for testing
205      * because the clock is hard-coded.
206      *
207      * @param zone  the zone ID to use, not null
208      * @return the current date using the system clock, not null
209      */
now(ZoneId zone)210     public static LocalDate now(ZoneId zone) {
211         return now(Clock.system(zone));
212     }
213 
214     /**
215      * Obtains the current date from the specified clock.
216      * <p>
217      * This will query the specified clock to obtain the current date - today.
218      * Using this method allows the use of an alternate clock for testing.
219      * The alternate clock may be introduced using {@link Clock dependency injection}.
220      *
221      * @param clock  the clock to use, not null
222      * @return the current date, not null
223      */
now(Clock clock)224     public static LocalDate now(Clock clock) {
225         Objects.requireNonNull(clock, "clock");
226         final Instant now = clock.instant();  // called once
227         return ofInstant(now, clock.getZone());
228     }
229 
230     //-----------------------------------------------------------------------
231     /**
232      * Obtains an instance of {@code LocalDate} from a year, month and day.
233      * <p>
234      * This returns a {@code LocalDate} with the specified year, month and day-of-month.
235      * The day must be valid for the year and month, otherwise an exception will be thrown.
236      *
237      * @param year  the year to represent, from MIN_YEAR to MAX_YEAR
238      * @param month  the month-of-year to represent, not null
239      * @param dayOfMonth  the day-of-month to represent, from 1 to 31
240      * @return the local date, not null
241      * @throws DateTimeException if the value of any field is out of range,
242      *  or if the day-of-month is invalid for the month-year
243      */
of(int year, Month month, int dayOfMonth)244     public static LocalDate of(int year, Month month, int dayOfMonth) {
245         YEAR.checkValidValue(year);
246         Objects.requireNonNull(month, "month");
247         DAY_OF_MONTH.checkValidValue(dayOfMonth);
248         return create(year, month.getValue(), dayOfMonth);
249     }
250 
251     /**
252      * Obtains an instance of {@code LocalDate} from a year, month and day.
253      * <p>
254      * This returns a {@code LocalDate} with the specified year, month and day-of-month.
255      * The day must be valid for the year and month, otherwise an exception will be thrown.
256      *
257      * @param year  the year to represent, from MIN_YEAR to MAX_YEAR
258      * @param month  the month-of-year to represent, from 1 (January) to 12 (December)
259      * @param dayOfMonth  the day-of-month to represent, from 1 to 31
260      * @return the local date, not null
261      * @throws DateTimeException if the value of any field is out of range,
262      *  or if the day-of-month is invalid for the month-year
263      */
of(int year, int month, int dayOfMonth)264     public static LocalDate of(int year, int month, int dayOfMonth) {
265         YEAR.checkValidValue(year);
266         MONTH_OF_YEAR.checkValidValue(month);
267         DAY_OF_MONTH.checkValidValue(dayOfMonth);
268         return create(year, month, dayOfMonth);
269     }
270 
271     //-----------------------------------------------------------------------
272     /**
273      * Obtains an instance of {@code LocalDate} from a year and day-of-year.
274      * <p>
275      * This returns a {@code LocalDate} with the specified year and day-of-year.
276      * The day-of-year must be valid for the year, otherwise an exception will be thrown.
277      *
278      * @param year  the year to represent, from MIN_YEAR to MAX_YEAR
279      * @param dayOfYear  the day-of-year to represent, from 1 to 366
280      * @return the local date, not null
281      * @throws DateTimeException if the value of any field is out of range,
282      *  or if the day-of-year is invalid for the year
283      */
ofYearDay(int year, int dayOfYear)284     public static LocalDate ofYearDay(int year, int dayOfYear) {
285         YEAR.checkValidValue(year);
286         DAY_OF_YEAR.checkValidValue(dayOfYear);
287         boolean leap = IsoChronology.INSTANCE.isLeapYear(year);
288         if (dayOfYear == 366 && leap == false) {
289             throw new DateTimeException("Invalid date 'DayOfYear 366' as '" + year + "' is not a leap year");
290         }
291         Month moy = Month.of((dayOfYear - 1) / 31 + 1);
292         int monthEnd = moy.firstDayOfYear(leap) + moy.length(leap) - 1;
293         if (dayOfYear > monthEnd) {
294             moy = moy.plus(1);
295         }
296         int dom = dayOfYear - moy.firstDayOfYear(leap) + 1;
297         return new LocalDate(year, moy.getValue(), dom);
298     }
299 
300     //-----------------------------------------------------------------------
301     /**
302      * Obtains an instance of {@code LocalDate} from an {@code Instant} and zone ID.
303      * <p>
304      * This creates a local date based on the specified instant.
305      * First, the offset from UTC/Greenwich is obtained using the zone ID and instant,
306      * which is simple as there is only one valid offset for each instant.
307      * Then, the instant and offset are used to calculate the local date.
308      *
309      * @param instant  the instant to create the date from, not null
310      * @param zone  the time-zone, which may be an offset, not null
311      * @return the local date, not null
312      * @throws DateTimeException if the result exceeds the supported range
313      * @since 9
314      */
ofInstant(Instant instant, ZoneId zone)315     public static LocalDate ofInstant(Instant instant, ZoneId zone) {
316         Objects.requireNonNull(instant, "instant");
317         Objects.requireNonNull(zone, "zone");
318         ZoneRules rules = zone.getRules();
319         ZoneOffset offset = rules.getOffset(instant);
320         long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();
321         long localEpochDay = Math.floorDiv(localSecond, SECONDS_PER_DAY);
322         return ofEpochDay(localEpochDay);
323     }
324 
325     //-----------------------------------------------------------------------
326     /**
327      * Obtains an instance of {@code LocalDate} from the epoch day count.
328      * <p>
329      * This returns a {@code LocalDate} with the specified epoch-day.
330      * The {@link ChronoField#EPOCH_DAY EPOCH_DAY} is a simple incrementing count
331      * of days where day 0 is 1970-01-01. Negative numbers represent earlier days.
332      *
333      * @param epochDay  the Epoch Day to convert, based on the epoch 1970-01-01
334      * @return the local date, not null
335      * @throws DateTimeException if the epoch day exceeds the supported date range
336      */
ofEpochDay(long epochDay)337     public static LocalDate ofEpochDay(long epochDay) {
338         EPOCH_DAY.checkValidValue(epochDay);
339         long zeroDay = epochDay + DAYS_0000_TO_1970;
340         // find the march-based year
341         zeroDay -= 60;  // adjust to 0000-03-01 so leap day is at end of four year cycle
342         long adjust = 0;
343         if (zeroDay < 0) {
344             // adjust negative years to positive for calculation
345             long adjustCycles = (zeroDay + 1) / DAYS_PER_CYCLE - 1;
346             adjust = adjustCycles * 400;
347             zeroDay += -adjustCycles * DAYS_PER_CYCLE;
348         }
349         long yearEst = (400 * zeroDay + 591) / DAYS_PER_CYCLE;
350         long doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400);
351         if (doyEst < 0) {
352             // fix estimate
353             yearEst--;
354             doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400);
355         }
356         yearEst += adjust;  // reset any negative year
357         int marchDoy0 = (int) doyEst;
358 
359         // convert march-based values back to january-based
360         int marchMonth0 = (marchDoy0 * 5 + 2) / 153;
361         int month = (marchMonth0 + 2) % 12 + 1;
362         int dom = marchDoy0 - (marchMonth0 * 306 + 5) / 10 + 1;
363         yearEst += marchMonth0 / 10;
364 
365         // check year now we are certain it is correct
366         int year = YEAR.checkValidIntValue(yearEst);
367         return new LocalDate(year, month, dom);
368     }
369 
370     //-----------------------------------------------------------------------
371     /**
372      * Obtains an instance of {@code LocalDate} from a temporal object.
373      * <p>
374      * This obtains a local date based on the specified temporal.
375      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
376      * which this factory converts to an instance of {@code LocalDate}.
377      * <p>
378      * The conversion uses the {@link TemporalQueries#localDate()} query, which relies
379      * on extracting the {@link ChronoField#EPOCH_DAY EPOCH_DAY} field.
380      * <p>
381      * This method matches the signature of the functional interface {@link TemporalQuery}
382      * allowing it to be used as a query via method reference, {@code LocalDate::from}.
383      *
384      * @param temporal  the temporal object to convert, not null
385      * @return the local date, not null
386      * @throws DateTimeException if unable to convert to a {@code LocalDate}
387      */
from(TemporalAccessor temporal)388     public static LocalDate from(TemporalAccessor temporal) {
389         Objects.requireNonNull(temporal, "temporal");
390         LocalDate date = temporal.query(TemporalQueries.localDate());
391         if (date == null) {
392             throw new DateTimeException("Unable to obtain LocalDate from TemporalAccessor: " +
393                     temporal + " of type " + temporal.getClass().getName());
394         }
395         return date;
396     }
397 
398     //-----------------------------------------------------------------------
399     /**
400      * Obtains an instance of {@code LocalDate} from a text string such as {@code 2007-12-03}.
401      * <p>
402      * The string must represent a valid date and is parsed using
403      * {@link java.time.format.DateTimeFormatter#ISO_LOCAL_DATE}.
404      *
405      * @param text  the text to parse such as "2007-12-03", not null
406      * @return the parsed local date, not null
407      * @throws DateTimeParseException if the text cannot be parsed
408      */
parse(CharSequence text)409     public static LocalDate parse(CharSequence text) {
410         return parse(text, DateTimeFormatter.ISO_LOCAL_DATE);
411     }
412 
413     /**
414      * Obtains an instance of {@code LocalDate} from a text string using a specific formatter.
415      * <p>
416      * The text is parsed using the formatter, returning a date.
417      *
418      * @param text  the text to parse, not null
419      * @param formatter  the formatter to use, not null
420      * @return the parsed local date, not null
421      * @throws DateTimeParseException if the text cannot be parsed
422      */
parse(CharSequence text, DateTimeFormatter formatter)423     public static LocalDate parse(CharSequence text, DateTimeFormatter formatter) {
424         Objects.requireNonNull(formatter, "formatter");
425         return formatter.parse(text, LocalDate::from);
426     }
427 
428     //-----------------------------------------------------------------------
429     /**
430      * Creates a local date from the year, month and day fields.
431      *
432      * @param year  the year to represent, validated from MIN_YEAR to MAX_YEAR
433      * @param month  the month-of-year to represent, from 1 to 12, validated
434      * @param dayOfMonth  the day-of-month to represent, validated from 1 to 31
435      * @return the local date, not null
436      * @throws DateTimeException if the day-of-month is invalid for the month-year
437      */
create(int year, int month, int dayOfMonth)438     private static LocalDate create(int year, int month, int dayOfMonth) {
439         if (dayOfMonth > 28) {
440             int dom = 31;
441             switch (month) {
442                 case 2:
443                     dom = (IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);
444                     break;
445                 case 4:
446                 case 6:
447                 case 9:
448                 case 11:
449                     dom = 30;
450                     break;
451             }
452             if (dayOfMonth > dom) {
453                 if (dayOfMonth == 29) {
454                     throw new DateTimeException("Invalid date 'February 29' as '" + year + "' is not a leap year");
455                 } else {
456                     throw new DateTimeException("Invalid date '" + Month.of(month).name() + " " + dayOfMonth + "'");
457                 }
458             }
459         }
460         return new LocalDate(year, month, dayOfMonth);
461     }
462 
463     /**
464      * Resolves the date, resolving days past the end of month.
465      *
466      * @param year  the year to represent, validated from MIN_YEAR to MAX_YEAR
467      * @param month  the month-of-year to represent, validated from 1 to 12
468      * @param day  the day-of-month to represent, validated from 1 to 31
469      * @return the resolved date, not null
470      */
resolvePreviousValid(int year, int month, int day)471     private static LocalDate resolvePreviousValid(int year, int month, int day) {
472         switch (month) {
473             case 2:
474                 day = Math.min(day, IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);
475                 break;
476             case 4:
477             case 6:
478             case 9:
479             case 11:
480                 day = Math.min(day, 30);
481                 break;
482         }
483         return new LocalDate(year, month, day);
484     }
485 
486     /**
487      * Constructor, previously validated.
488      *
489      * @param year  the year to represent, from MIN_YEAR to MAX_YEAR
490      * @param month  the month-of-year to represent, not null
491      * @param dayOfMonth  the day-of-month to represent, valid for year-month, from 1 to 31
492      */
LocalDate(int year, int month, int dayOfMonth)493     private LocalDate(int year, int month, int dayOfMonth) {
494         this.year = year;
495         this.month = (short) month;
496         this.day = (short) dayOfMonth;
497     }
498 
499     //-----------------------------------------------------------------------
500     /**
501      * Checks if the specified field is supported.
502      * <p>
503      * This checks if this date can be queried for the specified field.
504      * If false, then calling the {@link #range(TemporalField) range},
505      * {@link #get(TemporalField) get} and {@link #with(TemporalField, long)}
506      * methods will throw an exception.
507      * <p>
508      * If the field is a {@link ChronoField} then the query is implemented here.
509      * The supported fields are:
510      * <ul>
511      * <li>{@code DAY_OF_WEEK}
512      * <li>{@code ALIGNED_DAY_OF_WEEK_IN_MONTH}
513      * <li>{@code ALIGNED_DAY_OF_WEEK_IN_YEAR}
514      * <li>{@code DAY_OF_MONTH}
515      * <li>{@code DAY_OF_YEAR}
516      * <li>{@code EPOCH_DAY}
517      * <li>{@code ALIGNED_WEEK_OF_MONTH}
518      * <li>{@code ALIGNED_WEEK_OF_YEAR}
519      * <li>{@code MONTH_OF_YEAR}
520      * <li>{@code PROLEPTIC_MONTH}
521      * <li>{@code YEAR_OF_ERA}
522      * <li>{@code YEAR}
523      * <li>{@code ERA}
524      * </ul>
525      * All other {@code ChronoField} instances will return false.
526      * <p>
527      * If the field is not a {@code ChronoField}, then the result of this method
528      * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
529      * passing {@code this} as the argument.
530      * Whether the field is supported is determined by the field.
531      *
532      * @param field  the field to check, null returns false
533      * @return true if the field is supported on this date, false if not
534      */
535     @Override  // override for Javadoc
isSupported(TemporalField field)536     public boolean isSupported(TemporalField field) {
537         return ChronoLocalDate.super.isSupported(field);
538     }
539 
540     /**
541      * Checks if the specified unit is supported.
542      * <p>
543      * This checks if the specified unit can be added to, or subtracted from, this date.
544      * If false, then calling the {@link #plus(long, TemporalUnit)} and
545      * {@link #minus(long, TemporalUnit) minus} methods will throw an exception.
546      * <p>
547      * If the unit is a {@link ChronoUnit} then the query is implemented here.
548      * The supported units are:
549      * <ul>
550      * <li>{@code DAYS}
551      * <li>{@code WEEKS}
552      * <li>{@code MONTHS}
553      * <li>{@code YEARS}
554      * <li>{@code DECADES}
555      * <li>{@code CENTURIES}
556      * <li>{@code MILLENNIA}
557      * <li>{@code ERAS}
558      * </ul>
559      * All other {@code ChronoUnit} instances will return false.
560      * <p>
561      * If the unit is not a {@code ChronoUnit}, then the result of this method
562      * is obtained by invoking {@code TemporalUnit.isSupportedBy(Temporal)}
563      * passing {@code this} as the argument.
564      * Whether the unit is supported is determined by the unit.
565      *
566      * @param unit  the unit to check, null returns false
567      * @return true if the unit can be added/subtracted, false if not
568      */
569     @Override  // override for Javadoc
isSupported(TemporalUnit unit)570     public boolean isSupported(TemporalUnit unit) {
571         return ChronoLocalDate.super.isSupported(unit);
572     }
573 
574     //-----------------------------------------------------------------------
575     /**
576      * Gets the range of valid values for the specified field.
577      * <p>
578      * The range object expresses the minimum and maximum valid values for a field.
579      * This date is used to enhance the accuracy of the returned range.
580      * If it is not possible to return the range, because the field is not supported
581      * or for some other reason, an exception is thrown.
582      * <p>
583      * If the field is a {@link ChronoField} then the query is implemented here.
584      * The {@link #isSupported(TemporalField) supported fields} will return
585      * appropriate range instances.
586      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
587      * <p>
588      * If the field is not a {@code ChronoField}, then the result of this method
589      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
590      * passing {@code this} as the argument.
591      * Whether the range can be obtained is determined by the field.
592      *
593      * @param field  the field to query the range for, not null
594      * @return the range of valid values for the field, not null
595      * @throws DateTimeException if the range for the field cannot be obtained
596      * @throws UnsupportedTemporalTypeException if the field is not supported
597      */
598     @Override
range(TemporalField field)599     public ValueRange range(TemporalField field) {
600         if (field instanceof ChronoField chronoField) {
601             if (chronoField.isDateBased()) {
602                 switch (chronoField) {
603                     case DAY_OF_MONTH: return ValueRange.of(1, lengthOfMonth());
604                     case DAY_OF_YEAR: return ValueRange.of(1, lengthOfYear());
605                     case ALIGNED_WEEK_OF_MONTH: return ValueRange.of(1, getMonth() == Month.FEBRUARY && isLeapYear() == false ? 4 : 5);
606                     case YEAR_OF_ERA:
607                         return (getYear() <= 0 ? ValueRange.of(1, Year.MAX_VALUE + 1) : ValueRange.of(1, Year.MAX_VALUE));
608                 }
609                 return field.range();
610             }
611             throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
612         }
613         return field.rangeRefinedBy(this);
614     }
615 
616     /**
617      * Gets the value of the specified field from this date as an {@code int}.
618      * <p>
619      * This queries this date for the value of the specified field.
620      * The returned value will always be within the valid range of values for the field.
621      * If it is not possible to return the value, because the field is not supported
622      * or for some other reason, an exception is thrown.
623      * <p>
624      * If the field is a {@link ChronoField} then the query is implemented here.
625      * The {@link #isSupported(TemporalField) supported fields} will return valid
626      * values based on this date, except {@code EPOCH_DAY} and {@code PROLEPTIC_MONTH}
627      * which are too large to fit in an {@code int} and throw an {@code UnsupportedTemporalTypeException}.
628      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
629      * <p>
630      * If the field is not a {@code ChronoField}, then the result of this method
631      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
632      * passing {@code this} as the argument. Whether the value can be obtained,
633      * and what the value represents, is determined by the field.
634      *
635      * @param field  the field to get, not null
636      * @return the value for the field
637      * @throws DateTimeException if a value for the field cannot be obtained or
638      *         the value is outside the range of valid values for the field
639      * @throws UnsupportedTemporalTypeException if the field is not supported or
640      *         the range of values exceeds an {@code int}
641      * @throws ArithmeticException if numeric overflow occurs
642      */
643     @Override  // override for Javadoc and performance
get(TemporalField field)644     public int get(TemporalField field) {
645         if (field instanceof ChronoField) {
646             return get0(field);
647         }
648         return ChronoLocalDate.super.get(field);
649     }
650 
651     /**
652      * Gets the value of the specified field from this date as a {@code long}.
653      * <p>
654      * This queries this date for the value of the specified field.
655      * If it is not possible to return the value, because the field is not supported
656      * or for some other reason, an exception is thrown.
657      * <p>
658      * If the field is a {@link ChronoField} then the query is implemented here.
659      * The {@link #isSupported(TemporalField) supported fields} will return valid
660      * values based on this date.
661      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
662      * <p>
663      * If the field is not a {@code ChronoField}, then the result of this method
664      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
665      * passing {@code this} as the argument. Whether the value can be obtained,
666      * and what the value represents, is determined by the field.
667      *
668      * @param field  the field to get, not null
669      * @return the value for the field
670      * @throws DateTimeException if a value for the field cannot be obtained
671      * @throws UnsupportedTemporalTypeException if the field is not supported
672      * @throws ArithmeticException if numeric overflow occurs
673      */
674     @Override
getLong(TemporalField field)675     public long getLong(TemporalField field) {
676         if (field instanceof ChronoField) {
677             if (field == EPOCH_DAY) {
678                 return toEpochDay();
679             }
680             if (field == PROLEPTIC_MONTH) {
681                 return getProlepticMonth();
682             }
683             return get0(field);
684         }
685         return field.getFrom(this);
686     }
687 
get0(TemporalField field)688     private int get0(TemporalField field) {
689         switch ((ChronoField) field) {
690             case DAY_OF_WEEK: return getDayOfWeek().getValue();
691             case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((day - 1) % 7) + 1;
692             case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1;
693             case DAY_OF_MONTH: return day;
694             case DAY_OF_YEAR: return getDayOfYear();
695             case EPOCH_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'EpochDay' for get() method, use getLong() instead");
696             case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1;
697             case ALIGNED_WEEK_OF_YEAR: return ((getDayOfYear() - 1) / 7) + 1;
698             case MONTH_OF_YEAR: return month;
699             case PROLEPTIC_MONTH: throw new UnsupportedTemporalTypeException("Invalid field 'ProlepticMonth' for get() method, use getLong() instead");
700             case YEAR_OF_ERA: return (year >= 1 ? year : 1 - year);
701             case YEAR: return year;
702             case ERA: return (year >= 1 ? 1 : 0);
703         }
704         throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
705     }
706 
getProlepticMonth()707     private long getProlepticMonth() {
708         return (year * 12L + month - 1);
709     }
710 
711     //-----------------------------------------------------------------------
712     /**
713      * Gets the chronology of this date, which is the ISO calendar system.
714      * <p>
715      * The {@code Chronology} represents the calendar system in use.
716      * The ISO-8601 calendar system is the modern civil calendar system used today
717      * in most of the world. It is equivalent to the proleptic Gregorian calendar
718      * system, in which today's rules for leap years are applied for all time.
719      *
720      * @return the ISO chronology, not null
721      */
722     @Override
getChronology()723     public IsoChronology getChronology() {
724         return IsoChronology.INSTANCE;
725     }
726 
727     /**
728      * Gets the era applicable at this date.
729      * <p>
730      * The official ISO-8601 standard does not define eras, however {@code IsoChronology} does.
731      * It defines two eras, 'CE' from year one onwards and 'BCE' from year zero backwards.
732      * Since dates before the Julian-Gregorian cutover are not in line with history,
733      * the cutover between 'BCE' and 'CE' is also not aligned with the commonly used
734      * eras, often referred to using 'BC' and 'AD'.
735      * <p>
736      * Users of this class should typically ignore this method as it exists primarily
737      * to fulfill the {@link ChronoLocalDate} contract where it is necessary to support
738      * the Japanese calendar system.
739      *
740      * @return the IsoEra applicable at this date, not null
741      */
742     @Override // override for Javadoc
743     // Android-changed: To match OpenJDK 11 API, this API returns IsoEra type after Android T.
744     @CovariantReturnType(returnType = java.time.chrono.IsoEra.class, presentAfter = 33)
getEra()745     public Era getEra() {
746         return (getYear() >= 1 ? IsoEra.CE : IsoEra.BCE);
747     }
748 
749     /**
750      * Gets the year field.
751      * <p>
752      * This method returns the primitive {@code int} value for the year.
753      * <p>
754      * The year returned by this method is proleptic as per {@code get(YEAR)}.
755      * To obtain the year-of-era, use {@code get(YEAR_OF_ERA)}.
756      *
757      * @return the year, from MIN_YEAR to MAX_YEAR
758      */
getYear()759     public int getYear() {
760         return year;
761     }
762 
763     /**
764      * Gets the month-of-year field from 1 to 12.
765      * <p>
766      * This method returns the month as an {@code int} from 1 to 12.
767      * Application code is frequently clearer if the enum {@link Month}
768      * is used by calling {@link #getMonth()}.
769      *
770      * @return the month-of-year, from 1 to 12
771      * @see #getMonth()
772      */
getMonthValue()773     public int getMonthValue() {
774         return month;
775     }
776 
777     /**
778      * Gets the month-of-year field using the {@code Month} enum.
779      * <p>
780      * This method returns the enum {@link Month} for the month.
781      * This avoids confusion as to what {@code int} values mean.
782      * If you need access to the primitive {@code int} value then the enum
783      * provides the {@link Month#getValue() int value}.
784      *
785      * @return the month-of-year, not null
786      * @see #getMonthValue()
787      */
getMonth()788     public Month getMonth() {
789         return Month.of(month);
790     }
791 
792     /**
793      * Gets the day-of-month field.
794      * <p>
795      * This method returns the primitive {@code int} value for the day-of-month.
796      *
797      * @return the day-of-month, from 1 to 31
798      */
getDayOfMonth()799     public int getDayOfMonth() {
800         return day;
801     }
802 
803     /**
804      * Gets the day-of-year field.
805      * <p>
806      * This method returns the primitive {@code int} value for the day-of-year.
807      *
808      * @return the day-of-year, from 1 to 365, or 366 in a leap year
809      */
getDayOfYear()810     public int getDayOfYear() {
811         return getMonth().firstDayOfYear(isLeapYear()) + day - 1;
812     }
813 
814     /**
815      * Gets the day-of-week field, which is an enum {@code DayOfWeek}.
816      * <p>
817      * This method returns the enum {@link DayOfWeek} for the day-of-week.
818      * This avoids confusion as to what {@code int} values mean.
819      * If you need access to the primitive {@code int} value then the enum
820      * provides the {@link DayOfWeek#getValue() int value}.
821      * <p>
822      * Additional information can be obtained from the {@code DayOfWeek}.
823      * This includes textual names of the values.
824      *
825      * @return the day-of-week, not null
826      */
getDayOfWeek()827     public DayOfWeek getDayOfWeek() {
828         int dow0 = Math.floorMod(toEpochDay() + 3, 7);
829         return DayOfWeek.of(dow0 + 1);
830     }
831 
832     //-----------------------------------------------------------------------
833     /**
834      * Checks if the year is a leap year, according to the ISO proleptic
835      * calendar system rules.
836      * <p>
837      * This method applies the current rules for leap years across the whole time-line.
838      * In general, a year is a leap year if it is divisible by four without
839      * remainder. However, years divisible by 100, are not leap years, with
840      * the exception of years divisible by 400 which are.
841      * <p>
842      * For example, 1904 is a leap year it is divisible by 4.
843      * 1900 was not a leap year as it is divisible by 100, however 2000 was a
844      * leap year as it is divisible by 400.
845      * <p>
846      * The calculation is proleptic - applying the same rules into the far future and far past.
847      * This is historically inaccurate, but is correct for the ISO-8601 standard.
848      *
849      * @return true if the year is leap, false otherwise
850      */
851     @Override // override for Javadoc and performance
isLeapYear()852     public boolean isLeapYear() {
853         return IsoChronology.INSTANCE.isLeapYear(year);
854     }
855 
856     /**
857      * Returns the length of the month represented by this date.
858      * <p>
859      * This returns the length of the month in days.
860      * For example, a date in January would return 31.
861      *
862      * @return the length of the month in days
863      */
864     @Override
lengthOfMonth()865     public int lengthOfMonth() {
866         switch (month) {
867             case 2:
868                 return (isLeapYear() ? 29 : 28);
869             case 4:
870             case 6:
871             case 9:
872             case 11:
873                 return 30;
874             default:
875                 return 31;
876         }
877     }
878 
879     /**
880      * Returns the length of the year represented by this date.
881      * <p>
882      * This returns the length of the year in days, either 365 or 366.
883      *
884      * @return 366 if the year is leap, 365 otherwise
885      */
886     @Override // override for Javadoc and performance
lengthOfYear()887     public int lengthOfYear() {
888         return (isLeapYear() ? 366 : 365);
889     }
890 
891     //-----------------------------------------------------------------------
892     /**
893      * Returns an adjusted copy of this date.
894      * <p>
895      * This returns a {@code LocalDate}, based on this one, with the date adjusted.
896      * The adjustment takes place using the specified adjuster strategy object.
897      * Read the documentation of the adjuster to understand what adjustment will be made.
898      * <p>
899      * A simple adjuster might simply set the one of the fields, such as the year field.
900      * A more complex adjuster might set the date to the last day of the month.
901      * <p>
902      * A selection of common adjustments is provided in
903      * {@link java.time.temporal.TemporalAdjusters TemporalAdjusters}.
904      * These include finding the "last day of the month" and "next Wednesday".
905      * Key date-time classes also implement the {@code TemporalAdjuster} interface,
906      * such as {@link Month} and {@link java.time.MonthDay MonthDay}.
907      * The adjuster is responsible for handling special cases, such as the varying
908      * lengths of month and leap years.
909      * <p>
910      * For example this code returns a date on the last day of July:
911      * <pre>
912      *  import static java.time.Month.*;
913      *  import static java.time.temporal.TemporalAdjusters.*;
914      *
915      *  result = localDate.with(JULY).with(lastDayOfMonth());
916      * </pre>
917      * <p>
918      * The result of this method is obtained by invoking the
919      * {@link TemporalAdjuster#adjustInto(Temporal)} method on the
920      * specified adjuster passing {@code this} as the argument.
921      * <p>
922      * This instance is immutable and unaffected by this method call.
923      *
924      * @param adjuster the adjuster to use, not null
925      * @return a {@code LocalDate} based on {@code this} with the adjustment made, not null
926      * @throws DateTimeException if the adjustment cannot be made
927      * @throws ArithmeticException if numeric overflow occurs
928      */
929     @Override
with(TemporalAdjuster adjuster)930     public LocalDate with(TemporalAdjuster adjuster) {
931         // optimizations
932         if (adjuster instanceof LocalDate) {
933             return (LocalDate) adjuster;
934         }
935         return (LocalDate) adjuster.adjustInto(this);
936     }
937 
938     /**
939      * Returns a copy of this date with the specified field set to a new value.
940      * <p>
941      * This returns a {@code LocalDate}, based on this one, with the value
942      * for the specified field changed.
943      * This can be used to change any supported field, such as the year, month or day-of-month.
944      * If it is not possible to set the value, because the field is not supported or for
945      * some other reason, an exception is thrown.
946      * <p>
947      * In some cases, changing the specified field can cause the resulting date to become invalid,
948      * such as changing the month from 31st January to February would make the day-of-month invalid.
949      * In cases like this, the field is responsible for resolving the date. Typically it will choose
950      * the previous valid date, which would be the last valid day of February in this example.
951      * <p>
952      * If the field is a {@link ChronoField} then the adjustment is implemented here.
953      * The supported fields behave as follows:
954      * <ul>
955      * <li>{@code DAY_OF_WEEK} -
956      *  Returns a {@code LocalDate} with the specified day-of-week.
957      *  The date is adjusted up to 6 days forward or backward within the boundary
958      *  of a Monday to Sunday week.
959      * <li>{@code ALIGNED_DAY_OF_WEEK_IN_MONTH} -
960      *  Returns a {@code LocalDate} with the specified aligned-day-of-week.
961      *  The date is adjusted to the specified month-based aligned-day-of-week.
962      *  Aligned weeks are counted such that the first week of a given month starts
963      *  on the first day of that month.
964      *  This may cause the date to be moved up to 6 days into the following month.
965      * <li>{@code ALIGNED_DAY_OF_WEEK_IN_YEAR} -
966      *  Returns a {@code LocalDate} with the specified aligned-day-of-week.
967      *  The date is adjusted to the specified year-based aligned-day-of-week.
968      *  Aligned weeks are counted such that the first week of a given year starts
969      *  on the first day of that year.
970      *  This may cause the date to be moved up to 6 days into the following year.
971      * <li>{@code DAY_OF_MONTH} -
972      *  Returns a {@code LocalDate} with the specified day-of-month.
973      *  The month and year will be unchanged. If the day-of-month is invalid for the
974      *  year and month, then a {@code DateTimeException} is thrown.
975      * <li>{@code DAY_OF_YEAR} -
976      *  Returns a {@code LocalDate} with the specified day-of-year.
977      *  The year will be unchanged. If the day-of-year is invalid for the
978      *  year, then a {@code DateTimeException} is thrown.
979      * <li>{@code EPOCH_DAY} -
980      *  Returns a {@code LocalDate} with the specified epoch-day.
981      *  This completely replaces the date and is equivalent to {@link #ofEpochDay(long)}.
982      * <li>{@code ALIGNED_WEEK_OF_MONTH} -
983      *  Returns a {@code LocalDate} with the specified aligned-week-of-month.
984      *  Aligned weeks are counted such that the first week of a given month starts
985      *  on the first day of that month.
986      *  This adjustment moves the date in whole week chunks to match the specified week.
987      *  The result will have the same day-of-week as this date.
988      *  This may cause the date to be moved into the following month.
989      * <li>{@code ALIGNED_WEEK_OF_YEAR} -
990      *  Returns a {@code LocalDate} with the specified aligned-week-of-year.
991      *  Aligned weeks are counted such that the first week of a given year starts
992      *  on the first day of that year.
993      *  This adjustment moves the date in whole week chunks to match the specified week.
994      *  The result will have the same day-of-week as this date.
995      *  This may cause the date to be moved into the following year.
996      * <li>{@code MONTH_OF_YEAR} -
997      *  Returns a {@code LocalDate} with the specified month-of-year.
998      *  The year will be unchanged. The day-of-month will also be unchanged,
999      *  unless it would be invalid for the new month and year. In that case, the
1000      *  day-of-month is adjusted to the maximum valid value for the new month and year.
1001      * <li>{@code PROLEPTIC_MONTH} -
1002      *  Returns a {@code LocalDate} with the specified proleptic-month.
1003      *  The day-of-month will be unchanged, unless it would be invalid for the new month
1004      *  and year. In that case, the day-of-month is adjusted to the maximum valid value
1005      *  for the new month and year.
1006      * <li>{@code YEAR_OF_ERA} -
1007      *  Returns a {@code LocalDate} with the specified year-of-era.
1008      *  The era and month will be unchanged. The day-of-month will also be unchanged,
1009      *  unless it would be invalid for the new month and year. In that case, the
1010      *  day-of-month is adjusted to the maximum valid value for the new month and year.
1011      * <li>{@code YEAR} -
1012      *  Returns a {@code LocalDate} with the specified year.
1013      *  The month will be unchanged. The day-of-month will also be unchanged,
1014      *  unless it would be invalid for the new month and year. In that case, the
1015      *  day-of-month is adjusted to the maximum valid value for the new month and year.
1016      * <li>{@code ERA} -
1017      *  Returns a {@code LocalDate} with the specified era.
1018      *  The year-of-era and month will be unchanged. The day-of-month will also be unchanged,
1019      *  unless it would be invalid for the new month and year. In that case, the
1020      *  day-of-month is adjusted to the maximum valid value for the new month and year.
1021      * </ul>
1022      * <p>
1023      * In all cases, if the new value is outside the valid range of values for the field
1024      * then a {@code DateTimeException} will be thrown.
1025      * <p>
1026      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
1027      * <p>
1028      * If the field is not a {@code ChronoField}, then the result of this method
1029      * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
1030      * passing {@code this} as the argument. In this case, the field determines
1031      * whether and how to adjust the instant.
1032      * <p>
1033      * This instance is immutable and unaffected by this method call.
1034      *
1035      * @param field  the field to set in the result, not null
1036      * @param newValue  the new value of the field in the result
1037      * @return a {@code LocalDate} based on {@code this} with the specified field set, not null
1038      * @throws DateTimeException if the field cannot be set
1039      * @throws UnsupportedTemporalTypeException if the field is not supported
1040      * @throws ArithmeticException if numeric overflow occurs
1041      */
1042     @Override
with(TemporalField field, long newValue)1043     public LocalDate with(TemporalField field, long newValue) {
1044         if (field instanceof ChronoField chronoField) {
1045             chronoField.checkValidValue(newValue);
1046             switch (chronoField) {
1047                 case DAY_OF_WEEK: return plusDays(newValue - getDayOfWeek().getValue());
1048                 case ALIGNED_DAY_OF_WEEK_IN_MONTH: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_MONTH));
1049                 case ALIGNED_DAY_OF_WEEK_IN_YEAR: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_YEAR));
1050                 case DAY_OF_MONTH: return withDayOfMonth((int) newValue);
1051                 case DAY_OF_YEAR: return withDayOfYear((int) newValue);
1052                 case EPOCH_DAY: return LocalDate.ofEpochDay(newValue);
1053                 case ALIGNED_WEEK_OF_MONTH: return plusWeeks(newValue - getLong(ALIGNED_WEEK_OF_MONTH));
1054                 case ALIGNED_WEEK_OF_YEAR: return plusWeeks(newValue - getLong(ALIGNED_WEEK_OF_YEAR));
1055                 case MONTH_OF_YEAR: return withMonth((int) newValue);
1056                 case PROLEPTIC_MONTH: return plusMonths(newValue - getProlepticMonth());
1057                 case YEAR_OF_ERA: return withYear((int) (year >= 1 ? newValue : 1 - newValue));
1058                 case YEAR: return withYear((int) newValue);
1059                 case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year));
1060             }
1061             throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
1062         }
1063         return field.adjustInto(this, newValue);
1064     }
1065 
1066     //-----------------------------------------------------------------------
1067     /**
1068      * Returns a copy of this {@code LocalDate} with the year altered.
1069      * <p>
1070      * If the day-of-month is invalid for the year, it will be changed to the last valid day of the month.
1071      * <p>
1072      * This instance is immutable and unaffected by this method call.
1073      *
1074      * @param year  the year to set in the result, from MIN_YEAR to MAX_YEAR
1075      * @return a {@code LocalDate} based on this date with the requested year, not null
1076      * @throws DateTimeException if the year value is invalid
1077      */
withYear(int year)1078     public LocalDate withYear(int year) {
1079         if (this.year == year) {
1080             return this;
1081         }
1082         YEAR.checkValidValue(year);
1083         return resolvePreviousValid(year, month, day);
1084     }
1085 
1086     /**
1087      * Returns a copy of this {@code LocalDate} with the month-of-year altered.
1088      * <p>
1089      * If the day-of-month is invalid for the year, it will be changed to the last valid day of the month.
1090      * <p>
1091      * This instance is immutable and unaffected by this method call.
1092      *
1093      * @param month  the month-of-year to set in the result, from 1 (January) to 12 (December)
1094      * @return a {@code LocalDate} based on this date with the requested month, not null
1095      * @throws DateTimeException if the month-of-year value is invalid
1096      */
withMonth(int month)1097     public LocalDate withMonth(int month) {
1098         if (this.month == month) {
1099             return this;
1100         }
1101         MONTH_OF_YEAR.checkValidValue(month);
1102         return resolvePreviousValid(year, month, day);
1103     }
1104 
1105     /**
1106      * Returns a copy of this {@code LocalDate} with the day-of-month altered.
1107      * <p>
1108      * If the resulting date is invalid, an exception is thrown.
1109      * <p>
1110      * This instance is immutable and unaffected by this method call.
1111      *
1112      * @param dayOfMonth  the day-of-month to set in the result, from 1 to 28-31
1113      * @return a {@code LocalDate} based on this date with the requested day, not null
1114      * @throws DateTimeException if the day-of-month value is invalid,
1115      *  or if the day-of-month is invalid for the month-year
1116      */
withDayOfMonth(int dayOfMonth)1117     public LocalDate withDayOfMonth(int dayOfMonth) {
1118         if (this.day == dayOfMonth) {
1119             return this;
1120         }
1121         return of(year, month, dayOfMonth);
1122     }
1123 
1124     /**
1125      * Returns a copy of this {@code LocalDate} with the day-of-year altered.
1126      * <p>
1127      * If the resulting date is invalid, an exception is thrown.
1128      * <p>
1129      * This instance is immutable and unaffected by this method call.
1130      *
1131      * @param dayOfYear  the day-of-year to set in the result, from 1 to 365-366
1132      * @return a {@code LocalDate} based on this date with the requested day, not null
1133      * @throws DateTimeException if the day-of-year value is invalid,
1134      *  or if the day-of-year is invalid for the year
1135      */
withDayOfYear(int dayOfYear)1136     public LocalDate withDayOfYear(int dayOfYear) {
1137         if (this.getDayOfYear() == dayOfYear) {
1138             return this;
1139         }
1140         return ofYearDay(year, dayOfYear);
1141     }
1142 
1143     //-----------------------------------------------------------------------
1144     /**
1145      * Returns a copy of this date with the specified amount added.
1146      * <p>
1147      * This returns a {@code LocalDate}, based on this one, with the specified amount added.
1148      * The amount is typically {@link Period} but may be any other type implementing
1149      * the {@link TemporalAmount} interface.
1150      * <p>
1151      * The calculation is delegated to the amount object by calling
1152      * {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free
1153      * to implement the addition in any way it wishes, however it typically
1154      * calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation
1155      * of the amount implementation to determine if it can be successfully added.
1156      * <p>
1157      * This instance is immutable and unaffected by this method call.
1158      *
1159      * @param amountToAdd  the amount to add, not null
1160      * @return a {@code LocalDate} based on this date with the addition made, not null
1161      * @throws DateTimeException if the addition cannot be made
1162      * @throws ArithmeticException if numeric overflow occurs
1163      */
1164     @Override
plus(TemporalAmount amountToAdd)1165     public LocalDate plus(TemporalAmount amountToAdd) {
1166         if (amountToAdd instanceof Period periodToAdd) {
1167             return plusMonths(periodToAdd.toTotalMonths()).plusDays(periodToAdd.getDays());
1168         }
1169         Objects.requireNonNull(amountToAdd, "amountToAdd");
1170         return (LocalDate) amountToAdd.addTo(this);
1171     }
1172 
1173     /**
1174      * Returns a copy of this date with the specified amount added.
1175      * <p>
1176      * This returns a {@code LocalDate}, based on this one, with the amount
1177      * in terms of the unit added. If it is not possible to add the amount, because the
1178      * unit is not supported or for some other reason, an exception is thrown.
1179      * <p>
1180      * In some cases, adding the amount can cause the resulting date to become invalid.
1181      * For example, adding one month to 31st January would result in 31st February.
1182      * In cases like this, the unit is responsible for resolving the date.
1183      * Typically it will choose the previous valid date, which would be the last valid
1184      * day of February in this example.
1185      * <p>
1186      * If the field is a {@link ChronoUnit} then the addition is implemented here.
1187      * The supported fields behave as follows:
1188      * <ul>
1189      * <li>{@code DAYS} -
1190      *  Returns a {@code LocalDate} with the specified number of days added.
1191      *  This is equivalent to {@link #plusDays(long)}.
1192      * <li>{@code WEEKS} -
1193      *  Returns a {@code LocalDate} with the specified number of weeks added.
1194      *  This is equivalent to {@link #plusWeeks(long)} and uses a 7 day week.
1195      * <li>{@code MONTHS} -
1196      *  Returns a {@code LocalDate} with the specified number of months added.
1197      *  This is equivalent to {@link #plusMonths(long)}.
1198      *  The day-of-month will be unchanged unless it would be invalid for the new
1199      *  month and year. In that case, the day-of-month is adjusted to the maximum
1200      *  valid value for the new month and year.
1201      * <li>{@code YEARS} -
1202      *  Returns a {@code LocalDate} with the specified number of years added.
1203      *  This is equivalent to {@link #plusYears(long)}.
1204      *  The day-of-month will be unchanged unless it would be invalid for the new
1205      *  month and year. In that case, the day-of-month is adjusted to the maximum
1206      *  valid value for the new month and year.
1207      * <li>{@code DECADES} -
1208      *  Returns a {@code LocalDate} with the specified number of decades added.
1209      *  This is equivalent to calling {@link #plusYears(long)} with the amount
1210      *  multiplied by 10.
1211      *  The day-of-month will be unchanged unless it would be invalid for the new
1212      *  month and year. In that case, the day-of-month is adjusted to the maximum
1213      *  valid value for the new month and year.
1214      * <li>{@code CENTURIES} -
1215      *  Returns a {@code LocalDate} with the specified number of centuries added.
1216      *  This is equivalent to calling {@link #plusYears(long)} with the amount
1217      *  multiplied by 100.
1218      *  The day-of-month will be unchanged unless it would be invalid for the new
1219      *  month and year. In that case, the day-of-month is adjusted to the maximum
1220      *  valid value for the new month and year.
1221      * <li>{@code MILLENNIA} -
1222      *  Returns a {@code LocalDate} with the specified number of millennia added.
1223      *  This is equivalent to calling {@link #plusYears(long)} with the amount
1224      *  multiplied by 1,000.
1225      *  The day-of-month will be unchanged unless it would be invalid for the new
1226      *  month and year. In that case, the day-of-month is adjusted to the maximum
1227      *  valid value for the new month and year.
1228      * <li>{@code ERAS} -
1229      *  Returns a {@code LocalDate} with the specified number of eras added.
1230      *  Only two eras are supported so the amount must be one, zero or minus one.
1231      *  If the amount is non-zero then the year is changed such that the year-of-era
1232      *  is unchanged.
1233      *  The day-of-month will be unchanged unless it would be invalid for the new
1234      *  month and year. In that case, the day-of-month is adjusted to the maximum
1235      *  valid value for the new month and year.
1236      * </ul>
1237      * <p>
1238      * All other {@code ChronoUnit} instances will throw an {@code UnsupportedTemporalTypeException}.
1239      * <p>
1240      * If the field is not a {@code ChronoUnit}, then the result of this method
1241      * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
1242      * passing {@code this} as the argument. In this case, the unit determines
1243      * whether and how to perform the addition.
1244      * <p>
1245      * This instance is immutable and unaffected by this method call.
1246      *
1247      * @param amountToAdd  the amount of the unit to add to the result, may be negative
1248      * @param unit  the unit of the amount to add, not null
1249      * @return a {@code LocalDate} based on this date with the specified amount added, not null
1250      * @throws DateTimeException if the addition cannot be made
1251      * @throws UnsupportedTemporalTypeException if the unit is not supported
1252      * @throws ArithmeticException if numeric overflow occurs
1253      */
1254     @Override
plus(long amountToAdd, TemporalUnit unit)1255     public LocalDate plus(long amountToAdd, TemporalUnit unit) {
1256         if (unit instanceof ChronoUnit chronoUnit) {
1257             switch (chronoUnit) {
1258                 case DAYS: return plusDays(amountToAdd);
1259                 case WEEKS: return plusWeeks(amountToAdd);
1260                 case MONTHS: return plusMonths(amountToAdd);
1261                 case YEARS: return plusYears(amountToAdd);
1262                 case DECADES: return plusYears(Math.multiplyExact(amountToAdd, 10));
1263                 case CENTURIES: return plusYears(Math.multiplyExact(amountToAdd, 100));
1264                 case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000));
1265                 case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd));
1266             }
1267             throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
1268         }
1269         return unit.addTo(this, amountToAdd);
1270     }
1271 
1272     //-----------------------------------------------------------------------
1273     /**
1274      * Returns a copy of this {@code LocalDate} with the specified number of years added.
1275      * <p>
1276      * This method adds the specified amount to the years field in three steps:
1277      * <ol>
1278      * <li>Add the input years to the year field</li>
1279      * <li>Check if the resulting date would be invalid</li>
1280      * <li>Adjust the day-of-month to the last valid day if necessary</li>
1281      * </ol>
1282      * <p>
1283      * For example, 2008-02-29 (leap year) plus one year would result in the
1284      * invalid date 2009-02-29 (standard year). Instead of returning an invalid
1285      * result, the last valid day of the month, 2009-02-28, is selected instead.
1286      * <p>
1287      * This instance is immutable and unaffected by this method call.
1288      *
1289      * @param yearsToAdd  the years to add, may be negative
1290      * @return a {@code LocalDate} based on this date with the years added, not null
1291      * @throws DateTimeException if the result exceeds the supported date range
1292      */
plusYears(long yearsToAdd)1293     public LocalDate plusYears(long yearsToAdd) {
1294         if (yearsToAdd == 0) {
1295             return this;
1296         }
1297         int newYear = YEAR.checkValidIntValue(year + yearsToAdd);  // safe overflow
1298         return resolvePreviousValid(newYear, month, day);
1299     }
1300 
1301     /**
1302      * Returns a copy of this {@code LocalDate} with the specified number of months added.
1303      * <p>
1304      * This method adds the specified amount to the months field in three steps:
1305      * <ol>
1306      * <li>Add the input months to the month-of-year field</li>
1307      * <li>Check if the resulting date would be invalid</li>
1308      * <li>Adjust the day-of-month to the last valid day if necessary</li>
1309      * </ol>
1310      * <p>
1311      * For example, 2007-03-31 plus one month would result in the invalid date
1312      * 2007-04-31. Instead of returning an invalid result, the last valid day
1313      * of the month, 2007-04-30, is selected instead.
1314      * <p>
1315      * This instance is immutable and unaffected by this method call.
1316      *
1317      * @param monthsToAdd  the months to add, may be negative
1318      * @return a {@code LocalDate} based on this date with the months added, not null
1319      * @throws DateTimeException if the result exceeds the supported date range
1320      */
plusMonths(long monthsToAdd)1321     public LocalDate plusMonths(long monthsToAdd) {
1322         if (monthsToAdd == 0) {
1323             return this;
1324         }
1325         long monthCount = year * 12L + (month - 1);
1326         long calcMonths = monthCount + monthsToAdd;  // safe overflow
1327         int newYear = YEAR.checkValidIntValue(Math.floorDiv(calcMonths, 12));
1328         int newMonth = Math.floorMod(calcMonths, 12) + 1;
1329         return resolvePreviousValid(newYear, newMonth, day);
1330     }
1331 
1332     /**
1333      * Returns a copy of this {@code LocalDate} with the specified number of weeks added.
1334      * <p>
1335      * This method adds the specified amount in weeks to the days field incrementing
1336      * the month and year fields as necessary to ensure the result remains valid.
1337      * The result is only invalid if the maximum/minimum year is exceeded.
1338      * <p>
1339      * For example, 2008-12-31 plus one week would result in 2009-01-07.
1340      * <p>
1341      * This instance is immutable and unaffected by this method call.
1342      *
1343      * @param weeksToAdd  the weeks to add, may be negative
1344      * @return a {@code LocalDate} based on this date with the weeks added, not null
1345      * @throws DateTimeException if the result exceeds the supported date range
1346      */
plusWeeks(long weeksToAdd)1347     public LocalDate plusWeeks(long weeksToAdd) {
1348         return plusDays(Math.multiplyExact(weeksToAdd, 7));
1349     }
1350 
1351     /**
1352      * Returns a copy of this {@code LocalDate} with the specified number of days added.
1353      * <p>
1354      * This method adds the specified amount to the days field incrementing the
1355      * month and year fields as necessary to ensure the result remains valid.
1356      * The result is only invalid if the maximum/minimum year is exceeded.
1357      * <p>
1358      * For example, 2008-12-31 plus one day would result in 2009-01-01.
1359      * <p>
1360      * This instance is immutable and unaffected by this method call.
1361      *
1362      * @param daysToAdd  the days to add, may be negative
1363      * @return a {@code LocalDate} based on this date with the days added, not null
1364      * @throws DateTimeException if the result exceeds the supported date range
1365      */
plusDays(long daysToAdd)1366     public LocalDate plusDays(long daysToAdd) {
1367         if (daysToAdd == 0) {
1368             return this;
1369         }
1370         long dom = day + daysToAdd;
1371         if (dom > 0) {
1372             if (dom <= 28) {
1373                 return new LocalDate(year, month, (int) dom);
1374             } else if (dom <= 59) { // 59th Jan is 28th Feb, 59th Feb is 31st Mar
1375                 long monthLen = lengthOfMonth();
1376                 if (dom <= monthLen) {
1377                     return new LocalDate(year, month, (int) dom);
1378                 } else if (month < 12) {
1379                     return new LocalDate(year, month + 1, (int) (dom - monthLen));
1380                 } else {
1381                     YEAR.checkValidValue(year + 1);
1382                     return new LocalDate(year + 1, 1, (int) (dom - monthLen));
1383                 }
1384             }
1385         }
1386 
1387         long mjDay = Math.addExact(toEpochDay(), daysToAdd);
1388         return LocalDate.ofEpochDay(mjDay);
1389     }
1390 
1391     //-----------------------------------------------------------------------
1392     /**
1393      * Returns a copy of this date with the specified amount subtracted.
1394      * <p>
1395      * This returns a {@code LocalDate}, based on this one, with the specified amount subtracted.
1396      * The amount is typically {@link Period} but may be any other type implementing
1397      * the {@link TemporalAmount} interface.
1398      * <p>
1399      * The calculation is delegated to the amount object by calling
1400      * {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free
1401      * to implement the subtraction in any way it wishes, however it typically
1402      * calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation
1403      * of the amount implementation to determine if it can be successfully subtracted.
1404      * <p>
1405      * This instance is immutable and unaffected by this method call.
1406      *
1407      * @param amountToSubtract  the amount to subtract, not null
1408      * @return a {@code LocalDate} based on this date with the subtraction made, not null
1409      * @throws DateTimeException if the subtraction cannot be made
1410      * @throws ArithmeticException if numeric overflow occurs
1411      */
1412     @Override
minus(TemporalAmount amountToSubtract)1413     public LocalDate minus(TemporalAmount amountToSubtract) {
1414         if (amountToSubtract instanceof Period periodToSubtract) {
1415             return minusMonths(periodToSubtract.toTotalMonths()).minusDays(periodToSubtract.getDays());
1416         }
1417         Objects.requireNonNull(amountToSubtract, "amountToSubtract");
1418         return (LocalDate) amountToSubtract.subtractFrom(this);
1419     }
1420 
1421     /**
1422      * Returns a copy of this date with the specified amount subtracted.
1423      * <p>
1424      * This returns a {@code LocalDate}, based on this one, with the amount
1425      * in terms of the unit subtracted. If it is not possible to subtract the amount,
1426      * because the unit is not supported or for some other reason, an exception is thrown.
1427      * <p>
1428      * This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.
1429      * See that method for a full description of how addition, and thus subtraction, works.
1430      * <p>
1431      * This instance is immutable and unaffected by this method call.
1432      *
1433      * @param amountToSubtract  the amount of the unit to subtract from the result, may be negative
1434      * @param unit  the unit of the amount to subtract, not null
1435      * @return a {@code LocalDate} based on this date with the specified amount subtracted, not null
1436      * @throws DateTimeException if the subtraction cannot be made
1437      * @throws UnsupportedTemporalTypeException if the unit is not supported
1438      * @throws ArithmeticException if numeric overflow occurs
1439      */
1440     @Override
minus(long amountToSubtract, TemporalUnit unit)1441     public LocalDate minus(long amountToSubtract, TemporalUnit unit) {
1442         return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
1443     }
1444 
1445     //-----------------------------------------------------------------------
1446     /**
1447      * Returns a copy of this {@code LocalDate} with the specified number of years subtracted.
1448      * <p>
1449      * This method subtracts the specified amount from the years field in three steps:
1450      * <ol>
1451      * <li>Subtract the input years from the year field</li>
1452      * <li>Check if the resulting date would be invalid</li>
1453      * <li>Adjust the day-of-month to the last valid day if necessary</li>
1454      * </ol>
1455      * <p>
1456      * For example, 2008-02-29 (leap year) minus one year would result in the
1457      * invalid date 2007-02-29 (standard year). Instead of returning an invalid
1458      * result, the last valid day of the month, 2007-02-28, is selected instead.
1459      * <p>
1460      * This instance is immutable and unaffected by this method call.
1461      *
1462      * @param yearsToSubtract  the years to subtract, may be negative
1463      * @return a {@code LocalDate} based on this date with the years subtracted, not null
1464      * @throws DateTimeException if the result exceeds the supported date range
1465      */
minusYears(long yearsToSubtract)1466     public LocalDate minusYears(long yearsToSubtract) {
1467         return (yearsToSubtract == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-yearsToSubtract));
1468     }
1469 
1470     /**
1471      * Returns a copy of this {@code LocalDate} with the specified number of months subtracted.
1472      * <p>
1473      * This method subtracts the specified amount from the months field in three steps:
1474      * <ol>
1475      * <li>Subtract the input months from the month-of-year field</li>
1476      * <li>Check if the resulting date would be invalid</li>
1477      * <li>Adjust the day-of-month to the last valid day if necessary</li>
1478      * </ol>
1479      * <p>
1480      * For example, 2007-03-31 minus one month would result in the invalid date
1481      * 2007-02-31. Instead of returning an invalid result, the last valid day
1482      * of the month, 2007-02-28, is selected instead.
1483      * <p>
1484      * This instance is immutable and unaffected by this method call.
1485      *
1486      * @param monthsToSubtract  the months to subtract, may be negative
1487      * @return a {@code LocalDate} based on this date with the months subtracted, not null
1488      * @throws DateTimeException if the result exceeds the supported date range
1489      */
minusMonths(long monthsToSubtract)1490     public LocalDate minusMonths(long monthsToSubtract) {
1491         return (monthsToSubtract == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-monthsToSubtract));
1492     }
1493 
1494     /**
1495      * Returns a copy of this {@code LocalDate} with the specified number of weeks subtracted.
1496      * <p>
1497      * This method subtracts the specified amount in weeks from the days field decrementing
1498      * the month and year fields as necessary to ensure the result remains valid.
1499      * The result is only invalid if the maximum/minimum year is exceeded.
1500      * <p>
1501      * For example, 2009-01-07 minus one week would result in 2008-12-31.
1502      * <p>
1503      * This instance is immutable and unaffected by this method call.
1504      *
1505      * @param weeksToSubtract  the weeks to subtract, may be negative
1506      * @return a {@code LocalDate} based on this date with the weeks subtracted, not null
1507      * @throws DateTimeException if the result exceeds the supported date range
1508      */
minusWeeks(long weeksToSubtract)1509     public LocalDate minusWeeks(long weeksToSubtract) {
1510         return (weeksToSubtract == Long.MIN_VALUE ? plusWeeks(Long.MAX_VALUE).plusWeeks(1) : plusWeeks(-weeksToSubtract));
1511     }
1512 
1513     /**
1514      * Returns a copy of this {@code LocalDate} with the specified number of days subtracted.
1515      * <p>
1516      * This method subtracts the specified amount from the days field decrementing the
1517      * month and year fields as necessary to ensure the result remains valid.
1518      * The result is only invalid if the maximum/minimum year is exceeded.
1519      * <p>
1520      * For example, 2009-01-01 minus one day would result in 2008-12-31.
1521      * <p>
1522      * This instance is immutable and unaffected by this method call.
1523      *
1524      * @param daysToSubtract  the days to subtract, may be negative
1525      * @return a {@code LocalDate} based on this date with the days subtracted, not null
1526      * @throws DateTimeException if the result exceeds the supported date range
1527      */
minusDays(long daysToSubtract)1528     public LocalDate minusDays(long daysToSubtract) {
1529         return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));
1530     }
1531 
1532     //-----------------------------------------------------------------------
1533     /**
1534      * Queries this date using the specified query.
1535      * <p>
1536      * This queries this date using the specified query strategy object.
1537      * The {@code TemporalQuery} object defines the logic to be used to
1538      * obtain the result. Read the documentation of the query to understand
1539      * what the result of this method will be.
1540      * <p>
1541      * The result of this method is obtained by invoking the
1542      * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the
1543      * specified query passing {@code this} as the argument.
1544      *
1545      * @param <R> the type of the result
1546      * @param query  the query to invoke, not null
1547      * @return the query result, null may be returned (defined by the query)
1548      * @throws DateTimeException if unable to query (defined by the query)
1549      * @throws ArithmeticException if numeric overflow occurs (defined by the query)
1550      */
1551     @SuppressWarnings("unchecked")
1552     @Override
query(TemporalQuery<R> query)1553     public <R> R query(TemporalQuery<R> query) {
1554         if (query == TemporalQueries.localDate()) {
1555             return (R) this;
1556         }
1557         return ChronoLocalDate.super.query(query);
1558     }
1559 
1560     /**
1561      * Adjusts the specified temporal object to have the same date as this object.
1562      * <p>
1563      * This returns a temporal object of the same observable type as the input
1564      * with the date changed to be the same as this.
1565      * <p>
1566      * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}
1567      * passing {@link ChronoField#EPOCH_DAY} as the field.
1568      * <p>
1569      * In most cases, it is clearer to reverse the calling pattern by using
1570      * {@link Temporal#with(TemporalAdjuster)}:
1571      * <pre>
1572      *   // these two lines are equivalent, but the second approach is recommended
1573      *   temporal = thisLocalDate.adjustInto(temporal);
1574      *   temporal = temporal.with(thisLocalDate);
1575      * </pre>
1576      * <p>
1577      * This instance is immutable and unaffected by this method call.
1578      *
1579      * @param temporal  the target object to be adjusted, not null
1580      * @return the adjusted object, not null
1581      * @throws DateTimeException if unable to make the adjustment
1582      * @throws ArithmeticException if numeric overflow occurs
1583      */
1584     @Override  // override for Javadoc
adjustInto(Temporal temporal)1585     public Temporal adjustInto(Temporal temporal) {
1586         return ChronoLocalDate.super.adjustInto(temporal);
1587     }
1588 
1589     /**
1590      * Calculates the amount of time until another date in terms of the specified unit.
1591      * <p>
1592      * This calculates the amount of time between two {@code LocalDate}
1593      * objects in terms of a single {@code TemporalUnit}.
1594      * The start and end points are {@code this} and the specified date.
1595      * The result will be negative if the end is before the start.
1596      * The {@code Temporal} passed to this method is converted to a
1597      * {@code LocalDate} using {@link #from(TemporalAccessor)}.
1598      * For example, the amount in days between two dates can be calculated
1599      * using {@code startDate.until(endDate, DAYS)}.
1600      * <p>
1601      * The calculation returns a whole number, representing the number of
1602      * complete units between the two dates.
1603      * For example, the amount in months between 2012-06-15 and 2012-08-14
1604      * will only be one month as it is one day short of two months.
1605      * <p>
1606      * There are two equivalent ways of using this method.
1607      * The first is to invoke this method.
1608      * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
1609      * <pre>
1610      *   // these two lines are equivalent
1611      *   amount = start.until(end, MONTHS);
1612      *   amount = MONTHS.between(start, end);
1613      * </pre>
1614      * The choice should be made based on which makes the code more readable.
1615      * <p>
1616      * The calculation is implemented in this method for {@link ChronoUnit}.
1617      * The units {@code DAYS}, {@code WEEKS}, {@code MONTHS}, {@code YEARS},
1618      * {@code DECADES}, {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS}
1619      * are supported. Other {@code ChronoUnit} values will throw an exception.
1620      * <p>
1621      * If the unit is not a {@code ChronoUnit}, then the result of this method
1622      * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
1623      * passing {@code this} as the first argument and the converted input temporal
1624      * as the second argument.
1625      * <p>
1626      * This instance is immutable and unaffected by this method call.
1627      *
1628      * @param endExclusive  the end date, exclusive, which is converted to a {@code LocalDate}, not null
1629      * @param unit  the unit to measure the amount in, not null
1630      * @return the amount of time between this date and the end date
1631      * @throws DateTimeException if the amount cannot be calculated, or the end
1632      *  temporal cannot be converted to a {@code LocalDate}
1633      * @throws UnsupportedTemporalTypeException if the unit is not supported
1634      * @throws ArithmeticException if numeric overflow occurs
1635      */
1636     @Override
until(Temporal endExclusive, TemporalUnit unit)1637     public long until(Temporal endExclusive, TemporalUnit unit) {
1638         LocalDate end = LocalDate.from(endExclusive);
1639         if (unit instanceof ChronoUnit) {
1640             switch ((ChronoUnit) unit) {
1641                 case DAYS: return daysUntil(end);
1642                 case WEEKS: return daysUntil(end) / 7;
1643                 case MONTHS: return monthsUntil(end);
1644                 case YEARS: return monthsUntil(end) / 12;
1645                 case DECADES: return monthsUntil(end) / 120;
1646                 case CENTURIES: return monthsUntil(end) / 1200;
1647                 case MILLENNIA: return monthsUntil(end) / 12000;
1648                 case ERAS: return end.getLong(ERA) - getLong(ERA);
1649             }
1650             throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
1651         }
1652         return unit.between(this, end);
1653     }
1654 
daysUntil(LocalDate end)1655     long daysUntil(LocalDate end) {
1656         return end.toEpochDay() - toEpochDay();  // no overflow
1657     }
1658 
monthsUntil(LocalDate end)1659     private long monthsUntil(LocalDate end) {
1660         long packed1 = getProlepticMonth() * 32L + getDayOfMonth();  // no overflow
1661         long packed2 = end.getProlepticMonth() * 32L + end.getDayOfMonth();  // no overflow
1662         return (packed2 - packed1) / 32;
1663     }
1664 
1665     /**
1666      * Calculates the period between this date and another date as a {@code Period}.
1667      * <p>
1668      * This calculates the period between two dates in terms of years, months and days.
1669      * The start and end points are {@code this} and the specified date.
1670      * The result will be negative if the end is before the start.
1671      * The negative sign will be the same in each of year, month and day.
1672      * <p>
1673      * The calculation is performed using the ISO calendar system.
1674      * If necessary, the input date will be converted to ISO.
1675      * <p>
1676      * The start date is included, but the end date is not.
1677      * The period is calculated by removing complete months, then calculating
1678      * the remaining number of days, adjusting to ensure that both have the same sign.
1679      * The number of months is then normalized into years and months based on a 12 month year.
1680      * A month is considered to be complete if the end day-of-month is greater
1681      * than or equal to the start day-of-month.
1682      * For example, from {@code 2010-01-15} to {@code 2011-03-18} is "1 year, 2 months and 3 days".
1683      * <p>
1684      * There are two equivalent ways of using this method.
1685      * The first is to invoke this method.
1686      * The second is to use {@link Period#between(LocalDate, LocalDate)}:
1687      * <pre>
1688      *   // these two lines are equivalent
1689      *   period = start.until(end);
1690      *   period = Period.between(start, end);
1691      * </pre>
1692      * The choice should be made based on which makes the code more readable.
1693      *
1694      * @param endDateExclusive  the end date, exclusive, which may be in any chronology, not null
1695      * @return the period between this date and the end date, not null
1696      */
1697     @Override
until(ChronoLocalDate endDateExclusive)1698     public Period until(ChronoLocalDate endDateExclusive) {
1699         LocalDate end = LocalDate.from(endDateExclusive);
1700         long totalMonths = end.getProlepticMonth() - this.getProlepticMonth();  // safe
1701         int days = end.day - this.day;
1702         if (totalMonths > 0 && days < 0) {
1703             totalMonths--;
1704             LocalDate calcDate = this.plusMonths(totalMonths);
1705             days = (int) (end.toEpochDay() - calcDate.toEpochDay());  // safe
1706         } else if (totalMonths < 0 && days > 0) {
1707             totalMonths++;
1708             days -= end.lengthOfMonth();
1709         }
1710         long years = totalMonths / 12;  // safe
1711         int months = (int) (totalMonths % 12);  // safe
1712         return Period.of(Math.toIntExact(years), months, days);
1713     }
1714 
1715     /**
1716      * Returns a sequential ordered stream of dates. The returned stream starts from this date
1717      * (inclusive) and goes to {@code endExclusive} (exclusive) by an incremental step of 1 day.
1718      * <p>
1719      * This method is equivalent to {@code datesUntil(endExclusive, Period.ofDays(1))}.
1720      *
1721      * @param endExclusive  the end date, exclusive, not null
1722      * @return a sequential {@code Stream} for the range of {@code LocalDate} values
1723      * @throws IllegalArgumentException if end date is before this date
1724      * @since 9
1725      */
datesUntil(LocalDate endExclusive)1726     public Stream<LocalDate> datesUntil(LocalDate endExclusive) {
1727         long end = endExclusive.toEpochDay();
1728         long start = toEpochDay();
1729         if (end < start) {
1730             throw new IllegalArgumentException(endExclusive + " < " + this);
1731         }
1732         return LongStream.range(start, end).mapToObj(LocalDate::ofEpochDay);
1733     }
1734 
1735     /**
1736      * Returns a sequential ordered stream of dates by given incremental step. The returned stream
1737      * starts from this date (inclusive) and goes to {@code endExclusive} (exclusive).
1738      * <p>
1739      * The n-th date which appears in the stream is equal to {@code this.plus(step.multipliedBy(n))}
1740      * (but the result of step multiplication never overflows). For example, if this date is
1741      * {@code 2015-01-31}, the end date is {@code 2015-05-01} and the step is 1 month, then the
1742      * stream contains {@code 2015-01-31}, {@code 2015-02-28}, {@code 2015-03-31}, and
1743      * {@code 2015-04-30}.
1744      *
1745      * @param endExclusive  the end date, exclusive, not null
1746      * @param step  the non-zero, non-negative {@code Period} which represents the step.
1747      * @return a sequential {@code Stream} for the range of {@code LocalDate} values
1748      * @throws IllegalArgumentException if step is zero, or {@code step.getDays()} and
1749      *             {@code step.toTotalMonths()} have opposite sign, or end date is before this date
1750      *             and step is positive, or end date is after this date and step is negative
1751      * @since 9
1752      */
datesUntil(LocalDate endExclusive, Period step)1753     public Stream<LocalDate> datesUntil(LocalDate endExclusive, Period step) {
1754         if (step.isZero()) {
1755             throw new IllegalArgumentException("step is zero");
1756         }
1757         long end = endExclusive.toEpochDay();
1758         long start = toEpochDay();
1759         long until = end - start;
1760         long months = step.toTotalMonths();
1761         long days = step.getDays();
1762         if ((months < 0 && days > 0) || (months > 0 && days < 0)) {
1763             throw new IllegalArgumentException("period months and days are of opposite sign");
1764         }
1765         if (until == 0) {
1766             return Stream.empty();
1767         }
1768         int sign = months > 0 || days > 0 ? 1 : -1;
1769         if (sign < 0 ^ until < 0) {
1770             throw new IllegalArgumentException(endExclusive + (sign < 0 ? " > " : " < ") + this);
1771         }
1772         if (months == 0) {
1773             long steps = (until - sign) / days; // non-negative
1774             return LongStream.rangeClosed(0, steps).mapToObj(
1775                     n -> LocalDate.ofEpochDay(start + n * days));
1776         }
1777         // 48699/1600 = 365.2425/12, no overflow, non-negative result
1778         long steps = until * 1600 / (months * 48699 + days * 1600) + 1;
1779         long addMonths = months * steps;
1780         long addDays = days * steps;
1781         long maxAddMonths = months > 0 ? MAX.getProlepticMonth() - getProlepticMonth()
1782                 : getProlepticMonth() - MIN.getProlepticMonth();
1783         // adjust steps estimation
1784         if (addMonths * sign > maxAddMonths
1785                 || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) {
1786             steps--;
1787             addMonths -= months;
1788             addDays -= days;
1789             if (addMonths * sign > maxAddMonths
1790                     || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) {
1791                 steps--;
1792             }
1793         }
1794         return LongStream.rangeClosed(0, steps).mapToObj(
1795                 n -> this.plusMonths(months * n).plusDays(days * n));
1796     }
1797 
1798     /**
1799      * Formats this date using the specified formatter.
1800      * <p>
1801      * This date will be passed to the formatter to produce a string.
1802      *
1803      * @param formatter  the formatter to use, not null
1804      * @return the formatted date string, not null
1805      * @throws DateTimeException if an error occurs during printing
1806      */
1807     @Override  // override for Javadoc and performance
format(DateTimeFormatter formatter)1808     public String format(DateTimeFormatter formatter) {
1809         Objects.requireNonNull(formatter, "formatter");
1810         return formatter.format(this);
1811     }
1812 
1813     //-----------------------------------------------------------------------
1814     /**
1815      * Combines this date with a time to create a {@code LocalDateTime}.
1816      * <p>
1817      * This returns a {@code LocalDateTime} formed from this date at the specified time.
1818      * All possible combinations of date and time are valid.
1819      *
1820      * @param time  the time to combine with, not null
1821      * @return the local date-time formed from this date and the specified time, not null
1822      */
1823     @Override
atTime(LocalTime time)1824     public LocalDateTime atTime(LocalTime time) {
1825         return LocalDateTime.of(this, time);
1826     }
1827 
1828     /**
1829      * Combines this date with a time to create a {@code LocalDateTime}.
1830      * <p>
1831      * This returns a {@code LocalDateTime} formed from this date at the
1832      * specified hour and minute.
1833      * The seconds and nanosecond fields will be set to zero.
1834      * The individual time fields must be within their valid range.
1835      * All possible combinations of date and time are valid.
1836      *
1837      * @param hour  the hour-of-day to use, from 0 to 23
1838      * @param minute  the minute-of-hour to use, from 0 to 59
1839      * @return the local date-time formed from this date and the specified time, not null
1840      * @throws DateTimeException if the value of any field is out of range
1841      */
atTime(int hour, int minute)1842     public LocalDateTime atTime(int hour, int minute) {
1843         return atTime(LocalTime.of(hour, minute));
1844     }
1845 
1846     /**
1847      * Combines this date with a time to create a {@code LocalDateTime}.
1848      * <p>
1849      * This returns a {@code LocalDateTime} formed from this date at the
1850      * specified hour, minute and second.
1851      * The nanosecond field will be set to zero.
1852      * The individual time fields must be within their valid range.
1853      * All possible combinations of date and time are valid.
1854      *
1855      * @param hour  the hour-of-day to use, from 0 to 23
1856      * @param minute  the minute-of-hour to use, from 0 to 59
1857      * @param second  the second-of-minute to represent, from 0 to 59
1858      * @return the local date-time formed from this date and the specified time, not null
1859      * @throws DateTimeException if the value of any field is out of range
1860      */
atTime(int hour, int minute, int second)1861     public LocalDateTime atTime(int hour, int minute, int second) {
1862         return atTime(LocalTime.of(hour, minute, second));
1863     }
1864 
1865     /**
1866      * Combines this date with a time to create a {@code LocalDateTime}.
1867      * <p>
1868      * This returns a {@code LocalDateTime} formed from this date at the
1869      * specified hour, minute, second and nanosecond.
1870      * The individual time fields must be within their valid range.
1871      * All possible combinations of date and time are valid.
1872      *
1873      * @param hour  the hour-of-day to use, from 0 to 23
1874      * @param minute  the minute-of-hour to use, from 0 to 59
1875      * @param second  the second-of-minute to represent, from 0 to 59
1876      * @param nanoOfSecond  the nano-of-second to represent, from 0 to 999,999,999
1877      * @return the local date-time formed from this date and the specified time, not null
1878      * @throws DateTimeException if the value of any field is out of range
1879      */
atTime(int hour, int minute, int second, int nanoOfSecond)1880     public LocalDateTime atTime(int hour, int minute, int second, int nanoOfSecond) {
1881         return atTime(LocalTime.of(hour, minute, second, nanoOfSecond));
1882     }
1883 
1884     /**
1885      * Combines this date with an offset time to create an {@code OffsetDateTime}.
1886      * <p>
1887      * This returns an {@code OffsetDateTime} formed from this date at the specified time.
1888      * All possible combinations of date and time are valid.
1889      *
1890      * @param time  the time to combine with, not null
1891      * @return the offset date-time formed from this date and the specified time, not null
1892      */
atTime(OffsetTime time)1893     public OffsetDateTime atTime(OffsetTime time) {
1894         return OffsetDateTime.of(LocalDateTime.of(this, time.toLocalTime()), time.getOffset());
1895     }
1896 
1897     /**
1898      * Combines this date with the time of midnight to create a {@code LocalDateTime}
1899      * at the start of this date.
1900      * <p>
1901      * This returns a {@code LocalDateTime} formed from this date at the time of
1902      * midnight, 00:00, at the start of this date.
1903      *
1904      * @return the local date-time of midnight at the start of this date, not null
1905      */
atStartOfDay()1906     public LocalDateTime atStartOfDay() {
1907         return LocalDateTime.of(this, LocalTime.MIDNIGHT);
1908     }
1909 
1910     /**
1911      * Returns a zoned date-time from this date at the earliest valid time according
1912      * to the rules in the time-zone.
1913      * <p>
1914      * Time-zone rules, such as daylight savings, mean that not every local date-time
1915      * is valid for the specified zone, thus the local date-time may not be midnight.
1916      * <p>
1917      * In most cases, there is only one valid offset for a local date-time.
1918      * In the case of an overlap, there are two valid offsets, and the earlier one is used,
1919      * corresponding to the first occurrence of midnight on the date.
1920      * In the case of a gap, the zoned date-time will represent the instant just after the gap.
1921      * <p>
1922      * If the zone ID is a {@link ZoneOffset}, then the result always has a time of midnight.
1923      * <p>
1924      * To convert to a specific time in a given time-zone call {@link #atTime(LocalTime)}
1925      * followed by {@link LocalDateTime#atZone(ZoneId)}.
1926      *
1927      * @param zone  the zone ID to use, not null
1928      * @return the zoned date-time formed from this date and the earliest valid time for the zone, not null
1929      */
atStartOfDay(ZoneId zone)1930     public ZonedDateTime atStartOfDay(ZoneId zone) {
1931         Objects.requireNonNull(zone, "zone");
1932         // need to handle case where there is a gap from 11:30 to 00:30
1933         // standard ZDT factory would result in 01:00 rather than 00:30
1934         LocalDateTime ldt = atTime(LocalTime.MIDNIGHT);
1935         if (!(zone instanceof ZoneOffset)) {
1936             ZoneRules rules = zone.getRules();
1937             ZoneOffsetTransition trans = rules.getTransition(ldt);
1938             if (trans != null && trans.isGap()) {
1939                 ldt = trans.getDateTimeAfter();
1940             }
1941         }
1942         return ZonedDateTime.of(ldt, zone);
1943     }
1944 
1945     //-----------------------------------------------------------------------
1946     @Override
toEpochDay()1947     public long toEpochDay() {
1948         long y = year;
1949         long m = month;
1950         long total = 0;
1951         total += 365 * y;
1952         if (y >= 0) {
1953             total += (y + 3) / 4 - (y + 99) / 100 + (y + 399) / 400;
1954         } else {
1955             total -= y / -4 - y / -100 + y / -400;
1956         }
1957         total += ((367 * m - 362) / 12);
1958         total += day - 1;
1959         if (m > 2) {
1960             total--;
1961             if (isLeapYear() == false) {
1962                 total--;
1963             }
1964         }
1965         return total - DAYS_0000_TO_1970;
1966     }
1967 
1968     /**
1969      * Converts this {@code LocalDate} to the number of seconds since the epoch
1970      * of 1970-01-01T00:00:00Z.
1971      * <p>
1972      * This combines this local date with the specified time and
1973      * offset to calculate the epoch-second value, which is the
1974      * number of elapsed seconds from 1970-01-01T00:00:00Z.
1975      * Instants on the time-line after the epoch are positive, earlier
1976      * are negative.
1977      *
1978      * @param time the local time, not null
1979      * @param offset the zone offset, not null
1980      * @return the number of seconds since the epoch of 1970-01-01T00:00:00Z, may be negative
1981      * @since 9
1982      */
toEpochSecond(LocalTime time, ZoneOffset offset)1983     public long toEpochSecond(LocalTime time, ZoneOffset offset) {
1984         Objects.requireNonNull(time, "time");
1985         Objects.requireNonNull(offset, "offset");
1986         long secs = toEpochDay() * SECONDS_PER_DAY + time.toSecondOfDay();
1987         secs -= offset.getTotalSeconds();
1988         return secs;
1989     }
1990 
1991     //-----------------------------------------------------------------------
1992     /**
1993      * Compares this date to another date.
1994      * <p>
1995      * The comparison is primarily based on the date, from earliest to latest.
1996      * It is "consistent with equals", as defined by {@link Comparable}.
1997      * <p>
1998      * If all the dates being compared are instances of {@code LocalDate},
1999      * then the comparison will be entirely based on the date.
2000      * If some dates being compared are in different chronologies, then the
2001      * chronology is also considered, see {@link java.time.chrono.ChronoLocalDate#compareTo}.
2002      *
2003      * @param other  the other date to compare to, not null
2004      * @return the comparator value, negative if less, positive if greater
2005      */
2006     @Override  // override for Javadoc and performance
compareTo(ChronoLocalDate other)2007     public int compareTo(ChronoLocalDate other) {
2008         if (other instanceof LocalDate) {
2009             return compareTo0((LocalDate) other);
2010         }
2011         return ChronoLocalDate.super.compareTo(other);
2012     }
2013 
compareTo0(LocalDate otherDate)2014     int compareTo0(LocalDate otherDate) {
2015         int cmp = (year - otherDate.year);
2016         if (cmp == 0) {
2017             cmp = (month - otherDate.month);
2018             if (cmp == 0) {
2019                 cmp = (day - otherDate.day);
2020             }
2021         }
2022         return cmp;
2023     }
2024 
2025     /**
2026      * Checks if this date is after the specified date.
2027      * <p>
2028      * This checks to see if this date represents a point on the
2029      * local time-line after the other date.
2030      * <pre>
2031      *   LocalDate a = LocalDate.of(2012, 6, 30);
2032      *   LocalDate b = LocalDate.of(2012, 7, 1);
2033      *   a.isAfter(b) == false
2034      *   a.isAfter(a) == false
2035      *   b.isAfter(a) == true
2036      * </pre>
2037      * <p>
2038      * This method only considers the position of the two dates on the local time-line.
2039      * It does not take into account the chronology, or calendar system.
2040      * This is different from the comparison in {@link #compareTo(ChronoLocalDate)},
2041      * but is the same approach as {@link ChronoLocalDate#timeLineOrder()}.
2042      *
2043      * @param other  the other date to compare to, not null
2044      * @return true if this date is after the specified date
2045      */
2046     @Override  // override for Javadoc and performance
isAfter(ChronoLocalDate other)2047     public boolean isAfter(ChronoLocalDate other) {
2048         if (other instanceof LocalDate) {
2049             return compareTo0((LocalDate) other) > 0;
2050         }
2051         return ChronoLocalDate.super.isAfter(other);
2052     }
2053 
2054     /**
2055      * Checks if this date is before the specified date.
2056      * <p>
2057      * This checks to see if this date represents a point on the
2058      * local time-line before the other date.
2059      * <pre>
2060      *   LocalDate a = LocalDate.of(2012, 6, 30);
2061      *   LocalDate b = LocalDate.of(2012, 7, 1);
2062      *   a.isBefore(b) == true
2063      *   a.isBefore(a) == false
2064      *   b.isBefore(a) == false
2065      * </pre>
2066      * <p>
2067      * This method only considers the position of the two dates on the local time-line.
2068      * It does not take into account the chronology, or calendar system.
2069      * This is different from the comparison in {@link #compareTo(ChronoLocalDate)},
2070      * but is the same approach as {@link ChronoLocalDate#timeLineOrder()}.
2071      *
2072      * @param other  the other date to compare to, not null
2073      * @return true if this date is before the specified date
2074      */
2075     @Override  // override for Javadoc and performance
isBefore(ChronoLocalDate other)2076     public boolean isBefore(ChronoLocalDate other) {
2077         if (other instanceof LocalDate) {
2078             return compareTo0((LocalDate) other) < 0;
2079         }
2080         return ChronoLocalDate.super.isBefore(other);
2081     }
2082 
2083     /**
2084      * Checks if this date is equal to the specified date.
2085      * <p>
2086      * This checks to see if this date represents the same point on the
2087      * local time-line as the other date.
2088      * <pre>
2089      *   LocalDate a = LocalDate.of(2012, 6, 30);
2090      *   LocalDate b = LocalDate.of(2012, 7, 1);
2091      *   a.isEqual(b) == false
2092      *   a.isEqual(a) == true
2093      *   b.isEqual(a) == false
2094      * </pre>
2095      * <p>
2096      * This method only considers the position of the two dates on the local time-line.
2097      * It does not take into account the chronology, or calendar system.
2098      * This is different from the comparison in {@link #compareTo(ChronoLocalDate)}
2099      * but is the same approach as {@link ChronoLocalDate#timeLineOrder()}.
2100      *
2101      * @param other  the other date to compare to, not null
2102      * @return true if this date is equal to the specified date
2103      */
2104     @Override  // override for Javadoc and performance
isEqual(ChronoLocalDate other)2105     public boolean isEqual(ChronoLocalDate other) {
2106         if (other instanceof LocalDate) {
2107             return compareTo0((LocalDate) other) == 0;
2108         }
2109         return ChronoLocalDate.super.isEqual(other);
2110     }
2111 
2112     //-----------------------------------------------------------------------
2113     /**
2114      * Checks if this date is equal to another date.
2115      * <p>
2116      * Compares this {@code LocalDate} with another ensuring that the date is the same.
2117      * <p>
2118      * Only objects of type {@code LocalDate} are compared, other types return false.
2119      * To compare the dates of two {@code TemporalAccessor} instances, including dates
2120      * in two different chronologies, use {@link ChronoField#EPOCH_DAY} as a comparator.
2121      *
2122      * @param obj  the object to check, null returns false
2123      * @return true if this is equal to the other date
2124      */
2125     @Override
equals(Object obj)2126     public boolean equals(Object obj) {
2127         if (this == obj) {
2128             return true;
2129         }
2130         if (obj instanceof LocalDate) {
2131             return compareTo0((LocalDate) obj) == 0;
2132         }
2133         return false;
2134     }
2135 
2136     /**
2137      * A hash code for this date.
2138      *
2139      * @return a suitable hash code
2140      */
2141     @Override
hashCode()2142     public int hashCode() {
2143         int yearValue = year;
2144         int monthValue = month;
2145         int dayValue = day;
2146         return (yearValue & 0xFFFFF800) ^ ((yearValue << 11) + (monthValue << 6) + (dayValue));
2147     }
2148 
2149     //-----------------------------------------------------------------------
2150     /**
2151      * Outputs this date as a {@code String}, such as {@code 2007-12-03}.
2152      * <p>
2153      * The output will be in the ISO-8601 format {@code uuuu-MM-dd}.
2154      *
2155      * @return a string representation of this date, not null
2156      */
2157     @Override
toString()2158     public String toString() {
2159         int yearValue = year;
2160         int monthValue = month;
2161         int dayValue = day;
2162         int absYear = Math.abs(yearValue);
2163         StringBuilder buf = new StringBuilder(10);
2164         if (absYear < 1000) {
2165             if (yearValue < 0) {
2166                 buf.append(yearValue - 10000).deleteCharAt(1);
2167             } else {
2168                 buf.append(yearValue + 10000).deleteCharAt(0);
2169             }
2170         } else {
2171             if (yearValue > 9999) {
2172                 buf.append('+');
2173             }
2174             buf.append(yearValue);
2175         }
2176         return buf.append(monthValue < 10 ? "-0" : "-")
2177             .append(monthValue)
2178             .append(dayValue < 10 ? "-0" : "-")
2179             .append(dayValue)
2180             .toString();
2181     }
2182 
2183     //-----------------------------------------------------------------------
2184     /**
2185      * Writes the object using a
2186      * <a href="{@docRoot}/serialized-form.html#java.time.Ser">dedicated serialized form</a>.
2187      * @serialData
2188      * <pre>
2189      *  out.writeByte(3);  // identifies a LocalDate
2190      *  out.writeInt(year);
2191      *  out.writeByte(month);
2192      *  out.writeByte(day);
2193      * </pre>
2194      *
2195      * @return the instance of {@code Ser}, not null
2196      */
2197     @java.io.Serial
writeReplace()2198     private Object writeReplace() {
2199         return new Ser(Ser.LOCAL_DATE_TYPE, this);
2200     }
2201 
2202     /**
2203      * Defend against malicious streams.
2204      *
2205      * @param s the stream to read
2206      * @throws InvalidObjectException always
2207      */
2208     @java.io.Serial
readObject(ObjectInputStream s)2209     private void readObject(ObjectInputStream s) throws InvalidObjectException {
2210         throw new InvalidObjectException("Deserialization via serialization delegate");
2211     }
2212 
writeExternal(DataOutput out)2213     void writeExternal(DataOutput out) throws IOException {
2214         out.writeInt(year);
2215         out.writeByte(month);
2216         out.writeByte(day);
2217     }
2218 
readExternal(DataInput in)2219     static LocalDate readExternal(DataInput in) throws IOException {
2220         int year = in.readInt();
2221         int month = in.readByte();
2222         int dayOfMonth = in.readByte();
2223         return LocalDate.of(year, month, dayOfMonth);
2224     }
2225 
2226 }
2227