src/share/classes/java/time/chrono/ChronoLocalDate.java

Print this page

        

@@ -71,18 +71,18 @@
 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.time.temporal.UnsupportedTemporalTypeException;
 import java.util.Comparator;
 import java.util.Objects;
 
 /**
  * A date without time-of-day or time-zone in an arbitrary chronology, intended

@@ -247,29 +247,59 @@
  */
 public interface ChronoLocalDate<D extends ChronoLocalDate<D>>
         extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDate<?>> {
 
     /**
-     * Comparator for two {@code ChronoLocalDate}s ignoring the chronology.
+     * Gets a comparator that compares {@code ChronoLocalDate} in
+     * time-line order ignoring the chronology.
      * <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
-     * on the time-line position.
-     * This is equivalent to using {@code Long.compare(date1.toEpochDay(),  date2.toEpochDay())}.
+     * on the position of the date on the local time-line.
+     * The underlying comparison is equivalent to comparing the epoch-day.
      *
      * @see #isAfter
      * @see #isBefore
      * @see #isEqual
      */
-    public static final Comparator<ChronoLocalDate<?>> DATE_COMPARATOR =
-            new Comparator<ChronoLocalDate<?>>() {
-        @Override
-        public int compare(ChronoLocalDate<?> date1, ChronoLocalDate<?> date2) {
-            return Long.compare(date1.toEpochDay(), date2.toEpochDay());
+    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());
+        }
+        return chrono.date(temporal);
         }
-    };
 
     //-----------------------------------------------------------------------
     /**
      * Gets the chronology of this date.
      * <p>

@@ -293,11 +323,11 @@
      * <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() {
+    default Era getEra() {
         return getChronology().eraOf(get(ERA));
     }
 
     /**
      * Checks if the year is a leap year, as defined by the calendar system.

@@ -308,11 +338,11 @@
      * <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() {
+    default boolean isLeapYear() {
         return getChronology().isLeapYear(getLong(YEAR));
     }
 
     /**
      * Returns the length of the month represented by this date, as defined by the calendar system.

@@ -330,18 +360,18 @@
      * <p>
      * The default implementation uses {@link #isLeapYear()} and returns 365 or 366.
      *
      * @return the length of the year in days
      */
-    public default int lengthOfYear() {
+    default int lengthOfYear() {
         return (isLeapYear() ? 366 : 365);
     }
 
     @Override
-    public default boolean isSupported(TemporalField field) {
+    default boolean isSupported(TemporalField field) {
         if (field instanceof ChronoField) {
-            return ((ChronoField) field).isDateField();
+            return field.isDateBased();
         }
         return field != null && field.isSupportedBy(this);
     }
 
     //-----------------------------------------------------------------------

@@ -350,67 +380,69 @@
      * {@inheritDoc}
      * @throws DateTimeException {@inheritDoc}
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default D with(TemporalAdjuster adjuster) {
+    default D with(TemporalAdjuster adjuster) {
         return (D) getChronology().ensureChronoLocalDate(Temporal.super.with(adjuster));
     }
 
     /**
      * {@inheritDoc}
      * @throws DateTimeException {@inheritDoc}
+     * @throws UnsupportedTemporalTypeException {@inheritDoc}
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default D with(TemporalField field, long newValue) {
+    default D with(TemporalField field, long newValue) {
         if (field instanceof ChronoField) {
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("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) {
+    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) {
+    default D plus(long amountToAdd, TemporalUnit unit) {
         if (unit instanceof ChronoUnit) {
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("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) {
+    default D minus(TemporalAmount amount) {
         return (D) getChronology().ensureChronoLocalDate(Temporal.super.minus(amount));
     }
 
     /**
      * {@inheritDoc}
      * @throws DateTimeException {@inheritDoc}
+     * @throws UnsupportedTemporalTypeException {@inheritDoc}
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default D minus(long amountToSubtract, TemporalUnit unit) {
+    default D minus(long amountToSubtract, TemporalUnit unit) {
         return (D) getChronology().ensureChronoLocalDate(Temporal.super.minus(amountToSubtract, unit));
     }
 
     //-----------------------------------------------------------------------
     /**

@@ -431,18 +463,18 @@
      * @throws DateTimeException if unable to query (defined by the query)
      * @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()) {
+    default <R> R query(TemporalQuery<R> query) {
+        if (query == TemporalQuery.zoneId() || query == TemporalQuery.zone() || query == TemporalQuery.offset()) {
             return null;
-        } else if (query == Queries.localTime()) {
+        } else if (query == TemporalQuery.localTime()) {
             return null;
-        } else if (query == Queries.chronology()) {
+        } else if (query == TemporalQuery.chronology()) {
             return (R) getChronology();
-        } else if (query == Queries.precision()) {
+        } else if (query == TemporalQuery.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);

@@ -471,11 +503,11 @@
      * @return the adjusted object, not null
      * @throws DateTimeException if unable to make the adjustment
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
-    public default Temporal adjustInto(Temporal temporal) {
+    default Temporal adjustInto(Temporal temporal) {
         return temporal.with(EPOCH_DAY, toEpochDay());
     }
 
     /**
      * Calculates the period between this date and another date in

@@ -520,33 +552,50 @@
      * @return the amount of the period between this date and the end date
      * @throws DateTimeException if the period cannot be calculated
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override  // override for Javadoc
-    public abstract long periodUntil(Temporal endDate, TemporalUnit unit);
+    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.
+     * The negative sign will be the same in each of year, month and day.
      * <p>
-     * The calculation is performed using the the chronology of this date.
+     * The calculation is performed using 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);
+    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);
+    }
 
     //-----------------------------------------------------------------------
     /**
      * Combines this date with a time to create a {@code ChronoLocalDateTime}.
      * <p>

@@ -554,11 +603,11 @@
      * 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) {
+    default ChronoLocalDateTime<D> atTime(LocalTime localTime) {
         return (ChronoLocalDateTime<D>)ChronoLocalDateTimeImpl.of(this, localTime);
     }
 
     //-----------------------------------------------------------------------
     /**

@@ -570,11 +619,11 @@
      * <p>
      * This default implementation queries the {@code EPOCH_DAY} field.
      *
      * @return the Epoch Day equivalent to this date
      */
-    public default long toEpochDay() {
+    default long toEpochDay() {
         return getLong(EPOCH_DAY);
     }
 
     //-----------------------------------------------------------------------
     /**

@@ -604,11 +653,11 @@
      *
      * @param other  the other date to compare to, not null
      * @return the comparator value, negative if less, positive if greater
      */
     @Override
-    public default int compareTo(ChronoLocalDate<?> other) {
+    default int compareTo(ChronoLocalDate<?> other) {
         int cmp = Long.compare(toEpochDay(), other.toEpochDay());
         if (cmp == 0) {
             cmp = getChronology().compareTo(other.getChronology());
         }
         return cmp;

@@ -626,11 +675,11 @@
      * 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
      */
-    public default boolean isAfter(ChronoLocalDate<?> other) {
+    default boolean isAfter(ChronoLocalDate<?> other) {
         return this.toEpochDay() > other.toEpochDay();
     }
 
     /**
      * Checks if this date is before the specified date ignoring the chronology.

@@ -644,11 +693,11 @@
      * 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
      */
-    public default boolean isBefore(ChronoLocalDate<?> other) {
+    default boolean isBefore(ChronoLocalDate<?> other) {
         return this.toEpochDay() < other.toEpochDay();
     }
 
     /**
      * Checks if this date is equal to the specified date ignoring the chronology.

@@ -662,11 +711,11 @@
      * 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
      */
-    public default boolean isEqual(ChronoLocalDate<?> other) {
+    default boolean isEqual(ChronoLocalDate<?> other) {
         return this.toEpochDay() == other.toEpochDay();
     }
 
     //-----------------------------------------------------------------------
     /**

@@ -693,30 +742,13 @@
 
     //-----------------------------------------------------------------------
     /**
      * Outputs this date as a {@code String}.
      * <p>
-     * The output will include the full local date and the chronology ID.
+     * The output will include the full local date.
      *
      * @return the formatted date, not null
      */
     @Override
     String toString();
 
-    /**
-     * 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);
-    }
-
 }