ChronoLocalDate.java 33.7 KB
Newer Older
S
sherman 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * This file is available under and governed by the GNU General Public
 * License version 2 only, as published by the Free Software Foundation.
 * However, the following notice accompanied the original version of this
 * file:
 *
 * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 *  * Neither the name of JSR-310 nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
S
sherman 已提交
62
package java.time.chrono;
S
sherman 已提交
63 64 65 66 67 68 69 70 71

import static java.time.temporal.ChronoField.EPOCH_DAY;
import static java.time.temporal.ChronoField.ERA;
import static java.time.temporal.ChronoField.YEAR;
import static java.time.temporal.ChronoUnit.DAYS;

import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.LocalTime;
S
sherman 已提交
72
import java.time.Period;
S
sherman 已提交
73
import java.time.format.DateTimeFormatter;
S
sherman 已提交
74 75 76 77 78 79 80 81 82
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAmount;
import java.time.temporal.TemporalField;
import java.time.temporal.TemporalQuery;
import java.time.temporal.TemporalUnit;
83
import java.time.temporal.UnsupportedTemporalTypeException;
S
sherman 已提交
84 85 86 87 88 89 90 91 92 93 94
import java.util.Comparator;
import java.util.Objects;

/**
 * A date without time-of-day or time-zone in an arbitrary chronology, intended
 * for advanced globalization use cases.
 * <p>
 * <b>Most applications should declare method signatures, fields and variables
 * as {@link LocalDate}, not this interface.</b>
 * <p>
 * A {@code ChronoLocalDate} is the abstract representation of a date where the
S
sherman 已提交
95
 * {@code Chronology chronology}, or calendar system, is pluggable.
S
sherman 已提交
96 97 98 99 100 101 102 103 104 105 106
 * The date is defined in terms of fields expressed by {@link TemporalField},
 * where most common implementations are defined in {@link ChronoField}.
 * The chronology defines how the calendar system operates and the meaning of
 * the standard fields.
 *
 * <h3>When to use this interface</h3>
 * The design of the API encourages the use of {@code LocalDate} rather than this
 * interface, even in the case where the application needs to deal with multiple
 * calendar systems. The rationale for this is explored in the following documentation.
 * <p>
 * The primary use case where this interface should be used is where the generic
S
sherman 已提交
107
 * type parameter {@code <D>} is fully defined as a specific chronology.
S
sherman 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
 * In that case, the assumptions of that chronology are known at development
 * time and specified in the code.
 * <p>
 * When the chronology is defined in the generic type parameter as ? or otherwise
 * unknown at development time, the rest of the discussion below applies.
 * <p>
 * To emphasize the point, declaring a method signature, field or variable as this
 * interface type can initially seem like the sensible way to globalize an application,
 * however it is usually the wrong approach.
 * As such, it should be considered an application-wide architectural decision to choose
 * to use this interface as opposed to {@code LocalDate}.
 *
 * <h3>Architectural issues to consider</h3>
 * These are some of the points that must be considered before using this interface
 * throughout an application.
 * <p>
 * 1) Applications using this interface, as opposed to using just {@code LocalDate},
 * face a significantly higher probability of bugs. This is because the calendar system
 * in use is not known at development time. A key cause of bugs is where the developer
 * applies assumptions from their day-to-day knowledge of the ISO calendar system
 * to code that is intended to deal with any arbitrary calendar system.
 * The section below outlines how those assumptions can cause problems
 * The primary mechanism for reducing this increased risk of bugs is a strong code review process.
 * This should also be considered a extra cost in maintenance for the lifetime of the code.
 * <p>
 * 2) This interface does not enforce immutability of implementations.
 * While the implementation notes indicate that all implementations must be immutable
 * there is nothing in the code or type system to enforce this. Any method declared
 * to accept a {@code ChronoLocalDate} could therefore be passed a poorly or
 * maliciously written mutable implementation.
 * <p>
 * 3) Applications using this interface  must consider the impact of eras.
 * {@code LocalDate} shields users from the concept of eras, by ensuring that {@code getYear()}
 * returns the proleptic year. That decision ensures that developers can think of
 * {@code LocalDate} instances as consisting of three fields - year, month-of-year and day-of-month.
 * By contrast, users of this interface must think of dates as consisting of four fields -
 * era, year-of-era, month-of-year and day-of-month. The extra era field is frequently
 * forgotten, yet it is of vital importance to dates in an arbitrary calendar system.
 * For example, in the Japanese calendar system, the era represents the reign of an Emperor.
 * Whenever one reign ends and another starts, the year-of-era is reset to one.
 * <p>
 * 4) The only agreed international standard for passing a date between two systems
 * is the ISO-8601 standard which requires the ISO calendar system. Using this interface
 * throughout the application will inevitably lead to the requirement to pass the date
 * across a network or component boundary, requiring an application specific protocol or format.
 * <p>
 * 5) Long term persistence, such as a database, will almost always only accept dates in the
 * ISO-8601 calendar system (or the related Julian-Gregorian). Passing around dates in other
 * calendar systems increases the complications of interacting with persistence.
 * <p>
 * 6) Most of the time, passing a {@code ChronoLocalDate} throughout an application
 * is unnecessary, as discussed in the last section below.
 *
 * <h3>False assumptions causing bugs in multi-calendar system code</h3>
 * As indicated above, there are many issues to consider when try to use and manipulate a
 * date in an arbitrary calendar system. These are some of the key issues.
 * <p>
 * Code that queries the day-of-month and assumes that the value will never be more than
 * 31 is invalid. Some calendar systems have more than 31 days in some months.
 * <p>
 * Code that adds 12 months to a date and assumes that a year has been added is invalid.
 * Some calendar systems have a different number of months, such as 13 in the Coptic or Ethiopic.
 * <p>
 * Code that adds one month to a date and assumes that the month-of-year value will increase
 * by one or wrap to the next year is invalid. Some calendar systems have a variable number
 * of months in a year, such as the Hebrew.
 * <p>
 * Code that adds one month, then adds a second one month and assumes that the day-of-month
 * will remain close to its original value is invalid. Some calendar systems have a large difference
 * between the length of the longest month and the length of the shortest month.
 * For example, the Coptic or Ethiopic have 12 months of 30 days and 1 month of 5 days.
 * <p>
 * Code that adds seven days and assumes that a week has been added is invalid.
 * Some calendar systems have weeks of other than seven days, such as the French Revolutionary.
 * <p>
 * Code that assumes that because the year of {@code date1} is greater than the year of {@code date2}
 * then {@code date1} is after {@code date2} is invalid. This is invalid for all calendar systems
 * when referring to the year-of-era, and especially untrue of the Japanese calendar system
 * where the year-of-era restarts with the reign of every new Emperor.
 * <p>
 * Code that treats month-of-year one and day-of-month one as the start of the year is invalid.
 * Not all calendar systems start the year when the month value is one.
 * <p>
 * In general, manipulating a date, and even querying a date, is wide open to bugs when the
 * calendar system is unknown at development time. This is why it is essential that code using
 * this interface is subjected to additional code reviews. It is also why an architectural
 * decision to avoid this interface type is usually the correct one.
 *
 * <h3>Using LocalDate instead</h3>
 * The primary alternative to using this interface throughout your application is as follows.
 * <p><ul>
 * <li>Declare all method signatures referring to dates in terms of {@code LocalDate}.
 * <li>Either store the chronology (calendar system) in the user profile or lookup
 *  the chronology from the user locale
 * <li>Convert the ISO {@code LocalDate} to and from the user's preferred calendar system during
 *  printing and parsing
 * </ul><p>
 * This approach treats the problem of globalized calendar systems as a localization issue
 * and confines it to the UI layer. This approach is in keeping with other localization
 * issues in the java platform.
 * <p>
 * As discussed above, performing calculations on a date where the rules of the calendar system
 * are pluggable requires skill and is not recommended.
 * Fortunately, the need to perform calculations on a date in an arbitrary calendar system
 * is extremely rare. For example, it is highly unlikely that the business rules of a library
 * book rental scheme will allow rentals to be for one month, where meaning of the month
 * is dependent on the user's preferred calendar system.
 * <p>
 * A key use case for calculations on a date in an arbitrary calendar system is producing
 * a month-by-month calendar for display and user interaction. Again, this is a UI issue,
 * and use of this interface solely within a few methods of the UI layer may be justified.
 * <p>
 * In any other part of the system, where a date must be manipulated in a calendar system
 * other than ISO, the use case will generally specify the calendar system to use.
 * For example, an application may need to calculate the next Islamic or Hebrew holiday
 * which may require manipulating the date.
 * This kind of use case can be handled as follows:
 * <p><ul>
 * <li>start from the ISO {@code LocalDate} being passed to the method
 * <li>convert the date to the alternate calendar system, which for this use case is known
 *  rather than arbitrary
 * <li>perform the calculation
 * <li>convert back to {@code LocalDate}
 * </ul><p>
 * Developers writing low-level frameworks or libraries should also avoid this interface.
 * Instead, one of the two general purpose access interfaces should be used.
 * Use {@link TemporalAccessor} if read-only access is required, or use {@link Temporal}
 * if read-write access is required.
 *
237
 * @implSpec
S
sherman 已提交
238 239 240 241 242
 * This interface must be implemented with care to ensure other classes operate correctly.
 * All implementations that can be instantiated must be final, immutable and thread-safe.
 * Subclasses should be Serializable wherever possible.
 * <p>
 * Additional calendar systems may be added to the system.
S
sherman 已提交
243
 * See {@link Chronology} for more details.
S
sherman 已提交
244
 *
S
sherman 已提交
245
 * @param <D> the concrete type for the date
S
sherman 已提交
246 247
 * @since 1.8
 */
S
sherman 已提交
248
public interface ChronoLocalDate<D extends ChronoLocalDate<D>>
S
sherman 已提交
249 250 251
        extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDate<?>> {

    /**
252 253
     * Gets a comparator that compares {@code ChronoLocalDate} in
     * time-line order ignoring the chronology.
S
sherman 已提交
254 255 256 257
     * <p>
     * This comparator differs from the comparison in {@link #compareTo} in that it
     * only compares the underlying date and not the chronology.
     * This allows dates in different calendar systems to be compared based
258 259
     * on the position of the date on the local time-line.
     * The underlying comparison is equivalent to comparing the epoch-day.
260
     * @return a comparator that compares in time-line order ignoring the chronology
S
sherman 已提交
261 262 263 264 265
     *
     * @see #isAfter
     * @see #isBefore
     * @see #isEqual
     */
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
    static Comparator<ChronoLocalDate<?>> timeLineOrder() {
        return Chronology.DATE_ORDER;
    }

    //-----------------------------------------------------------------------
    /**
     * Obtains an instance of {@code ChronoLocalDate} from a temporal object.
     * <p>
     * This obtains a local date based on the specified temporal.
     * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
     * which this factory converts to an instance of {@code ChronoLocalDate}.
     * <p>
     * The conversion extracts and combines the chronology and the date
     * from the temporal object. The behavior is equivalent to using
     * {@link Chronology#date(TemporalAccessor)} with the extracted chronology.
     * Implementations are permitted to perform optimizations such as accessing
     * those fields that are equivalent to the relevant objects.
     * <p>
     * This method matches the signature of the functional interface {@link TemporalQuery}
     * allowing it to be used as a query via method reference, {@code ChronoLocalDate::from}.
     *
     * @param temporal  the temporal object to convert, not null
     * @return the date, not null
     * @throws DateTimeException if unable to convert to a {@code ChronoLocalDate}
     * @see Chronology#date(TemporalAccessor)
     */
    static ChronoLocalDate<?> from(TemporalAccessor temporal) {
        if (temporal instanceof ChronoLocalDate) {
            return (ChronoLocalDate<?>) temporal;
        }
        Chronology chrono = temporal.query(TemporalQuery.chronology());
        if (chrono == null) {
            throw new DateTimeException("Unable to obtain ChronoLocalDate from TemporalAccessor: " + temporal.getClass());
S
sherman 已提交
299
        }
300 301
        return chrono.date(temporal);
    }
S
sherman 已提交
302 303 304 305 306

    //-----------------------------------------------------------------------
    /**
     * Gets the chronology of this date.
     * <p>
S
sherman 已提交
307
     * The {@code Chronology} represents the calendar system in use.
S
sherman 已提交
308 309 310 311
     * The era and other fields in {@link ChronoField} are defined by the chronology.
     *
     * @return the chronology, not null
     */
S
sherman 已提交
312
    Chronology getChronology();
S
sherman 已提交
313 314 315 316 317 318 319

    /**
     * Gets the era, as defined by the chronology.
     * <p>
     * The era is, conceptually, the largest division of the time-line.
     * Most calendar systems have a single epoch dividing the time-line into two eras.
     * However, some have multiple eras, such as one for the reign of each leader.
S
sherman 已提交
320
     * The exact meaning is determined by the {@code Chronology}.
S
sherman 已提交
321 322 323 324
     * <p>
     * All correctly implemented {@code Era} classes are singletons, thus it
     * is valid code to write {@code date.getEra() == SomeChrono.ERA_NAME)}.
     * <p>
S
sherman 已提交
325
     * This default implementation uses {@link Chronology#eraOf(int)}.
S
sherman 已提交
326 327 328
     *
     * @return the chronology specific era constant applicable at this date, not null
     */
329
    default Era getEra() {
S
sherman 已提交
330
        return getChronology().eraOf(get(ERA));
S
sherman 已提交
331 332 333 334 335 336 337 338 339
    }

    /**
     * Checks if the year is a leap year, as defined by the calendar system.
     * <p>
     * A leap-year is a year of a longer length than normal.
     * The exact meaning is determined by the chronology with the constraint that
     * a leap-year must imply a year-length longer than a non leap-year.
     * <p>
S
sherman 已提交
340
     * This default implementation uses {@link Chronology#isLeapYear(long)}.
S
sherman 已提交
341 342 343
     *
     * @return true if this date is in a leap year, false otherwise
     */
344
    default boolean isLeapYear() {
S
sherman 已提交
345
        return getChronology().isLeapYear(getLong(YEAR));
S
sherman 已提交
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
    }

    /**
     * Returns the length of the month represented by this date, as defined by the calendar system.
     * <p>
     * This returns the length of the month in days.
     *
     * @return the length of the month in days
     */
    int lengthOfMonth();

    /**
     * Returns the length of the year represented by this date, as defined by the calendar system.
     * <p>
     * This returns the length of the year in days.
     * <p>
     * The default implementation uses {@link #isLeapYear()} and returns 365 or 366.
     *
     * @return the length of the year in days
     */
366
    default int lengthOfYear() {
S
sherman 已提交
367 368 369 370
        return (isLeapYear() ? 366 : 365);
    }

    @Override
371
    default boolean isSupported(TemporalField field) {
S
sherman 已提交
372
        if (field instanceof ChronoField) {
373
            return field.isDateBased();
S
sherman 已提交
374
        }
S
sherman 已提交
375
        return field != null && field.isSupportedBy(this);
S
sherman 已提交
376 377 378 379 380 381 382 383 384 385
    }

    //-----------------------------------------------------------------------
    // override for covariant return type
    /**
     * {@inheritDoc}
     * @throws DateTimeException {@inheritDoc}
     * @throws ArithmeticException {@inheritDoc}
     */
    @Override
386
    default D with(TemporalAdjuster adjuster) {
S
sherman 已提交
387
        return (D) getChronology().ensureChronoLocalDate(Temporal.super.with(adjuster));
S
sherman 已提交
388 389 390 391 392
    }

    /**
     * {@inheritDoc}
     * @throws DateTimeException {@inheritDoc}
393
     * @throws UnsupportedTemporalTypeException {@inheritDoc}
S
sherman 已提交
394 395 396
     * @throws ArithmeticException {@inheritDoc}
     */
    @Override
397
    default D with(TemporalField field, long newValue) {
S
sherman 已提交
398
        if (field instanceof ChronoField) {
399
            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
S
sherman 已提交
400
        }
S
sherman 已提交
401
        return (D) getChronology().ensureChronoLocalDate(field.adjustInto(this, newValue));
S
sherman 已提交
402 403 404 405 406 407 408 409
    }

    /**
     * {@inheritDoc}
     * @throws DateTimeException {@inheritDoc}
     * @throws ArithmeticException {@inheritDoc}
     */
    @Override
410
    default D plus(TemporalAmount amount) {
S
sherman 已提交
411
        return (D) getChronology().ensureChronoLocalDate(Temporal.super.plus(amount));
S
sherman 已提交
412 413 414 415 416 417 418 419
    }

    /**
     * {@inheritDoc}
     * @throws DateTimeException {@inheritDoc}
     * @throws ArithmeticException {@inheritDoc}
     */
    @Override
420
    default D plus(long amountToAdd, TemporalUnit unit) {
S
sherman 已提交
421
        if (unit instanceof ChronoUnit) {
422
            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
S
sherman 已提交
423
        }
S
sherman 已提交
424
        return (D) getChronology().ensureChronoLocalDate(unit.addTo(this, amountToAdd));
S
sherman 已提交
425 426 427 428 429 430 431 432
    }

    /**
     * {@inheritDoc}
     * @throws DateTimeException {@inheritDoc}
     * @throws ArithmeticException {@inheritDoc}
     */
    @Override
433
    default D minus(TemporalAmount amount) {
S
sherman 已提交
434
        return (D) getChronology().ensureChronoLocalDate(Temporal.super.minus(amount));
S
sherman 已提交
435 436 437 438 439
    }

    /**
     * {@inheritDoc}
     * @throws DateTimeException {@inheritDoc}
440
     * @throws UnsupportedTemporalTypeException {@inheritDoc}
S
sherman 已提交
441 442 443
     * @throws ArithmeticException {@inheritDoc}
     */
    @Override
444
    default D minus(long amountToSubtract, TemporalUnit unit) {
S
sherman 已提交
445
        return (D) getChronology().ensureChronoLocalDate(Temporal.super.minus(amountToSubtract, unit));
S
sherman 已提交
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
    }

    //-----------------------------------------------------------------------
    /**
     * Queries this date using the specified query.
     * <p>
     * This queries this date using the specified query strategy object.
     * The {@code TemporalQuery} object defines the logic to be used to
     * obtain the result. Read the documentation of the query to understand
     * what the result of this method will be.
     * <p>
     * The result of this method is obtained by invoking the
     * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the
     * specified query passing {@code this} as the argument.
     *
     * @param <R> the type of the result
     * @param query  the query to invoke, not null
     * @return the query result, null may be returned (defined by the query)
     * @throws DateTimeException if unable to query (defined by the query)
     * @throws ArithmeticException if numeric overflow occurs (defined by the query)
     */
    @SuppressWarnings("unchecked")
    @Override
469 470
    default <R> R query(TemporalQuery<R> query) {
        if (query == TemporalQuery.zoneId() || query == TemporalQuery.zone() || query == TemporalQuery.offset()) {
S
sherman 已提交
471
            return null;
472
        } else if (query == TemporalQuery.localTime()) {
S
sherman 已提交
473
            return null;
474
        } else if (query == TemporalQuery.chronology()) {
S
sherman 已提交
475
            return (R) getChronology();
476
        } else if (query == TemporalQuery.precision()) {
S
sherman 已提交
477
            return (R) DAYS;
S
sherman 已提交
478
        }
S
sherman 已提交
479 480
        // inline TemporalAccessor.super.query(query) as an optimization
        // non-JDK classes are not permitted to make this optimization
S
sherman 已提交
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
        return query.queryFrom(this);
    }

    /**
     * Adjusts the specified temporal object to have the same date as this object.
     * <p>
     * This returns a temporal object of the same observable type as the input
     * with the date changed to be the same as this.
     * <p>
     * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}
     * passing {@link ChronoField#EPOCH_DAY} as the field.
     * <p>
     * In most cases, it is clearer to reverse the calling pattern by using
     * {@link Temporal#with(TemporalAdjuster)}:
     * <pre>
     *   // these two lines are equivalent, but the second approach is recommended
     *   temporal = thisLocalDate.adjustInto(temporal);
     *   temporal = temporal.with(thisLocalDate);
     * </pre>
     * <p>
     * This instance is immutable and unaffected by this method call.
     *
     * @param temporal  the target object to be adjusted, not null
     * @return the adjusted object, not null
     * @throws DateTimeException if unable to make the adjustment
     * @throws ArithmeticException if numeric overflow occurs
     */
    @Override
509
    default Temporal adjustInto(Temporal temporal) {
S
sherman 已提交
510 511 512 513
        return temporal.with(EPOCH_DAY, toEpochDay());
    }

    /**
514
     * Calculates the amount of time until another date in terms of the specified unit.
S
sherman 已提交
515
     * <p>
516 517
     * This calculates the amount of time between two {@code ChronoLocalDate}
     * objects in terms of a single {@code TemporalUnit}.
S
sherman 已提交
518 519 520 521 522 523
     * The start and end points are {@code this} and the specified date.
     * The result will be negative if the end is before the start.
     * The {@code Temporal} passed to this method must be a
     * {@code ChronoLocalDate} in the same chronology.
     * The calculation returns a whole number, representing the number of
     * complete units between the two dates.
524
     * For example, the amount in days between two dates can be calculated
S
sherman 已提交
525 526
     * using {@code startDate.periodUntil(endDate, DAYS)}.
     * <p>
S
sherman 已提交
527 528 529
     * There are two equivalent ways of using this method.
     * The first is to invoke this method.
     * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
S
sherman 已提交
530
     * <pre>
S
sherman 已提交
531 532 533
     *   // these two lines are equivalent
     *   amount = start.periodUntil(end, MONTHS);
     *   amount = MONTHS.between(start, end);
S
sherman 已提交
534
     * </pre>
S
sherman 已提交
535
     * The choice should be made based on which makes the code more readable.
S
sherman 已提交
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
     * <p>
     * The calculation is implemented in this method for {@link ChronoUnit}.
     * The units {@code DAYS}, {@code WEEKS}, {@code MONTHS}, {@code YEARS},
     * {@code DECADES}, {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS}
     * should be supported by all implementations.
     * Other {@code ChronoUnit} values will throw an exception.
     * <p>
     * If the unit is not a {@code ChronoUnit}, then the result of this method
     * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
     * passing {@code this} as the first argument and the input temporal as
     * the second argument.
     * <p>
     * This instance is immutable and unaffected by this method call.
     *
     * @param endDate  the end date, which must be a {@code ChronoLocalDate}
     *  in the same chronology, not null
552 553 554
     * @param unit  the unit to measure the amount in, not null
     * @return the amount of time between this date and the end date
     * @throws DateTimeException if the amount cannot be calculated
S
sherman 已提交
555 556 557
     * @throws ArithmeticException if numeric overflow occurs
     */
    @Override  // override for Javadoc
558
    long periodUntil(Temporal endDate, TemporalUnit unit);
S
sherman 已提交
559 560

    /**
S
sherman 已提交
561
     * Calculates the period between this date and another date as a {@code Period}.
S
sherman 已提交
562
     * <p>
S
sherman 已提交
563 564 565
     * This calculates the period between two dates in terms of years, months and days.
     * The start and end points are {@code this} and the specified date.
     * The result will be negative if the end is before the start.
566
     * The negative sign will be the same in each of year, month and day.
S
sherman 已提交
567
     * <p>
568
     * The calculation is performed using the chronology of this date.
S
sherman 已提交
569 570
     * If necessary, the input date will be converted to match.
     * <p>
S
sherman 已提交
571
     * This instance is immutable and unaffected by this method call.
S
sherman 已提交
572 573 574 575 576 577
     *
     * @param endDate  the end date, exclusive, which may be in any chronology, not null
     * @return the period between this date and the end date, not null
     * @throws DateTimeException if the period cannot be calculated
     * @throws ArithmeticException if numeric overflow occurs
     */
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597
    Period periodUntil(ChronoLocalDate<?> endDate);

    /**
     * Formats this date using the specified formatter.
     * <p>
     * This date will be passed to the formatter to produce a string.
     * <p>
     * The default implementation must behave as follows:
     * <pre>
     *  return formatter.format(this);
     * </pre>
     *
     * @param formatter  the formatter to use, not null
     * @return the formatted date string, not null
     * @throws DateTimeException if an error occurs during printing
     */
    default String format(DateTimeFormatter formatter) {
        Objects.requireNonNull(formatter, "formatter");
        return formatter.format(this);
    }
S
sherman 已提交
598 599 600 601

    //-----------------------------------------------------------------------
    /**
     * Combines this date with a time to create a {@code ChronoLocalDateTime}.
S
sherman 已提交
602
     * <p>
S
sherman 已提交
603 604
     * This returns a {@code ChronoLocalDateTime} formed from this date at the specified time.
     * All possible combinations of date and time are valid.
S
sherman 已提交
605 606 607 608
     *
     * @param localTime  the local time to use, not null
     * @return the local date-time formed from this date and the specified time, not null
     */
609
    default ChronoLocalDateTime<D> atTime(LocalTime localTime) {
S
sherman 已提交
610
        return (ChronoLocalDateTime<D>)ChronoLocalDateTimeImpl.of(this, localTime);
S
sherman 已提交
611 612 613 614 615 616 617 618 619 620 621 622 623 624
    }

    //-----------------------------------------------------------------------
    /**
     * Converts this date to the Epoch Day.
     * <p>
     * The {@link ChronoField#EPOCH_DAY Epoch Day count} is a simple
     * incrementing count of days where day 0 is 1970-01-01 (ISO).
     * This definition is the same for all chronologies, enabling conversion.
     * <p>
     * This default implementation queries the {@code EPOCH_DAY} field.
     *
     * @return the Epoch Day equivalent to this date
     */
625
    default long toEpochDay() {
S
sherman 已提交
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
        return getLong(EPOCH_DAY);
    }

    //-----------------------------------------------------------------------
    /**
     * Compares this date to another date, including the chronology.
     * <p>
     * The comparison is based first on the underlying time-line date, then
     * on the chronology.
     * It is "consistent with equals", as defined by {@link Comparable}.
     * <p>
     * For example, the following is the comparator order:
     * <ol>
     * <li>{@code 2012-12-03 (ISO)}</li>
     * <li>{@code 2012-12-04 (ISO)}</li>
     * <li>{@code 2555-12-04 (ThaiBuddhist)}</li>
     * <li>{@code 2012-12-05 (ISO)}</li>
     * </ol>
     * Values #2 and #3 represent the same date on the time-line.
     * When two values represent the same date, the chronology ID is compared to distinguish them.
     * This step is needed to make the ordering "consistent with equals".
     * <p>
     * If all the date objects being compared are in the same chronology, then the
     * additional chronology stage is not required and only the local date is used.
     * To compare the dates of two {@code TemporalAccessor} instances, including dates
     * in two different chronologies, use {@link ChronoField#EPOCH_DAY} as a comparator.
     * <p>
     * This default implementation performs the comparison defined above.
     *
     * @param other  the other date to compare to, not null
     * @return the comparator value, negative if less, positive if greater
     */
    @Override
659
    default int compareTo(ChronoLocalDate<?> other) {
S
sherman 已提交
660 661
        int cmp = Long.compare(toEpochDay(), other.toEpochDay());
        if (cmp == 0) {
S
sherman 已提交
662
            cmp = getChronology().compareTo(other.getChronology());
S
sherman 已提交
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
        }
        return cmp;
    }

    /**
     * Checks if this date is after the specified date ignoring the chronology.
     * <p>
     * This method differs from the comparison in {@link #compareTo} in that it
     * only compares the underlying date and not the chronology.
     * This allows dates in different calendar systems to be compared based
     * on the time-line position.
     * This is equivalent to using {@code date1.toEpochDay() &gt; date2.toEpochDay()}.
     * <p>
     * This default implementation performs the comparison based on the epoch-day.
     *
     * @param other  the other date to compare to, not null
     * @return true if this is after the specified date
     */
681
    default boolean isAfter(ChronoLocalDate<?> other) {
S
sherman 已提交
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
        return this.toEpochDay() > other.toEpochDay();
    }

    /**
     * Checks if this date is before the specified date ignoring the chronology.
     * <p>
     * This method differs from the comparison in {@link #compareTo} in that it
     * only compares the underlying date and not the chronology.
     * This allows dates in different calendar systems to be compared based
     * on the time-line position.
     * This is equivalent to using {@code date1.toEpochDay() &lt; date2.toEpochDay()}.
     * <p>
     * This default implementation performs the comparison based on the epoch-day.
     *
     * @param other  the other date to compare to, not null
     * @return true if this is before the specified date
     */
699
    default boolean isBefore(ChronoLocalDate<?> other) {
S
sherman 已提交
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
        return this.toEpochDay() < other.toEpochDay();
    }

    /**
     * Checks if this date is equal to the specified date ignoring the chronology.
     * <p>
     * This method differs from the comparison in {@link #compareTo} in that it
     * only compares the underlying date and not the chronology.
     * This allows dates in different calendar systems to be compared based
     * on the time-line position.
     * This is equivalent to using {@code date1.toEpochDay() == date2.toEpochDay()}.
     * <p>
     * This default implementation performs the comparison based on the epoch-day.
     *
     * @param other  the other date to compare to, not null
     * @return true if the underlying date is equal to the specified date
     */
717
    default boolean isEqual(ChronoLocalDate<?> other) {
S
sherman 已提交
718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
        return this.toEpochDay() == other.toEpochDay();
    }

    //-----------------------------------------------------------------------
    /**
     * Checks if this date is equal to another date, including the chronology.
     * <p>
     * Compares this date with another ensuring that the date and chronology are the same.
     * <p>
     * To compare the dates of two {@code TemporalAccessor} instances, including dates
     * in two different chronologies, use {@link ChronoField#EPOCH_DAY} as a comparator.
     *
     * @param obj  the object to check, null returns false
     * @return true if this is equal to the other date
     */
    @Override
    boolean equals(Object obj);

    /**
     * A hash code for this date.
     *
     * @return a suitable hash code
     */
    @Override
    int hashCode();

    //-----------------------------------------------------------------------
    /**
     * Outputs this date as a {@code String}.
     * <p>
748
     * The output will include the full local date.
S
sherman 已提交
749 750 751 752 753 754 755
     *
     * @return the formatted date, not null
     */
    @Override
    String toString();

}