001/*
002 * Copyright (c) 2007-2013, Stephen Colebourne & Michael Nascimento Santos
003 *
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions are met:
008 *
009 *  * Redistributions of source code must retain the above copyright notice,
010 *    this list of conditions and the following disclaimer.
011 *
012 *  * Redistributions in binary form must reproduce the above copyright notice,
013 *    this list of conditions and the following disclaimer in the documentation
014 *    and/or other materials provided with the distribution.
015 *
016 *  * Neither the name of JSR-310 nor the names of its contributors
017 *    may be used to endorse or promote products derived from this software
018 *    without specific prior written permission.
019 *
020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031 */
032package org.threeten.bp;
033
034import static org.threeten.bp.LocalTime.SECONDS_PER_DAY;
035import static org.threeten.bp.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH;
036import static org.threeten.bp.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR;
037import static org.threeten.bp.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH;
038import static org.threeten.bp.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR;
039import static org.threeten.bp.temporal.ChronoField.DAY_OF_MONTH;
040import static org.threeten.bp.temporal.ChronoField.DAY_OF_YEAR;
041import static org.threeten.bp.temporal.ChronoField.EPOCH_DAY;
042import static org.threeten.bp.temporal.ChronoField.EPOCH_MONTH;
043import static org.threeten.bp.temporal.ChronoField.ERA;
044import static org.threeten.bp.temporal.ChronoField.MONTH_OF_YEAR;
045import static org.threeten.bp.temporal.ChronoField.YEAR;
046
047import java.io.DataInput;
048import java.io.DataOutput;
049import java.io.IOException;
050import java.io.InvalidObjectException;
051import java.io.ObjectStreamException;
052import java.io.Serializable;
053import java.util.Objects;
054
055import org.threeten.bp.format.DateTimeBuilder;
056import org.threeten.bp.format.DateTimeFormatter;
057import org.threeten.bp.format.DateTimeFormatters;
058import org.threeten.bp.format.DateTimeParseException;
059import org.threeten.bp.jdk8.DefaultInterfaceChronoLocalDate;
060import org.threeten.bp.jdk8.Jdk8Methods;
061import org.threeten.bp.temporal.ChronoField;
062import org.threeten.bp.temporal.ChronoLocalDate;
063import org.threeten.bp.temporal.ChronoUnit;
064import org.threeten.bp.temporal.Era;
065import org.threeten.bp.temporal.ISOChrono;
066import org.threeten.bp.temporal.Temporal;
067import org.threeten.bp.temporal.TemporalAccessor;
068import org.threeten.bp.temporal.TemporalAdder;
069import org.threeten.bp.temporal.TemporalAdjuster;
070import org.threeten.bp.temporal.TemporalAdjusters;
071import org.threeten.bp.temporal.TemporalField;
072import org.threeten.bp.temporal.TemporalQuery;
073import org.threeten.bp.temporal.TemporalSubtractor;
074import org.threeten.bp.temporal.TemporalUnit;
075import org.threeten.bp.temporal.ValueRange;
076import org.threeten.bp.zone.ZoneOffsetTransition;
077import org.threeten.bp.zone.ZoneRules;
078
079/**
080 * A date without a time-zone in the ISO-8601 calendar system,
081 * such as {@code 2007-12-03}.
082 * <p>
083 * {@code LocalDate} is an immutable date-time object that represents a date,
084 * often viewed as year-month-day. Other date fields, such as day-of-year,
085 * day-of-week and week-of-year, can also be accessed.
086 * For example, the value "2nd October 2007" can be stored in a {@code LocalDate}.
087 * <p>
088 * This class does not store or represent a time or time-zone.
089 * Instead, it is a description of the date, as used for birthdays.
090 * It cannot represent an instant on the time-line without additional information
091 * such as an offset or time-zone.
092 * <p>
093 * The ISO-8601 calendar system is the modern civil calendar system used today
094 * in most of the world. It is equivalent to the proleptic Gregorian calendar
095 * system, in which today's rules for leap years are applied for all time.
096 * For most applications written today, the ISO-8601 rules are entirely suitable.
097 * However, any application that makes use of historical dates, and requires them
098 * to be accurate will find the ISO-8601 approach unsuitable.
099 *
100 * <h3>Specification for implementors</h3>
101 * This class is immutable and thread-safe.
102 */
103public final class LocalDate
104        extends DefaultInterfaceChronoLocalDate<ISOChrono>
105        implements Temporal, TemporalAdjuster, ChronoLocalDate<ISOChrono>, Serializable {
106
107    /**
108     * The minimum supported {@code LocalDate}, '-999999999-01-01'.
109     * This could be used by an application as a "far past" date.
110     */
111    public static final LocalDate MIN = LocalDate.of(Year.MIN_VALUE, 1, 1);
112    /**
113     * The maximum supported {@code LocalDate}, '+999999999-12-31'.
114     * This could be used by an application as a "far future" date.
115     */
116    public static final LocalDate MAX = LocalDate.of(Year.MAX_VALUE, 12, 31);
117
118    /**
119     * Serialization version.
120     */
121    private static final long serialVersionUID = 2942565459149668126L;
122    /**
123     * The number of days in a 400 year cycle.
124     */
125    private static final int DAYS_PER_CYCLE = 146097;
126    /**
127     * The number of days from year zero to year 1970.
128     * There are five 400 year cycles from year zero to 2000.
129     * There are 7 leap years from 1970 to 2000.
130     */
131    static final long DAYS_0000_TO_1970 = (DAYS_PER_CYCLE * 5L) - (30L * 365L + 7L);
132
133    /**
134     * The year.
135     */
136    private final int year;
137    /**
138     * The month-of-year.
139     */
140    private final short month;
141    /**
142     * The day-of-month.
143     */
144    private final short day;
145
146    //-----------------------------------------------------------------------
147    /**
148     * Obtains the current date from the system clock in the default time-zone.
149     * <p>
150     * This will query the {@link Clock#systemDefaultZone() system clock} in the default
151     * time-zone to obtain the current date.
152     * <p>
153     * Using this method will prevent the ability to use an alternate clock for testing
154     * because the clock is hard-coded.
155     *
156     * @return the current date using the system clock and default time-zone, not null
157     */
158    public static LocalDate now() {
159        return now(Clock.systemDefaultZone());
160    }
161
162    /**
163     * Obtains the current date from the system clock in the specified time-zone.
164     * <p>
165     * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date.
166     * Specifying the time-zone avoids dependence on the default time-zone.
167     * <p>
168     * Using this method will prevent the ability to use an alternate clock for testing
169     * because the clock is hard-coded.
170     *
171     * @param zone  the zone ID to use, not null
172     * @return the current date using the system clock, not null
173     */
174    public static LocalDate now(ZoneId zone) {
175        return now(Clock.system(zone));
176    }
177
178    /**
179     * Obtains the current date from the specified clock.
180     * <p>
181     * This will query the specified clock to obtain the current date - today.
182     * Using this method allows the use of an alternate clock for testing.
183     * The alternate clock may be introduced using {@link Clock dependency injection}.
184     *
185     * @param clock  the clock to use, not null
186     * @return the current date, not null
187     */
188    public static LocalDate now(Clock clock) {
189        Objects.requireNonNull(clock, "clock");
190        // inline OffsetDate factory to avoid creating object and InstantProvider checks
191        final Instant now = clock.instant();  // called once
192        ZoneOffset offset = clock.getZone().getRules().getOffset(now);
193        long epochSec = now.getEpochSecond() + offset.getTotalSeconds();  // overflow caught later
194        long epochDay = Jdk8Methods.floorDiv(epochSec, SECONDS_PER_DAY);
195        return LocalDate.ofEpochDay(epochDay);
196    }
197
198    //-----------------------------------------------------------------------
199    /**
200     * Obtains an instance of {@code LocalDate} from a year, month and day.
201     * <p>
202     * The day must be valid for the year and month, otherwise an exception will be thrown.
203     *
204     * @param year  the year to represent, from MIN_YEAR to MAX_YEAR
205     * @param month  the month-of-year to represent, not null
206     * @param dayOfMonth  the day-of-month to represent, from 1 to 31
207     * @return the local date, not null
208     * @throws DateTimeException if the value of any field is out of range
209     * @throws DateTimeException if the day-of-month is invalid for the month-year
210     */
211    public static LocalDate of(int year, Month month, int dayOfMonth) {
212        YEAR.checkValidValue(year);
213        Objects.requireNonNull(month, "month");
214        DAY_OF_MONTH.checkValidValue(dayOfMonth);
215        return create(year, month, dayOfMonth);
216    }
217
218    /**
219     * Obtains an instance of {@code LocalDate} from a year, month and day.
220     * <p>
221     * The day must be valid for the year and month, otherwise an exception will be thrown.
222     *
223     * @param year  the year to represent, from MIN_YEAR to MAX_YEAR
224     * @param month  the month-of-year to represent, from 1 (January) to 12 (December)
225     * @param dayOfMonth  the day-of-month to represent, from 1 to 31
226     * @return the local date, not null
227     * @throws DateTimeException if the value of any field is out of range
228     * @throws DateTimeException if the day-of-month is invalid for the month-year
229     */
230    public static LocalDate of(int year, int month, int dayOfMonth) {
231        YEAR.checkValidValue(year);
232        MONTH_OF_YEAR.checkValidValue(month);
233        DAY_OF_MONTH.checkValidValue(dayOfMonth);
234        return create(year, Month.of(month), dayOfMonth);
235    }
236
237    //-----------------------------------------------------------------------
238    /**
239     * Obtains an instance of {@code LocalDate} from a year and day-of-year.
240     * <p>
241     * The day-of-year must be valid for the year, otherwise an exception will be thrown.
242     *
243     * @param year  the year to represent, from MIN_YEAR to MAX_YEAR
244     * @param dayOfYear  the day-of-year to represent, from 1 to 366
245     * @return the local date, not null
246     * @throws DateTimeException if the value of any field is out of range
247     * @throws DateTimeException if the day-of-year is invalid for the month-year
248     */
249    public static LocalDate ofYearDay(int year, int dayOfYear) {
250        YEAR.checkValidValue(year);
251        DAY_OF_YEAR.checkValidValue(dayOfYear);
252        boolean leap = ISOChrono.INSTANCE.isLeapYear(year);
253        if (dayOfYear == 366 && leap == false) {
254            throw new DateTimeException("Invalid date 'DayOfYear 366' as '" + year + "' is not a leap year");
255        }
256        Month moy = Month.of((dayOfYear - 1) / 31 + 1);
257        int monthEnd = moy.firstDayOfYear(leap) + moy.length(leap) - 1;
258        if (dayOfYear > monthEnd) {
259            moy = moy.plus(1);
260        }
261        int dom = dayOfYear - moy.firstDayOfYear(leap) + 1;
262        return create(year, moy, dom);
263    }
264
265    //-----------------------------------------------------------------------
266    /**
267     * Obtains an instance of {@code LocalDate} from the epoch day count.
268     * <p>
269     * The Epoch Day count is a simple incrementing count of days
270     * where day 0 is 1970-01-01. Negative numbers represent earlier days.
271     *
272     * @param epochDay  the Epoch Day to convert, based on the epoch 1970-01-01
273     * @return the local date, not null
274     * @throws DateTimeException if the epoch days exceeds the supported date range
275     */
276    public static LocalDate ofEpochDay(long epochDay) {
277        long zeroDay = epochDay + DAYS_0000_TO_1970;
278        // find the march-based year
279        zeroDay -= 60;  // adjust to 0000-03-01 so leap day is at end of four year cycle
280        long adjust = 0;
281        if (zeroDay < 0) {
282            // adjust negative years to positive for calculation
283            long adjustCycles = (zeroDay + 1) / DAYS_PER_CYCLE - 1;
284            adjust = adjustCycles * 400;
285            zeroDay += -adjustCycles * DAYS_PER_CYCLE;
286        }
287        long yearEst = (400 * zeroDay + 591) / DAYS_PER_CYCLE;
288        long doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400);
289        if (doyEst < 0) {
290            // fix estimate
291            yearEst--;
292            doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400);
293        }
294        yearEst += adjust;  // reset any negative year
295        int marchDoy0 = (int) doyEst;
296
297        // convert march-based values back to january-based
298        int marchMonth0 = (marchDoy0 * 5 + 2) / 153;
299        int month = (marchMonth0 + 2) % 12 + 1;
300        int dom = marchDoy0 - (marchMonth0 * 306 + 5) / 10 + 1;
301        yearEst += marchMonth0 / 10;
302
303        // check year now we are certain it is correct
304        int year = YEAR.checkValidIntValue(yearEst);
305        return new LocalDate(year, month, dom);
306    }
307
308    //-----------------------------------------------------------------------
309    /**
310     * Obtains an instance of {@code LocalDate} from a temporal object.
311     * <p>
312     * A {@code TemporalAccessor} represents some form of date and time information.
313     * This factory converts the arbitrary temporal object to an instance of {@code LocalDate}.
314     * <p>
315     * The conversion extracts the {@link ChronoField#EPOCH_DAY EPOCH_DAY} field.
316     * <p>
317     * This method matches the signature of the functional interface {@link TemporalQuery}
318     * allowing it to be used as a query via method reference, {@code LocalDate::from}.
319     *
320     * @param temporal  the temporal object to convert, not null
321     * @return the local date, not null
322     * @throws DateTimeException if unable to convert to a {@code LocalDate}
323     */
324    public static LocalDate from(TemporalAccessor temporal) {
325        if (temporal instanceof LocalDate) {
326            return (LocalDate) temporal;
327        } else if (temporal instanceof LocalDateTime) {
328            return ((LocalDateTime) temporal).getDate();
329        } else if (temporal instanceof ZonedDateTime) {
330            return ((ZonedDateTime) temporal).getDate();
331        }
332        // handle builder as a special case
333        if (temporal instanceof DateTimeBuilder) {
334            DateTimeBuilder builder = (DateTimeBuilder) temporal;
335            LocalDate date = builder.extract(LocalDate.class);
336            if (date != null) {
337                return date;
338            }
339        }
340        try {
341            return ofEpochDay(temporal.getLong(EPOCH_DAY));
342        } catch (DateTimeException ex) {
343            throw new DateTimeException("Unable to obtain LocalDate from TemporalAccessor: " + temporal.getClass(), ex);
344        }
345    }
346
347    //-----------------------------------------------------------------------
348    /**
349     * Obtains an instance of {@code LocalDate} from a text string such as {@code 2007-12-03}.
350     * <p>
351     * The string must represent a valid date and is parsed using
352     * {@link org.threeten.bp.format.DateTimeFormatters#isoLocalDate()}.
353     *
354     * @param text  the text to parse such as "2007-12-03", not null
355     * @return the parsed local date, not null
356     * @throws DateTimeParseException if the text cannot be parsed
357     */
358    public static LocalDate parse(CharSequence text) {
359        return parse(text, DateTimeFormatters.isoLocalDate());
360    }
361
362    /**
363     * Obtains an instance of {@code LocalDate} from a text string using a specific formatter.
364     * <p>
365     * The text is parsed using the formatter, returning a date.
366     *
367     * @param text  the text to parse, not null
368     * @param formatter  the formatter to use, not null
369     * @return the parsed local date, not null
370     * @throws DateTimeParseException if the text cannot be parsed
371     */
372    public static LocalDate parse(CharSequence text, DateTimeFormatter formatter) {
373        Objects.requireNonNull(formatter, "formatter");
374        return formatter.parse(text, LocalDate.class);
375    }
376
377    //-----------------------------------------------------------------------
378    /**
379     * Creates a local date from the year, month and day fields.
380     *
381     * @param year  the year to represent, validated from MIN_YEAR to MAX_YEAR
382     * @param month  the month-of-year to represent, validated not null
383     * @param dayOfMonth  the day-of-month to represent, validated from 1 to 31
384     * @return the local date, not null
385     * @throws DateTimeException if the day-of-month is invalid for the month-year
386     */
387    private static LocalDate create(int year, Month month, int dayOfMonth) {
388        if (dayOfMonth > 28 && dayOfMonth > month.length(ISOChrono.INSTANCE.isLeapYear(year))) {
389            if (dayOfMonth == 29) {
390                throw new DateTimeException("Invalid date 'February 29' as '" + year + "' is not a leap year");
391            } else {
392                throw new DateTimeException("Invalid date '" + month.name() + " " + dayOfMonth + "'");
393            }
394        }
395        return new LocalDate(year, month.getValue(), dayOfMonth);
396    }
397
398    /**
399     * Resolves the date, resolving days past the end of month.
400     *
401     * @param year  the year to represent, validated from MIN_YEAR to MAX_YEAR
402     * @param month  the month-of-year to represent, validated from 1 to 12
403     * @param day  the day-of-month to represent, validated from 1 to 31
404     * @return the resolved date, not null
405     */
406    private static LocalDate resolvePreviousValid(int year, int month, int day) {
407        switch (month) {
408            case 2:
409                day = Math.min(day, ISOChrono.INSTANCE.isLeapYear(year) ? 29 : 28);
410                break;
411            case 4:
412            case 6:
413            case 9:
414            case 11:
415                day = Math.min(day, 30);
416                break;
417        }
418        return LocalDate.of(year, month, day);
419    }
420
421    /**
422     * Constructor, previously validated.
423     *
424     * @param year  the year to represent, from MIN_YEAR to MAX_YEAR
425     * @param month  the month-of-year to represent, not null
426     * @param dayOfMonth  the day-of-month to represent, valid for year-month, from 1 to 31
427     */
428    private LocalDate(int year, int month, int dayOfMonth) {
429        this.year = year;
430        this.month = (short) month;
431        this.day = (short) dayOfMonth;
432    }
433
434    //-----------------------------------------------------------------------
435    /**
436     * Checks if the specified field is supported.
437     * <p>
438     * This checks if this date can be queried for the specified field.
439     * If false, then calling the {@link #range(TemporalField) range} and
440     * {@link #get(TemporalField) get} methods will throw an exception.
441     * <p>
442     * If the field is a {@link ChronoField} then the query is implemented here.
443     * The {@link #isSupported(TemporalField) supported fields} will return valid
444     * values based on this date-time.
445     * The supported fields are:
446     * <ul>
447     * <li>{@code DAY_OF_WEEK}
448     * <li>{@code ALIGNED_DAY_OF_WEEK_IN_MONTH}
449     * <li>{@code ALIGNED_DAY_OF_WEEK_IN_YEAR}
450     * <li>{@code DAY_OF_MONTH}
451     * <li>{@code DAY_OF_YEAR}
452     * <li>{@code EPOCH_DAY}
453     * <li>{@code ALIGNED_WEEK_OF_MONTH}
454     * <li>{@code ALIGNED_WEEK_OF_YEAR}
455     * <li>{@code MONTH_OF_YEAR}
456     * <li>{@code EPOCH_MONTH}
457     * <li>{@code YEAR_OF_ERA}
458     * <li>{@code YEAR}
459     * <li>{@code ERA}
460     * </ul>
461     * All other {@code ChronoField} instances will return false.
462     * <p>
463     * If the field is not a {@code ChronoField}, then the result of this method
464     * is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
465     * passing {@code this} as the argument.
466     * Whether the field is supported is determined by the field.
467     *
468     * @param field  the field to check, null returns false
469     * @return true if the field is supported on this date, false if not
470     */
471    @Override  // override for Javadoc
472    public boolean isSupported(TemporalField field) {
473        return super.isSupported(field);
474    }
475
476    /**
477     * Gets the range of valid values for the specified field.
478     * <p>
479     * The range object expresses the minimum and maximum valid values for a field.
480     * This date is used to enhance the accuracy of the returned range.
481     * If it is not possible to return the range, because the field is not supported
482     * or for some other reason, an exception is thrown.
483     * <p>
484     * If the field is a {@link ChronoField} then the query is implemented here.
485     * The {@link #isSupported(TemporalField) supported fields} will return
486     * appropriate range instances.
487     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
488     * <p>
489     * If the field is not a {@code ChronoField}, then the result of this method
490     * is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
491     * passing {@code this} as the argument.
492     * Whether the range can be obtained is determined by the field.
493     *
494     * @param field  the field to query the range for, not null
495     * @return the range of valid values for the field, not null
496     * @throws DateTimeException if the range for the field cannot be obtained
497     */
498    @Override
499    public ValueRange range(TemporalField field) {
500        if (field instanceof ChronoField) {
501            ChronoField f = (ChronoField) field;
502            if (f.isDateField()) {
503                switch (f) {
504                    case DAY_OF_MONTH: return ValueRange.of(1, lengthOfMonth());
505                    case DAY_OF_YEAR: return ValueRange.of(1, lengthOfYear());
506                    case ALIGNED_WEEK_OF_MONTH: return ValueRange.of(1, getMonth() == Month.FEBRUARY && isLeapYear() == false ? 4 : 5);
507                    case YEAR_OF_ERA:
508                        return (getYear() <= 0 ? ValueRange.of(1, Year.MAX_VALUE + 1) : ValueRange.of(1, Year.MAX_VALUE));
509                }
510                return field.range();
511            }
512            throw new DateTimeException("Unsupported field: " + field.getName());
513        }
514        return field.doRange(this);
515    }
516
517    /**
518     * Gets the value of the specified field from this date as an {@code int}.
519     * <p>
520     * This queries this date for the value for the specified field.
521     * The returned value will always be within the valid range of values for the field.
522     * If it is not possible to return the value, because the field is not supported
523     * or for some other reason, an exception is thrown.
524     * <p>
525     * If the field is a {@link ChronoField} then the query is implemented here.
526     * The {@link #isSupported(TemporalField) supported fields} will return valid
527     * values based on this date, except {@code EPOCH_DAY} and {@code EPOCH_MONTH}
528     * which are too large to fit in an {@code int} and throw a {@code DateTimeException}.
529     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
530     * <p>
531     * If the field is not a {@code ChronoField}, then the result of this method
532     * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
533     * passing {@code this} as the argument. Whether the value can be obtained,
534     * and what the value represents, is determined by the field.
535     *
536     * @param field  the field to get, not null
537     * @return the value for the field
538     * @throws DateTimeException if a value for the field cannot be obtained
539     * @throws ArithmeticException if numeric overflow occurs
540     */
541    @Override  // override for Javadoc and performance
542    public int get(TemporalField field) {
543        if (field instanceof ChronoField) {
544            return get0(field);
545        }
546        return super.get(field);
547    }
548
549    /**
550     * Gets the value of the specified field from this date as a {@code long}.
551     * <p>
552     * This queries this date for the value for the specified field.
553     * If it is not possible to return the value, because the field is not supported
554     * or for some other reason, an exception is thrown.
555     * <p>
556     * If the field is a {@link ChronoField} then the query is implemented here.
557     * The {@link #isSupported(TemporalField) supported fields} will return valid
558     * values based on this date.
559     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
560     * <p>
561     * If the field is not a {@code ChronoField}, then the result of this method
562     * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
563     * passing {@code this} as the argument. Whether the value can be obtained,
564     * and what the value represents, is determined by the field.
565     *
566     * @param field  the field to get, not null
567     * @return the value for the field
568     * @throws DateTimeException if a value for the field cannot be obtained
569     * @throws ArithmeticException if numeric overflow occurs
570     */
571    @Override
572    public long getLong(TemporalField field) {
573        if (field instanceof ChronoField) {
574            if (field == EPOCH_DAY) {
575                return toEpochDay();
576            }
577            if (field == EPOCH_MONTH) {
578                return getEpochMonth();
579            }
580            return get0(field);
581        }
582        return field.doGet(this);
583    }
584
585    private int get0(TemporalField field) {
586        switch ((ChronoField) field) {
587            case DAY_OF_WEEK: return getDayOfWeek().getValue();
588            case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((day - 1) % 7) + 1;
589            case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1;
590            case DAY_OF_MONTH: return day;
591            case DAY_OF_YEAR: return getDayOfYear();
592            case EPOCH_DAY: throw new DateTimeException("Field too large for an int: " + field);
593            case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1;
594            case ALIGNED_WEEK_OF_YEAR: return ((getDayOfYear() - 1) / 7) + 1;
595            case MONTH_OF_YEAR: return month;
596            case EPOCH_MONTH: throw new DateTimeException("Field too large for an int: " + field);
597            case YEAR_OF_ERA: return (year >= 1 ? year : 1 - year);
598            case YEAR: return year;
599            case ERA: return (year >= 1 ? 1 : 0);
600        }
601        throw new DateTimeException("Unsupported field: " + field.getName());
602    }
603
604    private long getEpochMonth() {
605        return ((year - 1970) * 12L) + (month - 1);
606    }
607
608    //-----------------------------------------------------------------------
609    /**
610     * Gets the chronology of this date, which is the ISO calendar system.
611     * <p>
612     * The {@code Chrono} represents the calendar system in use.
613     * The ISO-8601 calendar system is the modern civil calendar system used today
614     * in most of the world. It is equivalent to the proleptic Gregorian calendar
615     * system, in which todays's rules for leap years are applied for all time.
616     *
617     * @return the ISO chronology, not null
618     */
619    @Override
620    public ISOChrono getChrono() {
621        return ISOChrono.INSTANCE;
622    }
623
624    /**
625     * Gets the era applicable at this date.
626     * <p>
627     * The official ISO-8601 standard does not define eras, however {@code ISOChrono} does.
628     * It defines two eras, 'CE' from year one onwards and 'BCE' from year zero backwards.
629     * Since dates before the Julian-Gregorian cutover are not in line with history,
630     * the cutover between 'BCE' and 'CE' is also not aligned with the commonly used
631     * eras, often referred to using 'BC' and 'AD'.
632     * <p>
633     * Users of this class should typically ignore this method as it exists primarily
634     * to fulfill the {@link ChronoLocalDate} contract where it is necessary to support
635     * the Japanese calendar system.
636     * <p>
637     * The returned era will be a singleton capable of being compared with the constants
638     * in {@link ISOChrono} using the {@code ==} operator.
639     *
640     * @return the {@code ISOChrono} era constant applicable at this date, not null
641     */
642    @Override // override for Javadoc
643    public Era<ISOChrono> getEra() {
644        return super.getEra();
645    }
646
647    /**
648     * Gets the year field.
649     * <p>
650     * This method returns the primitive {@code int} value for the year.
651     * <p>
652     * The year returned by this method is proleptic as per {@code get(YEAR)}.
653     * To obtain the year-of-era, use {@code get(YEAR_OF_ERA}.
654     *
655     * @return the year, from MIN_YEAR to MAX_YEAR
656     */
657    public int getYear() {
658        return year;
659    }
660
661    /**
662     * Gets the month-of-year field from 1 to 12.
663     * <p>
664     * This method returns the month as an {@code int} from 1 to 12.
665     * Application code is frequently clearer if the enum {@link Month}
666     * is used by calling {@link #getMonth()}.
667     *
668     * @return the month-of-year, from 1 to 12
669     * @see #getMonth()
670     */
671    public int getMonthValue() {
672        return month;
673    }
674
675    /**
676     * Gets the month-of-year field using the {@code Month} enum.
677     * <p>
678     * This method returns the enum {@link Month} for the month.
679     * This avoids confusion as to what {@code int} values mean.
680     * If you need access to the primitive {@code int} value then the enum
681     * provides the {@link Month#getValue() int value}.
682     *
683     * @return the month-of-year, not null
684     * @see #getMonthValue()
685     */
686    public Month getMonth() {
687        return Month.of(month);
688    }
689
690    /**
691     * Gets the day-of-month field.
692     * <p>
693     * This method returns the primitive {@code int} value for the day-of-month.
694     *
695     * @return the day-of-month, from 1 to 31
696     */
697    public int getDayOfMonth() {
698        return day;
699    }
700
701    /**
702     * Gets the day-of-year field.
703     * <p>
704     * This method returns the primitive {@code int} value for the day-of-year.
705     *
706     * @return the day-of-year, from 1 to 365, or 366 in a leap year
707     */
708    public int getDayOfYear() {
709        return getMonth().firstDayOfYear(isLeapYear()) + day - 1;
710    }
711
712    /**
713     * Gets the day-of-week field, which is an enum {@code DayOfWeek}.
714     * <p>
715     * This method returns the enum {@link DayOfWeek} for the day-of-week.
716     * This avoids confusion as to what {@code int} values mean.
717     * If you need access to the primitive {@code int} value then the enum
718     * provides the {@link DayOfWeek#getValue() int value}.
719     * <p>
720     * Additional information can be obtained from the {@code DayOfWeek}.
721     * This includes textual names of the values.
722     *
723     * @return the day-of-week, not null
724     */
725    public DayOfWeek getDayOfWeek() {
726        int dow0 = Jdk8Methods.floorMod(toEpochDay() + 3, 7);
727        return DayOfWeek.of(dow0 + 1);
728    }
729
730    //-----------------------------------------------------------------------
731    /**
732     * Checks if the year is a leap year, according to the ISO proleptic
733     * calendar system rules.
734     * <p>
735     * This method applies the current rules for leap years across the whole time-line.
736     * In general, a year is a leap year if it is divisible by four without
737     * remainder. However, years divisible by 100, are not leap years, with
738     * the exception of years divisible by 400 which are.
739     * <p>
740     * For example, 1904 is a leap year it is divisible by 4.
741     * 1900 was not a leap year as it is divisible by 100, however 2000 was a
742     * leap year as it is divisible by 400.
743     * <p>
744     * The calculation is proleptic - applying the same rules into the far future and far past.
745     * This is historically inaccurate, but is correct for the ISO-8601 standard.
746     *
747     * @return true if the year is leap, false otherwise
748     */
749    @Override // override for Javadoc and performance
750    public boolean isLeapYear() {
751        return ISOChrono.INSTANCE.isLeapYear(year);
752    }
753
754    /**
755     * Returns the length of the month represented by this date.
756     * <p>
757     * This returns the length of the month in days.
758     * For example, a date in January would return 31.
759     *
760     * @return the length of the month in days
761     */
762    @Override
763    public int lengthOfMonth() {
764        switch (month) {
765            case 2:
766                return (isLeapYear() ? 29 : 28);
767            case 4:
768            case 6:
769            case 9:
770            case 11:
771                return 30;
772            default:
773                return 31;
774        }
775    }
776
777    /**
778     * Returns the length of the year represented by this date.
779     * <p>
780     * This returns the length of the year in days, either 365 or 366.
781     *
782     * @return 366 if the year is leap, 365 otherwise
783     */
784    @Override // override for Javadoc and performance
785    public int lengthOfYear() {
786        return (isLeapYear() ? 366 : 365);
787    }
788
789    //-----------------------------------------------------------------------
790    /**
791     * Returns an adjusted copy of this date.
792     * <p>
793     * This returns a new {@code LocalDate}, based on this one, with the date adjusted.
794     * The adjustment takes place using the specified adjuster strategy object.
795     * Read the documentation of the adjuster to understand what adjustment will be made.
796     * <p>
797     * A simple adjuster might simply set the one of the fields, such as the year field.
798     * A more complex adjuster might set the date to the last day of the month.
799     * A selection of common adjustments is provided in {@link TemporalAdjusters}.
800     * These include finding the "last day of the month" and "next Wednesday".
801     * Key date-time classes also implement the {@code TemporalAdjuster} interface,
802     * such as {@link Month} and {@link MonthDay}.
803     * The adjuster is responsible for handling special cases, such as the varying
804     * lengths of month and leap years.
805     * <p>
806     * For example this code returns a date on the last day of July:
807     * <pre>
808     *  import static org.threeten.bp.Month.*;
809     *  import static org.threeten.bp.temporal.Adjusters.*;
810     *
811     *  result = localDate.with(JULY).with(lastDayOfMonth());
812     * </pre>
813     * <p>
814     * The result of this method is obtained by invoking the
815     * {@link TemporalAdjuster#adjustInto(Temporal)} method on the
816     * specified adjuster passing {@code this} as the argument.
817     * <p>
818     * This instance is immutable and unaffected by this method call.
819     *
820     * @param adjuster the adjuster to use, not null
821     * @return a {@code LocalDate} based on {@code this} with the adjustment made, not null
822     * @throws DateTimeException if the adjustment cannot be made
823     * @throws ArithmeticException if numeric overflow occurs
824     */
825    @Override
826    public LocalDate with(TemporalAdjuster adjuster) {
827        // optimizations
828        if (adjuster instanceof LocalDate) {
829            return (LocalDate) adjuster;
830        }
831        return (LocalDate) adjuster.adjustInto(this);
832    }
833
834    /**
835     * Returns a copy of this date with the specified field set to a new value.
836     * <p>
837     * This returns a new {@code LocalDate}, based on this one, with the value
838     * for the specified field changed.
839     * This can be used to change any supported field, such as the year, month or day-of-month.
840     * If it is not possible to set the value, because the field is not supported or for
841     * some other reason, an exception is thrown.
842     * <p>
843     * In some cases, changing the specified field can cause the resulting date to become invalid,
844     * such as changing the month from 31st January to February would make the day-of-month invalid.
845     * In cases like this, the field is responsible for resolving the date. Typically it will choose
846     * the previous valid date, which would be the last valid day of February in this example.
847     * <p>
848     * If the field is a {@link ChronoField} then the adjustment is implemented here.
849     * The supported fields behave as follows:
850     * <ul>
851     * <li>{@code DAY_OF_WEEK} -
852     *  Returns a {@code LocalDate} with the specified day-of-week.
853     *  The date is adjusted up to 6 days forward or backward within the boundary
854     *  of a Monday to Sunday week.
855     * <li>{@code ALIGNED_DAY_OF_WEEK_IN_MONTH} -
856     *  Returns a {@code LocalDate} with the specified aligned-day-of-week.
857     *  The date is adjusted to the specified month-based aligned-day-of-week.
858     *  Aligned weeks are counted such that the first week of a given month starts
859     *  on the first day of that month.
860     *  This may cause the date to be moved up to 6 days into the following month.
861     * <li>{@code ALIGNED_DAY_OF_WEEK_IN_YEAR} -
862     *  Returns a {@code LocalDate} with the specified aligned-day-of-week.
863     *  The date is adjusted to the specified year-based aligned-day-of-week.
864     *  Aligned weeks are counted such that the first week of a given year starts
865     *  on the first day of that year.
866     *  This may cause the date to be moved up to 6 days into the following year.
867     * <li>{@code DAY_OF_MONTH} -
868     *  Returns a {@code LocalDate} with the specified day-of-month.
869     *  The month and year will be unchanged. If the day-of-month is invalid for the
870     *  year and month, then a {@code DateTimeException} is thrown.
871     * <li>{@code DAY_OF_YEAR} -
872     *  Returns a {@code LocalDate} with the specified day-of-year.
873     *  The year will be unchanged. If the day-of-year is invalid for the
874     *  year, then a {@code DateTimeException} is thrown.
875     * <li>{@code EPOCH_DAY} -
876     *  Returns a {@code LocalDate} with the specified epoch-day.
877     *  This completely replaces the date and is equivalent to {@link #ofEpochDay(long)}.
878     * <li>{@code ALIGNED_WEEK_OF_MONTH} -
879     *  Returns a {@code LocalDate} with the specified aligned-week-of-month.
880     *  Aligned weeks are counted such that the first week of a given month starts
881     *  on the first day of that month.
882     *  This adjustment moves the date in whole week chunks to match the specified week.
883     *  The result will have the same day-of-week as this date.
884     *  This may cause the date to be moved into the following month.
885     * <li>{@code ALIGNED_WEEK_OF_YEAR} -
886     *  Returns a {@code LocalDate} with the specified aligned-week-of-year.
887     *  Aligned weeks are counted such that the first week of a given year starts
888     *  on the first day of that year.
889     *  This adjustment moves the date in whole week chunks to match the specified week.
890     *  The result will have the same day-of-week as this date.
891     *  This may cause the date to be moved into the following year.
892     * <li>{@code MONTH_OF_YEAR} -
893     *  Returns a {@code LocalDate} with the specified month-of-year.
894     *  The year will be unchanged. The day-of-month will also be unchanged,
895     *  unless it would be invalid for the new month and year. In that case, the
896     *  day-of-month is adjusted to the maximum valid value for the new month and year.
897     * <li>{@code EPOCH_MONTH} -
898     *  Returns a {@code LocalDate} with the specified epoch-month.
899     *  The day-of-month will be unchanged, unless it would be invalid for the new month
900     *  and year. In that case, the day-of-month is adjusted to the maximum valid value
901     *  for the new month and year.
902     * <li>{@code YEAR_OF_ERA} -
903     *  Returns a {@code LocalDate} with the specified year-of-era.
904     *  The era and month will be unchanged. The day-of-month will also be unchanged,
905     *  unless it would be invalid for the new month and year. In that case, the
906     *  day-of-month is adjusted to the maximum valid value for the new month and year.
907     * <li>{@code YEAR} -
908     *  Returns a {@code LocalDate} with the specified year.
909     *  The month will be unchanged. The day-of-month will also be unchanged,
910     *  unless it would be invalid for the new month and year. In that case, the
911     *  day-of-month is adjusted to the maximum valid value for the new month and year.
912     * <li>{@code ERA} -
913     *  Returns a {@code LocalDate} with the specified era.
914     *  The year-of-era and month will be unchanged. The day-of-month will also be unchanged,
915     *  unless it would be invalid for the new month and year. In that case, the
916     *  day-of-month is adjusted to the maximum valid value for the new month and year.
917     * </ul>
918     * <p>
919     * In all cases, if the new value is outside the valid range of values for the field
920     * then a {@code DateTimeException} will be thrown.
921     * <p>
922     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
923     * <p>
924     * If the field is not a {@code ChronoField}, then the result of this method
925     * is obtained by invoking {@code TemporalField.doWith(Temporal, long)}
926     * passing {@code this} as the argument. In this case, the field determines
927     * whether and how to adjust the instant.
928     * <p>
929     * This instance is immutable and unaffected by this method call.
930     *
931     * @param field  the field to set in the result, not null
932     * @param newValue  the new value of the field in the result
933     * @return a {@code LocalDate} based on {@code this} with the specified field set, not null
934     * @throws DateTimeException if the field cannot be set
935     * @throws ArithmeticException if numeric overflow occurs
936     */
937    @Override
938    public LocalDate with(TemporalField field, long newValue) {
939        if (field instanceof ChronoField) {
940            ChronoField f = (ChronoField) field;
941            f.checkValidValue(newValue);
942            switch (f) {
943                case DAY_OF_WEEK: return plusDays(newValue - getDayOfWeek().getValue());
944                case ALIGNED_DAY_OF_WEEK_IN_MONTH: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_MONTH));
945                case ALIGNED_DAY_OF_WEEK_IN_YEAR: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_YEAR));
946                case DAY_OF_MONTH: return withDayOfMonth((int) newValue);
947                case DAY_OF_YEAR: return withDayOfYear((int) newValue);
948                case EPOCH_DAY: return LocalDate.ofEpochDay(newValue);
949                case ALIGNED_WEEK_OF_MONTH: return plusWeeks(newValue - getLong(ALIGNED_WEEK_OF_MONTH));
950                case ALIGNED_WEEK_OF_YEAR: return plusWeeks(newValue - getLong(ALIGNED_WEEK_OF_YEAR));
951                case MONTH_OF_YEAR: return withMonth((int) newValue);
952                case EPOCH_MONTH: return plusMonths(newValue - getLong(EPOCH_MONTH));
953                case YEAR_OF_ERA: return withYear((int) (year >= 1 ? newValue : 1 - newValue));
954                case YEAR: return withYear((int) newValue);
955                case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year));
956            }
957            throw new DateTimeException("Unsupported field: " + field.getName());
958        }
959        return field.doWith(this, newValue);
960    }
961
962    //-----------------------------------------------------------------------
963    /**
964     * Returns a copy of this date with the year altered.
965     * If the day-of-month is invalid for the year, it will be changed to the last valid day of the month.
966     * <p>
967     * This instance is immutable and unaffected by this method call.
968     *
969     * @param year  the year to set in the result, from MIN_YEAR to MAX_YEAR
970     * @return a {@code LocalDate} based on this date with the requested year, not null
971     * @throws DateTimeException if the year value is invalid
972     */
973    public LocalDate withYear(int year) {
974        if (this.year == year) {
975            return this;
976        }
977        YEAR.checkValidValue(year);
978        return resolvePreviousValid(year, month, day);
979    }
980
981    /**
982     * Returns a copy of this date with the month-of-year altered.
983     * If the day-of-month is invalid for the year, it will be changed to the last valid day of the month.
984     * <p>
985     * This instance is immutable and unaffected by this method call.
986     *
987     * @param month  the month-of-year to set in the result, from 1 (January) to 12 (December)
988     * @return a {@code LocalDate} based on this date with the requested month, not null
989     * @throws DateTimeException if the month-of-year value is invalid
990     */
991    public LocalDate withMonth(int month) {
992        if (this.month == month) {
993            return this;
994        }
995        MONTH_OF_YEAR.checkValidValue(month);
996        return resolvePreviousValid(year, month, day);
997    }
998
999    /**
1000     * Returns a copy of this date with the day-of-month altered.
1001     * If the resulting date is invalid, an exception is thrown.
1002     * <p>
1003     * This instance is immutable and unaffected by this method call.
1004     *
1005     * @param dayOfMonth  the day-of-month to set in the result, from 1 to 28-31
1006     * @return a {@code LocalDate} based on this date with the requested day, not null
1007     * @throws DateTimeException if the day-of-month value is invalid
1008     * @throws DateTimeException if the day-of-month is invalid for the month-year
1009     */
1010    public LocalDate withDayOfMonth(int dayOfMonth) {
1011        if (this.day == dayOfMonth) {
1012            return this;
1013        }
1014        return of(year, month, dayOfMonth);
1015    }
1016
1017    /**
1018     * Returns a copy of this date with the day-of-year altered.
1019     * If the resulting date is invalid, an exception is thrown.
1020     * <p>
1021     * This instance is immutable and unaffected by this method call.
1022     *
1023     * @param dayOfYear  the day-of-year to set in the result, from 1 to 365-366
1024     * @return a {@code LocalDate} based on this date with the requested day, not null
1025     * @throws DateTimeException if the day-of-year value is invalid
1026     * @throws DateTimeException if the day-of-year is invalid for the year
1027     */
1028    public LocalDate withDayOfYear(int dayOfYear) {
1029        if (this.getDayOfYear() == dayOfYear) {
1030            return this;
1031        }
1032        return ofYearDay(year, dayOfYear);
1033    }
1034
1035    //-----------------------------------------------------------------------
1036    /**
1037     * Returns a copy of this date with the specified period added.
1038     * <p>
1039     * This method returns a new date based on this date with the specified period added.
1040     * The adder is typically {@link Period} but may be any other type implementing
1041     * the {@link TemporalAdder} interface.
1042     * The calculation is delegated to the specified adjuster, which typically calls
1043     * back to {@link #plus(long, TemporalUnit)}.
1044     * <p>
1045     * This instance is immutable and unaffected by this method call.
1046     *
1047     * @param adder  the adder to use, not null
1048     * @return a {@code LocalDate} based on this date with the addition made, not null
1049     * @throws DateTimeException if the addition cannot be made
1050     * @throws ArithmeticException if numeric overflow occurs
1051     */
1052    @Override
1053    public LocalDate plus(TemporalAdder adder) {
1054        return (LocalDate) adder.addTo(this);
1055    }
1056
1057    /**
1058     * Returns a copy of this date with the specified period added.
1059     * <p>
1060     * This method returns a new date based on this date with the specified period added.
1061     * This can be used to add any period that is defined by a unit, for example to add years, months or days.
1062     * The unit is responsible for the details of the calculation, including the resolution
1063     * of any edge cases in the calculation.
1064     * <p>
1065     * This instance is immutable and unaffected by this method call.
1066     *
1067     * @param amountToAdd  the amount of the unit to add to the result, may be negative
1068     * @param unit  the unit of the period to add, not null
1069     * @return a {@code LocalDate} based on this date with the specified period added, not null
1070     * @throws DateTimeException if the unit cannot be added to this type
1071     */
1072    @Override
1073    public LocalDate plus(long amountToAdd, TemporalUnit unit) {
1074        if (unit instanceof ChronoUnit) {
1075            ChronoUnit f = (ChronoUnit) unit;
1076            switch (f) {
1077                case DAYS: return plusDays(amountToAdd);
1078                case WEEKS: return plusWeeks(amountToAdd);
1079                case MONTHS: return plusMonths(amountToAdd);
1080                case YEARS: return plusYears(amountToAdd);
1081                case DECADES: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 10));
1082                case CENTURIES: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 100));
1083                case MILLENNIA: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 1000));
1084                case ERAS: return with(ERA, Jdk8Methods.safeAdd(getLong(ERA), amountToAdd));
1085            }
1086            throw new DateTimeException("Unsupported unit: " + unit.getName());
1087        }
1088        return unit.doPlus(this, amountToAdd);
1089    }
1090
1091    //-----------------------------------------------------------------------
1092    /**
1093     * Returns a copy of this {@code LocalDate} with the specified period in years added.
1094     * <p>
1095     * This method adds the specified amount to the years field in three steps:
1096     * <ol>
1097     * <li>Add the input years to the year field</li>
1098     * <li>Check if the resulting date would be invalid</li>
1099     * <li>Adjust the day-of-month to the last valid day if necessary</li>
1100     * </ol>
1101     * <p>
1102     * For example, 2008-02-29 (leap year) plus one year would result in the
1103     * invalid date 2009-02-29 (standard year). Instead of returning an invalid
1104     * result, the last valid day of the month, 2009-02-28, is selected instead.
1105     * <p>
1106     * This instance is immutable and unaffected by this method call.
1107     *
1108     * @param yearsToAdd  the years to add, may be negative
1109     * @return a {@code LocalDate} based on this date with the years added, not null
1110     * @throws DateTimeException if the result exceeds the supported date range
1111     */
1112    public LocalDate plusYears(long yearsToAdd) {
1113        if (yearsToAdd == 0) {
1114            return this;
1115        }
1116        int newYear = YEAR.checkValidIntValue(year + yearsToAdd);  // safe overflow
1117        return resolvePreviousValid(newYear, month, day);
1118    }
1119
1120    /**
1121     * Returns a copy of this {@code LocalDate} with the specified period in months added.
1122     * <p>
1123     * This method adds the specified amount to the months field in three steps:
1124     * <ol>
1125     * <li>Add the input months to the month-of-year field</li>
1126     * <li>Check if the resulting date would be invalid</li>
1127     * <li>Adjust the day-of-month to the last valid day if necessary</li>
1128     * </ol>
1129     * <p>
1130     * For example, 2007-03-31 plus one month would result in the invalid date
1131     * 2007-04-31. Instead of returning an invalid result, the last valid day
1132     * of the month, 2007-04-30, is selected instead.
1133     * <p>
1134     * This instance is immutable and unaffected by this method call.
1135     *
1136     * @param monthsToAdd  the months to add, may be negative
1137     * @return a {@code LocalDate} based on this date with the months added, not null
1138     * @throws DateTimeException if the result exceeds the supported date range
1139     */
1140    public LocalDate plusMonths(long monthsToAdd) {
1141        if (monthsToAdd == 0) {
1142            return this;
1143        }
1144        long monthCount = year * 12L + (month - 1);
1145        long calcMonths = monthCount + monthsToAdd;  // safe overflow
1146        int newYear = YEAR.checkValidIntValue(Jdk8Methods.floorDiv(calcMonths, 12));
1147        int newMonth = Jdk8Methods.floorMod(calcMonths, 12) + 1;
1148        return resolvePreviousValid(newYear, newMonth, day);
1149    }
1150
1151    /**
1152     * Returns a copy of this {@code LocalDate} with the specified period in weeks added.
1153     * <p>
1154     * This method adds the specified amount in weeks to the days field incrementing
1155     * the month and year fields as necessary to ensure the result remains valid.
1156     * The result is only invalid if the maximum/minimum year is exceeded.
1157     * <p>
1158     * For example, 2008-12-31 plus one week would result in 2009-01-07.
1159     * <p>
1160     * This instance is immutable and unaffected by this method call.
1161     *
1162     * @param weeksToAdd  the weeks to add, may be negative
1163     * @return a {@code LocalDate} based on this date with the weeks added, not null
1164     * @throws DateTimeException if the result exceeds the supported date range
1165     */
1166    public LocalDate plusWeeks(long weeksToAdd) {
1167        return plusDays(Jdk8Methods.safeMultiply(weeksToAdd, 7));
1168    }
1169
1170    /**
1171     * Returns a copy of this {@code LocalDate} with the specified number of days added.
1172     * <p>
1173     * This method adds the specified amount to the days field incrementing the
1174     * month and year fields as necessary to ensure the result remains valid.
1175     * The result is only invalid if the maximum/minimum year is exceeded.
1176     * <p>
1177     * For example, 2008-12-31 plus one day would result in 2009-01-01.
1178     * <p>
1179     * This instance is immutable and unaffected by this method call.
1180     *
1181     * @param daysToAdd  the days to add, may be negative
1182     * @return a {@code LocalDate} based on this date with the days added, not null
1183     * @throws DateTimeException if the result exceeds the supported date range
1184     */
1185    public LocalDate plusDays(long daysToAdd) {
1186        if (daysToAdd == 0) {
1187            return this;
1188        }
1189        long mjDay = Jdk8Methods.safeAdd(toEpochDay(), daysToAdd);
1190        return LocalDate.ofEpochDay(mjDay);
1191    }
1192
1193    //-----------------------------------------------------------------------
1194    /**
1195     * Returns a copy of this date with the specified period subtracted.
1196     * <p>
1197     * This method returns a new date based on this date with the specified period subtracted.
1198     * The subtractor is typically {@link Period} but may be any other type implementing
1199     * the {@link TemporalSubtractor} interface.
1200     * The calculation is delegated to the specified adjuster, which typically calls
1201     * back to {@link #minus(long, TemporalUnit)}.
1202     * <p>
1203     * This instance is immutable and unaffected by this method call.
1204     *
1205     * @param subtractor  the subtractor to use, not null
1206     * @return a {@code LocalDate} based on this date with the subtraction made, not null
1207     * @throws DateTimeException if the subtraction cannot be made
1208     * @throws ArithmeticException if numeric overflow occurs
1209     */
1210    @Override
1211    public LocalDate minus(TemporalSubtractor subtractor) {
1212        return (LocalDate) subtractor.subtractFrom(this);
1213    }
1214
1215    /**
1216     * Returns a copy of this date with the specified period subtracted.
1217     * <p>
1218     * This method returns a new date based on this date with the specified period subtracted.
1219     * This can be used to subtract any period that is defined by a unit, for example to subtract years, months or days.
1220     * The unit is responsible for the details of the calculation, including the resolution
1221     * of any edge cases in the calculation.
1222     * <p>
1223     * This instance is immutable and unaffected by this method call.
1224     *
1225     * @param amountToSubtract  the amount of the unit to subtract from the result, may be negative
1226     * @param unit  the unit of the period to subtract, not null
1227     * @return a {@code LocalDate} based on this date with the specified period subtracted, not null
1228     * @throws DateTimeException if the unit cannot be added to this type
1229     */
1230    @Override
1231    public LocalDate minus(long amountToSubtract, TemporalUnit unit) {
1232        return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
1233    }
1234
1235    //-----------------------------------------------------------------------
1236    /**
1237     * Returns a copy of this {@code LocalDate} with the specified period in years subtracted.
1238     * <p>
1239     * This method subtracts the specified amount from the years field in three steps:
1240     * <ol>
1241     * <li>Subtract the input years to the year field</li>
1242     * <li>Check if the resulting date would be invalid</li>
1243     * <li>Adjust the day-of-month to the last valid day if necessary</li>
1244     * </ol>
1245     * <p>
1246     * For example, 2008-02-29 (leap year) minus one year would result in the
1247     * invalid date 2007-02-29 (standard year). Instead of returning an invalid
1248     * result, the last valid day of the month, 2007-02-28, is selected instead.
1249     * <p>
1250     * This instance is immutable and unaffected by this method call.
1251     *
1252     * @param yearsToSubtract  the years to subtract, may be negative
1253     * @return a {@code LocalDate} based on this date with the years subtracted, not null
1254     * @throws DateTimeException if the result exceeds the supported date range
1255     */
1256    public LocalDate minusYears(long yearsToSubtract) {
1257        return (yearsToSubtract == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-yearsToSubtract));
1258    }
1259
1260    /**
1261     * Returns a copy of this {@code LocalDate} with the specified period in months subtracted.
1262     * <p>
1263     * This method subtracts the specified amount from the months field in three steps:
1264     * <ol>
1265     * <li>Subtract the input months to the month-of-year field</li>
1266     * <li>Check if the resulting date would be invalid</li>
1267     * <li>Adjust the day-of-month to the last valid day if necessary</li>
1268     * </ol>
1269     * <p>
1270     * For example, 2007-03-31 minus one month would result in the invalid date
1271     * 2007-02-31. Instead of returning an invalid result, the last valid day
1272     * of the month, 2007-02-28, is selected instead.
1273     * <p>
1274     * This instance is immutable and unaffected by this method call.
1275     *
1276     * @param monthsToSubtract  the months to subtract, may be negative
1277     * @return a {@code LocalDate} based on this date with the months subtracted, not null
1278     * @throws DateTimeException if the result exceeds the supported date range
1279     */
1280    public LocalDate minusMonths(long monthsToSubtract) {
1281        return (monthsToSubtract == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-monthsToSubtract));
1282    }
1283
1284    /**
1285     * Returns a copy of this {@code LocalDate} with the specified period in weeks subtracted.
1286     * <p>
1287     * This method subtracts the specified amount in weeks from the days field decrementing
1288     * the month and year fields as necessary to ensure the result remains valid.
1289     * The result is only invalid if the maximum/minimum year is exceeded.
1290     * <p>
1291     * For example, 2009-01-07 minus one week would result in 2008-12-31.
1292     * <p>
1293     * This instance is immutable and unaffected by this method call.
1294     *
1295     * @param weeksToSubtract  the weeks to subtract, may be negative
1296     * @return a {@code LocalDate} based on this date with the weeks subtracted, not null
1297     * @throws DateTimeException if the result exceeds the supported date range
1298     */
1299    public LocalDate minusWeeks(long weeksToSubtract) {
1300        return (weeksToSubtract == Long.MIN_VALUE ? plusWeeks(Long.MAX_VALUE).plusWeeks(1) : plusWeeks(-weeksToSubtract));
1301    }
1302
1303    /**
1304     * Returns a copy of this {@code LocalDate} with the specified number of days subtracted.
1305     * <p>
1306     * This method subtracts the specified amount from the days field decrementing the
1307     * month and year fields as necessary to ensure the result remains valid.
1308     * The result is only invalid if the maximum/minimum year is exceeded.
1309     * <p>
1310     * For example, 2009-01-01 minus one day would result in 2008-12-31.
1311     * <p>
1312     * This instance is immutable and unaffected by this method call.
1313     *
1314     * @param daysToSubtract  the days to subtract, may be negative
1315     * @return a {@code LocalDate} based on this date with the days subtracted, not null
1316     * @throws DateTimeException if the result exceeds the supported date range
1317     */
1318    public LocalDate minusDays(long daysToSubtract) {
1319        return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));
1320    }
1321
1322    //-----------------------------------------------------------------------
1323    /**
1324     * Queries this date using the specified query.
1325     * <p>
1326     * This queries this date using the specified query strategy object.
1327     * The {@code TemporalQuery} object defines the logic to be used to
1328     * obtain the result. Read the documentation of the query to understand
1329     * what the result of this method will be.
1330     * <p>
1331     * The result of this method is obtained by invoking the
1332     * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the
1333     * specified query passing {@code this} as the argument.
1334     *
1335     * @param <R> the type of the result
1336     * @param query  the query to invoke, not null
1337     * @return the query result, null may be returned (defined by the query)
1338     * @throws DateTimeException if unable to query (defined by the query)
1339     * @throws ArithmeticException if numeric overflow occurs (defined by the query)
1340     */
1341    @Override  // override for Javadoc
1342    public <R> R query(TemporalQuery<R> query) {
1343        return super.query(query);
1344    }
1345
1346    /**
1347     * Adjusts the specified temporal object to have the same date as this object.
1348     * <p>
1349     * This returns a temporal object of the same observable type as the input
1350     * with the date changed to be the same as this.
1351     * <p>
1352     * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}
1353     * passing {@link ChronoField#EPOCH_DAY} as the field.
1354     * <p>
1355     * In most cases, it is clearer to reverse the calling pattern by using
1356     * {@link Temporal#with(TemporalAdjuster)}:
1357     * <pre>
1358     *   // these two lines are equivalent, but the second approach is recommended
1359     *   temporal = thisLocalDate.adjustInto(temporal);
1360     *   temporal = temporal.with(thisLocalDate);
1361     * </pre>
1362     * <p>
1363     * This instance is immutable and unaffected by this method call.
1364     *
1365     * @param temporal  the target object to be adjusted, not null
1366     * @return the adjusted object, not null
1367     * @throws DateTimeException if unable to make the adjustment
1368     * @throws ArithmeticException if numeric overflow occurs
1369     */
1370    @Override  // override for Javadoc
1371    public Temporal adjustInto(Temporal temporal) {
1372        return super.adjustInto(temporal);
1373    }
1374
1375    /**
1376     * Calculates the period between this date and another date in
1377     * terms of the specified unit.
1378     * <p>
1379     * This calculates the period between two dates in terms of a single unit.
1380     * The start and end points are {@code this} and the specified date.
1381     * The result will be negative if the end is before the start.
1382     * The {@code Temporal} passed to this method must be a {@code LocalDate}.
1383     * For example, the period in days between two dates can be calculated
1384     * using {@code startDate.periodUntil(endDate, DAYS)}.
1385     * <p>
1386     * The calculation returns a whole number, representing the number of
1387     * complete units between the two dates.
1388     * For example, the period in months between 2012-06-15 and 2012-08-14
1389     * will only be one month as it is one day short of two months.
1390     * <p>
1391     * This method operates in association with {@link TemporalUnit#between}.
1392     * The result of this method is a {@code long} representing the amount of
1393     * the specified unit. By contrast, the result of {@code between} is an
1394     * object that can be used directly in addition/subtraction:
1395     * <pre>
1396     *   long period = start.periodUntil(end, MONTHS);   // this method
1397     *   dateTime.plus(MONTHS.between(start, end));      // use in plus/minus
1398     * </pre>
1399     * <p>
1400     * The calculation is implemented in this method for {@link ChronoUnit}.
1401     * The units {@code DAYS}, {@code WEEKS}, {@code MONTHS}, {@code YEARS},
1402     * {@code DECADES}, {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS}
1403     * are supported. Other {@code ChronoUnit} values will throw an exception.
1404     * <p>
1405     * If the unit is not a {@code ChronoUnit}, then the result of this method
1406     * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
1407     * passing {@code this} as the first argument and the input temporal as
1408     * the second argument.
1409     * <p>
1410     * This instance is immutable and unaffected by this method call.
1411     *
1412     * @param endDate  the end date, which must be a {@code LocalDate}, not null
1413     * @param unit  the unit to measure the period in, not null
1414     * @return the amount of the period between this date and the end date
1415     * @throws DateTimeException if the period cannot be calculated
1416     * @throws ArithmeticException if numeric overflow occurs
1417     */
1418    @Override
1419    public long periodUntil(Temporal endDate, TemporalUnit unit) {
1420        if (endDate instanceof LocalDate == false) {
1421            Objects.requireNonNull(endDate, "endDate");
1422            throw new DateTimeException("Unable to calculate period between objects of two different types");
1423        }
1424        LocalDate end = (LocalDate) endDate;
1425        if (unit instanceof ChronoUnit) {
1426            switch ((ChronoUnit) unit) {
1427                case DAYS: return daysUntil(end);
1428                case WEEKS: return daysUntil(end) / 7;
1429                case MONTHS: return monthsUntil(end);
1430                case YEARS: return monthsUntil(end) / 12;
1431                case DECADES: return monthsUntil(end) / 120;
1432                case CENTURIES: return monthsUntil(end) / 1200;
1433                case MILLENNIA: return monthsUntil(end) / 12000;
1434                case ERAS: return end.getLong(ERA) - getLong(ERA);
1435            }
1436            throw new DateTimeException("Unsupported unit: " + unit.getName());
1437        }
1438        return unit.between(this, endDate).getAmount();
1439    }
1440
1441    long daysUntil(LocalDate end) {
1442        return end.toEpochDay() - toEpochDay();  // no overflow
1443    }
1444
1445    private long monthsUntil(LocalDate end) {
1446        long packed1 = getEpochMonth() * 32L + getDayOfMonth();  // no overflow
1447        long packed2 = end.getEpochMonth() * 32L + end.getDayOfMonth();  // no overflow
1448        return (packed2 - packed1) / 32;
1449    }
1450
1451    //-----------------------------------------------------------------------
1452    /**
1453     * Returns a local date-time formed from this date at the specified time.
1454     * <p>
1455     * This combines this date with the specified time to form a {@code LocalDateTime}.
1456     * All possible combinations of date and time are valid.
1457     * <p>
1458     * This instance is immutable and unaffected by this method call.
1459     *
1460     * @param time  the time to combine with, not null
1461     * @return the local date-time formed from this date and the specified time, not null
1462     */
1463    @Override
1464    public LocalDateTime atTime(LocalTime time) {
1465        return LocalDateTime.of(this, time);
1466    }
1467
1468    /**
1469     * Returns a local date-time formed from this date at the specified time.
1470     * <p>
1471     * This combines this date with the specified time to form a {@code LocalDateTime}.
1472     * The individual time fields must be within their valid range.
1473     * All possible combinations of date and time are valid.
1474     * <p>
1475     * This instance is immutable and unaffected by this method call.
1476     *
1477     * @param hour  the hour-of-day to use, from 0 to 23
1478     * @param minute  the minute-of-hour to use, from 0 to 59
1479     * @return the local date-time formed from this date and the specified time, not null
1480     * @throws DateTimeException if the value of any field is out of range
1481     */
1482    public LocalDateTime atTime(int hour, int minute) {
1483        return atTime(LocalTime.of(hour, minute));
1484    }
1485
1486    /**
1487     * Returns a local date-time formed from this date at the specified time.
1488     * <p>
1489     * This combines this date with the specified time to form a {@code LocalDateTime}.
1490     * The individual time fields must be within their valid range.
1491     * All possible combinations of date and time are valid.
1492     * <p>
1493     * This instance is immutable and unaffected by this method call.
1494     *
1495     * @param hour  the hour-of-day to use, from 0 to 23
1496     * @param minute  the minute-of-hour to use, from 0 to 59
1497     * @param second  the second-of-minute to represent, from 0 to 59
1498     * @return the local date-time formed from this date and the specified time, not null
1499     * @throws DateTimeException if the value of any field is out of range
1500     */
1501    public LocalDateTime atTime(int hour, int minute, int second) {
1502        return atTime(LocalTime.of(hour, minute, second));
1503    }
1504
1505    /**
1506     * Returns a local date-time formed from this date at the specified time.
1507     * <p>
1508     * This combines this date with the specified time to form a {@code LocalDateTime}.
1509     * The individual time fields must be within their valid range.
1510     * All possible combinations of date and time are valid.
1511     * <p>
1512     * This instance is immutable and unaffected by this method call.
1513     *
1514     * @param hour  the hour-of-day to use, from 0 to 23
1515     * @param minute  the minute-of-hour to use, from 0 to 59
1516     * @param second  the second-of-minute to represent, from 0 to 59
1517     * @param nanoOfSecond  the nano-of-second to represent, from 0 to 999,999,999
1518     * @return the local date-time formed from this date and the specified time, not null
1519     * @throws DateTimeException if the value of any field is out of range
1520     */
1521    public LocalDateTime atTime(int hour, int minute, int second, int nanoOfSecond) {
1522        return atTime(LocalTime.of(hour, minute, second, nanoOfSecond));
1523    }
1524
1525    /**
1526     * Returns an offset date formed from this date and the specified offset.
1527     * <p>
1528     * This combines this date with the specified offset to form an {@code OffsetDate}.
1529     * All possible combinations of date and offset are valid.
1530     * <p>
1531     * This instance is immutable and unaffected by this method call.
1532     *
1533     * @param offset  the offset to combine with, not null
1534     * @return the offset date formed from this date and the specified offset, not null
1535     */
1536    public OffsetDate atOffset(ZoneOffset offset) {
1537        return OffsetDate.of(this, offset);
1538    }
1539
1540    /**
1541     * Returns a zoned date-time from this date at the earliest valid time according
1542     * to the rules in the time-zone.
1543     * <p>
1544     * Time-zone rules, such as daylight savings, mean that not every local date-time
1545     * is valid for the specified zone, thus the local date-time may not be midnight.
1546     * <p>
1547     * In most cases, there is only one valid offset for a local date-time.
1548     * In the case of an overlap, there are two valid offsets, and the earlier one is used,
1549     * corresponding to the first occurrence of midnight on the date.
1550     * In the case of a gap, the zoned date-time will represent the instant just after the gap.
1551     * <p>
1552     * If the zone ID is a {@link ZoneOffset}, then the result always has a time of midnight.
1553     * <p>
1554     * To convert to a specific time in a given time-zone call {@link #atTime(LocalTime)}
1555     * followed by {@link LocalDateTime#atZone(ZoneId)}.
1556     * <p>
1557     * This instance is immutable and unaffected by this method call.
1558     *
1559     * @param zone  the zone ID to use, not null
1560     * @return the zoned date-time formed from this date and the earliest valid time for the zone, not null
1561     */
1562    public ZonedDateTime atStartOfDay(ZoneId zone) {
1563        Objects.requireNonNull(zone, "zone");
1564        // need to handle case where there is a gap from 11:30 to 00:30
1565        // standard ZDT factory would result in 01:00 rather than 00:30
1566        LocalDateTime ldt = atTime(LocalTime.MIDNIGHT);
1567        if (zone instanceof ZoneOffset == false) {
1568            ZoneRules rules = zone.getRules();
1569            ZoneOffsetTransition trans = rules.getTransition(ldt);
1570            if (trans != null && trans.isGap()) {
1571                ldt = trans.getDateTimeAfter();
1572            }
1573        }
1574        return ZonedDateTime.of(ldt, zone);
1575    }
1576
1577    //-----------------------------------------------------------------------
1578    @Override
1579    public long toEpochDay() {
1580        long y = year;
1581        long m = month;
1582        long total = 0;
1583        total += 365 * y;
1584        if (y >= 0) {
1585            total += (y + 3) / 4 - (y + 99) / 100 + (y + 399) / 400;
1586        } else {
1587            total -= y / -4 - y / -100 + y / -400;
1588        }
1589        total += ((367 * m - 362) / 12);
1590        total += day - 1;
1591        if (m > 2) {
1592            total--;
1593            if (isLeapYear() == false) {
1594                total--;
1595            }
1596        }
1597        return total - DAYS_0000_TO_1970;
1598    }
1599
1600    //-----------------------------------------------------------------------
1601    /**
1602     * Compares this date to another date.
1603     * <p>
1604     * The comparison is primarily based on the date, from earliest to latest.
1605     * It is "consistent with equals", as defined by {@link Comparable}.
1606     * <p>
1607     * If all the dates being compared are instances of {@code LocalDate},
1608     * then the comparison will be entirely based on the date.
1609     * If some dates being compared are in different chronologies, then the
1610     * chronology is also considered, see {@link ChronoLocalDate#compareTo}.
1611     *
1612     * @param other  the other date to compare to, not null
1613     * @return the comparator value, negative if less, positive if greater
1614     */
1615    @Override  // override for Javadoc and performance
1616    public int compareTo(ChronoLocalDate<?> other) {
1617        if (other instanceof LocalDate) {
1618            return compareTo0((LocalDate) other);
1619        }
1620        return super.compareTo(other);
1621    }
1622
1623    int compareTo0(LocalDate otherDate) {
1624        int cmp = (year - otherDate.year);
1625        if (cmp == 0) {
1626            cmp = (month - otherDate.month);
1627            if (cmp == 0) {
1628                cmp = (day - otherDate.day);
1629            }
1630        }
1631        return cmp;
1632    }
1633
1634    /**
1635     * Checks if this date is after the specified date.
1636     * <p>
1637     * This checks to see if this date represents a point on the
1638     * local time-line after the other date.
1639     * <pre>
1640     *   LocalDate a = LocalDate.of(2012, 6, 30);
1641     *   LocalDate b = LocalDate.of(2012, 7, 1);
1642     *   a.isAfter(b) == false
1643     *   a.isAfter(a) == false
1644     *   b.isAfter(a) == true
1645     * </pre>
1646     * <p>
1647     * This method only considers the position of the two dates on the local time-line.
1648     * It does not take into account the chronology, or calendar system.
1649     * This is different from the comparison in {@link #compareTo(ChronoLocalDate)},
1650     * but is the same approach as {@link #DATE_COMPARATOR}.
1651     *
1652     * @param other  the other date to compare to, not null
1653     * @return true if this date is after the specified date
1654     */
1655    @Override  // override for Javadoc and performance
1656    public boolean isAfter(ChronoLocalDate<?> other) {
1657        if (other instanceof LocalDate) {
1658            return compareTo0((LocalDate) other) > 0;
1659        }
1660        return super.isAfter(other);
1661    }
1662
1663    /**
1664     * Checks if this date is before the specified date.
1665     * <p>
1666     * This checks to see if this date represents a point on the
1667     * local time-line before the other date.
1668     * <pre>
1669     *   LocalDate a = LocalDate.of(2012, 6, 30);
1670     *   LocalDate b = LocalDate.of(2012, 7, 1);
1671     *   a.isBefore(b) == true
1672     *   a.isBefore(a) == false
1673     *   b.isBefore(a) == false
1674     * </pre>
1675     * <p>
1676     * This method only considers the position of the two dates on the local time-line.
1677     * It does not take into account the chronology, or calendar system.
1678     * This is different from the comparison in {@link #compareTo(ChronoLocalDate)},
1679     * but is the same approach as {@link #DATE_COMPARATOR}.
1680     *
1681     * @param other  the other date to compare to, not null
1682     * @return true if this date is before the specified date
1683     */
1684    @Override  // override for Javadoc and performance
1685    public boolean isBefore(ChronoLocalDate<?> other) {
1686        if (other instanceof LocalDate) {
1687            return compareTo0((LocalDate) other) < 0;
1688        }
1689        return super.isBefore(other);
1690    }
1691
1692    /**
1693     * Checks if this date is equal to the specified date.
1694     * <p>
1695     * This checks to see if this date represents the same point on the
1696     * local time-line as the other date.
1697     * <pre>
1698     *   LocalDate a = LocalDate.of(2012, 6, 30);
1699     *   LocalDate b = LocalDate.of(2012, 7, 1);
1700     *   a.isEqual(b) == false
1701     *   a.isEqual(a) == true
1702     *   b.isEqual(a) == false
1703     * </pre>
1704     * <p>
1705     * This method only considers the position of the two dates on the local time-line.
1706     * It does not take into account the chronology, or calendar system.
1707     * This is different from the comparison in {@link #compareTo(ChronoLocalDate)}
1708     * but is the same approach as {@link #DATE_COMPARATOR}.
1709     *
1710     * @param other  the other date to compare to, not null
1711     * @return true if this date is equal to the specified date
1712     */
1713    @Override  // override for Javadoc and performance
1714    public boolean isEqual(ChronoLocalDate<?> other) {
1715        if (other instanceof LocalDate) {
1716            return compareTo0((LocalDate) other) == 0;
1717        }
1718        return super.isEqual(other);
1719    }
1720
1721    //-----------------------------------------------------------------------
1722    /**
1723     * Checks if this date is equal to another date.
1724     * <p>
1725     * Compares this {@code LocalDate} with another ensuring that the date is the same.
1726     * <p>
1727     * Only objects of type {@code LocalDate} are compared, other types return false.
1728     * To compare the dates of two {@code TemporalAccessor} instances, including dates
1729     * in two different chronologies, use {@link ChronoField#EPOCH_DAY} as a comparator.
1730     *
1731     * @param obj  the object to check, null returns false
1732     * @return true if this is equal to the other date
1733     */
1734    @Override
1735    public boolean equals(Object obj) {
1736        if (this == obj) {
1737            return true;
1738        }
1739        if (obj instanceof LocalDate) {
1740            return compareTo0((LocalDate) obj) == 0;
1741        }
1742        return false;
1743    }
1744
1745    /**
1746     * A hash code for this date.
1747     *
1748     * @return a suitable hash code
1749     */
1750    @Override
1751    public int hashCode() {
1752        int yearValue = year;
1753        int monthValue = month;
1754        int dayValue = day;
1755        return (yearValue & 0xFFFFF800) ^ ((yearValue << 11) + (monthValue << 6) + (dayValue));
1756    }
1757
1758    //-----------------------------------------------------------------------
1759    /**
1760     * Outputs this date as a {@code String}, such as {@code 2007-12-03}.
1761     * <p>
1762     * The output will be in the ISO-8601 format {@code yyyy-MM-dd}.
1763     *
1764     * @return a string representation of this date, not null
1765     */
1766    @Override
1767    public String toString() {
1768        int yearValue = year;
1769        int monthValue = month;
1770        int dayValue = day;
1771        int absYear = Math.abs(yearValue);
1772        StringBuilder buf = new StringBuilder(10);
1773        if (absYear < 1000) {
1774            if (yearValue < 0) {
1775                buf.append(yearValue - 10000).deleteCharAt(1);
1776            } else {
1777                buf.append(yearValue + 10000).deleteCharAt(0);
1778            }
1779        } else {
1780            if (yearValue > 9999) {
1781                buf.append('+');
1782            }
1783            buf.append(yearValue);
1784        }
1785        return buf.append(monthValue < 10 ? "-0" : "-")
1786            .append(monthValue)
1787            .append(dayValue < 10 ? "-0" : "-")
1788            .append(dayValue)
1789            .toString();
1790    }
1791
1792    /**
1793     * Outputs this date as a {@code String} using the formatter.
1794     * <p>
1795     * This date will be passed to the formatter
1796     * {@link DateTimeFormatter#print(TemporalAccessor) print method}.
1797     *
1798     * @param formatter  the formatter to use, not null
1799     * @return the formatted date string, not null
1800     * @throws DateTimeException if an error occurs during printing
1801     */
1802    @Override  // override for Javadoc
1803    public String toString(DateTimeFormatter formatter) {
1804        return super.toString(formatter);
1805    }
1806
1807    //-----------------------------------------------------------------------
1808    private Object writeReplace() {
1809        return new Ser(Ser.LOCAL_DATE_TYPE, this);
1810    }
1811
1812    /**
1813     * Defend against malicious streams.
1814     * @return never
1815     * @throws InvalidObjectException always
1816     */
1817    private Object readResolve() throws ObjectStreamException {
1818        throw new InvalidObjectException("Deserialization via serialization delegate");
1819    }
1820
1821    void writeExternal(DataOutput out) throws IOException {
1822        out.writeInt(year);
1823        out.writeByte(month);
1824        out.writeByte(day);
1825    }
1826
1827    static LocalDate readExternal(DataInput in) throws IOException {
1828        int year = in.readInt();
1829        int month = in.readByte();
1830        int dayOfMonth = in.readByte();
1831        return LocalDate.of(year, month, dayOfMonth);
1832    }
1833
1834}