src/share/classes/java/time/chrono/ChronoLocalDate.java
Print this page
*** 57,77 ****
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
! package java.time.temporal;
import static java.time.temporal.ChronoField.EPOCH_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;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.Objects;
/**
* A date without time-of-day or time-zone in an arbitrary chronology, intended
--- 57,88 ----
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
! package java.time.chrono;
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;
+ import java.time.Period;
import java.time.format.DateTimeFormatter;
+ import java.time.temporal.ChronoField;
+ import java.time.temporal.ChronoUnit;
+ import java.time.temporal.Queries;
+ import java.time.temporal.Temporal;
+ import java.time.temporal.TemporalAccessor;
+ import java.time.temporal.TemporalAdjuster;
+ import java.time.temporal.TemporalAmount;
+ import java.time.temporal.TemporalField;
+ import java.time.temporal.TemporalQuery;
+ import java.time.temporal.TemporalUnit;
import java.util.Comparator;
import java.util.Objects;
/**
* A date without time-of-day or time-zone in an arbitrary chronology, intended
*** 79,89 ****
* <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
! * {@code Chrono chronology}, or calendar system, is pluggable.
* 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.
*
--- 90,100 ----
* <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
! * {@code Chronology chronology}, or calendar system, is pluggable.
* 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.
*
*** 91,101 ****
* 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
! * type parameter {@code <C>} is fully defined as a specific chronology.
* 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.
--- 102,112 ----
* 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
! * type parameter {@code <D>} is fully defined as a specific chronology.
* 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.
*** 227,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.
! * See {@link Chrono} for more details.
*
! * @param <C> the chronology of this date
* @since 1.8
*/
! public interface ChronoLocalDate<C extends Chrono<C>>
extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDate<?>> {
/**
* Comparator for two {@code ChronoLocalDate}s ignoring the chronology.
* <p>
--- 238,253 ----
* 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.
! * See {@link Chronology} for more details.
*
! * @param <D> the concrete type for the date
* @since 1.8
*/
! public interface ChronoLocalDate<D extends ChronoLocalDate<D>>
extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDate<?>> {
/**
* Comparator for two {@code ChronoLocalDate}s ignoring the chronology.
* <p>
*** 260,308 ****
//-----------------------------------------------------------------------
/**
* Gets the chronology of this date.
* <p>
! * The {@code Chrono} represents the calendar system in use.
* The era and other fields in {@link ChronoField} are defined by the chronology.
*
* @return the chronology, not null
*/
! C getChrono();
/**
* 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.
! * The exact meaning is determined by the {@code Chrono}.
* <p>
* All correctly implemented {@code Era} classes are singletons, thus it
* is valid code to write {@code date.getEra() == SomeChrono.ERA_NAME)}.
* <p>
! * This default implementation uses {@link Chrono#eraOf(int)}.
*
* @return the chronology specific era constant applicable at this date, not null
*/
! public default Era<C> getEra() {
! return getChrono().eraOf(get(ERA));
}
/**
* 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>
! * This default implementation uses {@link Chrono#isLeapYear(long)}.
*
* @return true if this date is in a leap year, false otherwise
*/
public default boolean isLeapYear() {
! return getChrono().isLeapYear(getLong(YEAR));
}
/**
* Returns the length of the month represented by this date, as defined by the calendar system.
* <p>
--- 271,319 ----
//-----------------------------------------------------------------------
/**
* Gets the chronology of this date.
* <p>
! * The {@code Chronology} represents the calendar system in use.
* The era and other fields in {@link ChronoField} are defined by the chronology.
*
* @return the chronology, not null
*/
! Chronology getChronology();
/**
* 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.
! * The exact meaning is determined by the {@code Chronology}.
* <p>
* All correctly implemented {@code Era} classes are singletons, thus it
* is valid code to write {@code date.getEra() == SomeChrono.ERA_NAME)}.
* <p>
! * This default implementation uses {@link Chronology#eraOf(int)}.
*
* @return the chronology specific era constant applicable at this date, not null
*/
! public default Era getEra() {
! return getChronology().eraOf(get(ERA));
}
/**
* 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>
! * This default implementation uses {@link Chronology#isLeapYear(long)}.
*
* @return true if this date is in a leap year, false otherwise
*/
public default boolean isLeapYear() {
! return getChronology().isLeapYear(getLong(YEAR));
}
/**
* Returns the length of the month represented by this date, as defined by the calendar system.
* <p>
*** 328,406 ****
@Override
public default boolean isSupported(TemporalField field) {
if (field instanceof ChronoField) {
return ((ChronoField) field).isDateField();
}
! return field != null && field.doIsSupported(this);
}
//-----------------------------------------------------------------------
// override for covariant return type
/**
* {@inheritDoc}
* @throws DateTimeException {@inheritDoc}
* @throws ArithmeticException {@inheritDoc}
*/
@Override
! public default ChronoLocalDate<C> with(TemporalAdjuster adjuster) {
! return getChrono().ensureChronoLocalDate(Temporal.super.with(adjuster));
}
/**
* {@inheritDoc}
* @throws DateTimeException {@inheritDoc}
* @throws ArithmeticException {@inheritDoc}
*/
@Override
! public default ChronoLocalDate<C> with(TemporalField field, long newValue) {
if (field instanceof ChronoField) {
throw new DateTimeException("Unsupported field: " + field.getName());
}
! return getChrono().ensureChronoLocalDate(field.doWith(this, newValue));
}
/**
* {@inheritDoc}
* @throws DateTimeException {@inheritDoc}
* @throws ArithmeticException {@inheritDoc}
*/
@Override
! public default ChronoLocalDate<C> plus(TemporalAdder adder) {
! return getChrono().ensureChronoLocalDate(Temporal.super.plus(adder));
}
/**
* {@inheritDoc}
* @throws DateTimeException {@inheritDoc}
* @throws ArithmeticException {@inheritDoc}
*/
@Override
! public default ChronoLocalDate<C> plus(long amountToAdd, TemporalUnit unit) {
if (unit instanceof ChronoUnit) {
throw new DateTimeException("Unsupported unit: " + unit.getName());
}
! return getChrono().ensureChronoLocalDate(unit.doPlus(this, amountToAdd));
}
/**
* {@inheritDoc}
* @throws DateTimeException {@inheritDoc}
* @throws ArithmeticException {@inheritDoc}
*/
@Override
! public default ChronoLocalDate<C> minus(TemporalSubtractor subtractor) {
! return getChrono().ensureChronoLocalDate(Temporal.super.minus(subtractor));
}
/**
* {@inheritDoc}
* @throws DateTimeException {@inheritDoc}
* @throws ArithmeticException {@inheritDoc}
*/
@Override
! public default ChronoLocalDate<C> minus(long amountToSubtract, TemporalUnit unit) {
! return getChrono().ensureChronoLocalDate(Temporal.super.minus(amountToSubtract, unit));
}
//-----------------------------------------------------------------------
/**
* Queries this date using the specified query.
--- 339,417 ----
@Override
public default boolean isSupported(TemporalField field) {
if (field instanceof ChronoField) {
return ((ChronoField) field).isDateField();
}
! return field != null && field.isSupportedBy(this);
}
//-----------------------------------------------------------------------
// override for covariant return type
/**
* {@inheritDoc}
* @throws DateTimeException {@inheritDoc}
* @throws ArithmeticException {@inheritDoc}
*/
@Override
! public default D with(TemporalAdjuster adjuster) {
! return (D) getChronology().ensureChronoLocalDate(Temporal.super.with(adjuster));
}
/**
* {@inheritDoc}
* @throws DateTimeException {@inheritDoc}
* @throws ArithmeticException {@inheritDoc}
*/
@Override
! public default D with(TemporalField field, long newValue) {
if (field instanceof ChronoField) {
throw new DateTimeException("Unsupported field: " + field.getName());
}
! return (D) getChronology().ensureChronoLocalDate(field.adjustInto(this, newValue));
}
/**
* {@inheritDoc}
* @throws DateTimeException {@inheritDoc}
* @throws ArithmeticException {@inheritDoc}
*/
@Override
! public default D plus(TemporalAmount amount) {
! return (D) getChronology().ensureChronoLocalDate(Temporal.super.plus(amount));
}
/**
* {@inheritDoc}
* @throws DateTimeException {@inheritDoc}
* @throws ArithmeticException {@inheritDoc}
*/
@Override
! public default D plus(long amountToAdd, TemporalUnit unit) {
if (unit instanceof ChronoUnit) {
throw new DateTimeException("Unsupported unit: " + unit.getName());
}
! return (D) getChronology().ensureChronoLocalDate(unit.addTo(this, amountToAdd));
}
/**
* {@inheritDoc}
* @throws DateTimeException {@inheritDoc}
* @throws ArithmeticException {@inheritDoc}
*/
@Override
! public default D minus(TemporalAmount amount) {
! return (D) getChronology().ensureChronoLocalDate(Temporal.super.minus(amount));
}
/**
* {@inheritDoc}
* @throws DateTimeException {@inheritDoc}
* @throws ArithmeticException {@inheritDoc}
*/
@Override
! public default D minus(long amountToSubtract, TemporalUnit unit) {
! return (D) getChronology().ensureChronoLocalDate(Temporal.super.minus(amountToSubtract, unit));
}
//-----------------------------------------------------------------------
/**
* Queries this date using the specified query.
*** 421,440 ****
* @throws ArithmeticException if numeric overflow occurs (defined by the query)
*/
@SuppressWarnings("unchecked")
@Override
public default <R> R query(TemporalQuery<R> query) {
- if (query == Queries.chrono()) {
- return (R) getChrono();
- }
- if (query == Queries.precision()) {
- return (R) DAYS;
- }
- // inline TemporalAccessor.super.query(query) as an optimization
if (query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
return null;
}
return query.queryFrom(this);
}
/**
* Adjusts the specified temporal object to have the same date as this object.
--- 432,452 ----
* @throws ArithmeticException if numeric overflow occurs (defined by the query)
*/
@SuppressWarnings("unchecked")
@Override
public default <R> R query(TemporalQuery<R> query) {
if (query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
return null;
+ } else if (query == Queries.localTime()) {
+ return null;
+ } else if (query == Queries.chronology()) {
+ return (R) getChronology();
+ } else if (query == Queries.precision()) {
+ return (R) DAYS;
}
+ // inline TemporalAccessor.super.query(query) as an optimization
+ // non-JDK classes are not permitted to make this optimization
return query.queryFrom(this);
}
/**
* Adjusts the specified temporal object to have the same date as this object.
*** 477,494 ****
* The calculation returns a whole number, representing the number of
* complete units between the two dates.
* For example, the period in days between two dates can be calculated
* using {@code startDate.periodUntil(endDate, DAYS)}.
* <p>
! * This method operates in association with {@link TemporalUnit#between}.
! * The result of this method is a {@code long} representing the amount of
! * the specified unit. By contrast, the result of {@code between} is an
! * object that can be used directly in addition/subtraction:
* <pre>
! * long period = start.periodUntil(end, MONTHS); // this method
! * dateTime.plus(MONTHS.between(start, end)); // use in plus/minus
* </pre>
* <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.
--- 489,507 ----
* The calculation returns a whole number, representing the number of
* complete units between the two dates.
* For example, the period in days between two dates can be calculated
* using {@code startDate.periodUntil(endDate, DAYS)}.
* <p>
! * There are two equivalent ways of using this method.
! * The first is to invoke this method.
! * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
* <pre>
! * // these two lines are equivalent
! * amount = start.periodUntil(end, MONTHS);
! * amount = MONTHS.between(start, end);
* </pre>
+ * The choice should be made based on which makes the code more readable.
* <p>
* The calculation is implemented in this method for {@link ChronoUnit}.
* The units {@code DAYS}, {@code WEEKS}, {@code MONTHS}, {@code YEARS},
* {@code DECADES}, {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS}
* should be supported by all implementations.
*** 509,534 ****
* @throws ArithmeticException if numeric overflow occurs
*/
@Override // override for Javadoc
public abstract long periodUntil(Temporal endDate, TemporalUnit unit);
- //-----------------------------------------------------------------------
/**
! * Returns a date-time formed from this date at the specified time.
* <p>
! * This merges the two objects - {@code this} and the specified time -
! * to form an instance of {@code ChronoLocalDateTime}.
* <p>
* This instance is immutable and unaffected by this method call.
* <p>
! * This default implementation creates the date-time.
*
* @param localTime the local time to use, not null
* @return the local date-time formed from this date and the specified time, not null
*/
! public default ChronoLocalDateTime<C> atTime(LocalTime localTime) {
! return Chrono.dateTime(this, localTime);
}
//-----------------------------------------------------------------------
/**
* Converts this date to the Epoch Day.
--- 522,565 ----
* @throws ArithmeticException if numeric overflow occurs
*/
@Override // override for Javadoc
public abstract long periodUntil(Temporal endDate, TemporalUnit unit);
/**
! * Calculates the period between this date and another date as a {@code Period}.
* <p>
! * 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.
! * <p>
! * The calculation is performed using the the chronology of this date.
! * If necessary, the input date will be converted to match.
! * <p>
! * The result of this method can be a negative period if the end is before the start.
! * The negative sign will be the same in each of year, month and day.
* <p>
* This instance is immutable and unaffected by this method call.
+ *
+ * @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
+ */
+ public abstract Period periodUntil(ChronoLocalDate<?> endDate);
+
+ //-----------------------------------------------------------------------
+ /**
+ * Combines this date with a time to create a {@code ChronoLocalDateTime}.
* <p>
! * This returns a {@code ChronoLocalDateTime} formed from this date at the specified time.
! * All possible combinations of date and time are valid.
*
* @param localTime the local time to use, not null
* @return the local date-time formed from this date and the specified time, not null
*/
! public default ChronoLocalDateTime<D> atTime(LocalTime localTime) {
! return (ChronoLocalDateTime<D>)ChronoLocalDateTimeImpl.of(this, localTime);
}
//-----------------------------------------------------------------------
/**
* Converts this date to the Epoch Day.
*** 576,586 ****
*/
@Override
public default int compareTo(ChronoLocalDate<?> other) {
int cmp = Long.compare(toEpochDay(), other.toEpochDay());
if (cmp == 0) {
! cmp = getChrono().compareTo(other.getChrono());
}
return cmp;
}
/**
--- 607,617 ----
*/
@Override
public default int compareTo(ChronoLocalDate<?> other) {
int cmp = Long.compare(toEpochDay(), other.toEpochDay());
if (cmp == 0) {
! cmp = getChronology().compareTo(other.getChronology());
}
return cmp;
}
/**
*** 674,691 ****
/**
* Outputs this date as a {@code String} using the formatter.
* <p>
* The default implementation must behave as follows:
* <pre>
! * return formatter.print(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
*/
public default String toString(DateTimeFormatter formatter) {
Objects.requireNonNull(formatter, "formatter");
! return formatter.print(this);
}
}
--- 705,722 ----
/**
* Outputs this date as a {@code String} using the formatter.
* <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
*/
public default String toString(DateTimeFormatter formatter) {
Objects.requireNonNull(formatter, "formatter");
! return formatter.format(this);
}
}