jdk/src/share/classes/java/time/chrono/ChronoLocalDateTime.java
changeset 16852 60207b2b4b42
parent 15658 55b829ca2334
child 17474 8c100beabcc0
equal deleted inserted replaced
16851:3bbdae468b05 16852:60207b2b4b42
    71 import java.time.LocalTime;
    71 import java.time.LocalTime;
    72 import java.time.ZoneId;
    72 import java.time.ZoneId;
    73 import java.time.ZoneOffset;
    73 import java.time.ZoneOffset;
    74 import java.time.format.DateTimeFormatter;
    74 import java.time.format.DateTimeFormatter;
    75 import java.time.temporal.ChronoField;
    75 import java.time.temporal.ChronoField;
    76 import java.time.temporal.Queries;
       
    77 import java.time.temporal.Temporal;
    76 import java.time.temporal.Temporal;
    78 import java.time.temporal.TemporalAccessor;
    77 import java.time.temporal.TemporalAccessor;
    79 import java.time.temporal.TemporalAdjuster;
    78 import java.time.temporal.TemporalAdjuster;
    80 import java.time.temporal.TemporalAmount;
    79 import java.time.temporal.TemporalAmount;
    81 import java.time.temporal.TemporalField;
    80 import java.time.temporal.TemporalField;
   117  */
   116  */
   118 public interface ChronoLocalDateTime<D extends ChronoLocalDate<D>>
   117 public interface ChronoLocalDateTime<D extends ChronoLocalDate<D>>
   119         extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDateTime<?>> {
   118         extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDateTime<?>> {
   120 
   119 
   121     /**
   120     /**
   122      * Comparator for two {@code ChronoLocalDateTime} instances ignoring the chronology.
   121      * Gets a comparator that compares {@code ChronoLocalDateTime} in
   123      * <p>
   122      * time-line order ignoring the chronology.
   124      * This method differs from the comparison in {@link #compareTo} in that it
   123      * <p>
   125      * only compares the underlying date and not the chronology.
   124      * This comparator differs from the comparison in {@link #compareTo} in that it
       
   125      * only compares the underlying date-time and not the chronology.
   126      * This allows dates in different calendar systems to be compared based
   126      * This allows dates in different calendar systems to be compared based
   127      * on the time-line position.
   127      * on the position of the date-time on the local time-line.
       
   128      * The underlying comparison is equivalent to comparing the epoch-day and nano-of-day.
   128      *
   129      *
   129      * @see #isAfter
   130      * @see #isAfter
   130      * @see #isBefore
   131      * @see #isBefore
   131      * @see #isEqual
   132      * @see #isEqual
   132      */
   133      */
   133     Comparator<ChronoLocalDateTime<?>> DATE_TIME_COMPARATOR =
   134     static Comparator<ChronoLocalDateTime<?>> timeLineOrder() {
   134             new Comparator<ChronoLocalDateTime<?>>() {
   135         return Chronology.DATE_TIME_ORDER;
   135         @Override
   136     }
   136         public int compare(ChronoLocalDateTime<?> datetime1, ChronoLocalDateTime<?> datetime2) {
   137 
   137             int cmp = Long.compare(datetime1.toLocalDate().toEpochDay(), datetime2.toLocalDate().toEpochDay());
   138     //-----------------------------------------------------------------------
   138             if (cmp == 0) {
   139     /**
   139                 cmp = Long.compare(datetime1.toLocalTime().toNanoOfDay(), datetime2.toLocalTime().toNanoOfDay());
   140      * Obtains an instance of {@code ChronoLocalDateTime} from a temporal object.
   140             }
   141      * <p>
   141             return cmp;
   142      * This obtains a local date-time based on the specified temporal.
       
   143      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
       
   144      * which this factory converts to an instance of {@code ChronoLocalDateTime}.
       
   145      * <p>
       
   146      * The conversion extracts and combines the chronology and the date-time
       
   147      * from the temporal object. The behavior is equivalent to using
       
   148      * {@link Chronology#localDateTime(TemporalAccessor)} with the extracted chronology.
       
   149      * Implementations are permitted to perform optimizations such as accessing
       
   150      * those fields that are equivalent to the relevant objects.
       
   151      * <p>
       
   152      * This method matches the signature of the functional interface {@link TemporalQuery}
       
   153      * allowing it to be used as a query via method reference, {@code ChronoLocalDateTime::from}.
       
   154      *
       
   155      * @param temporal  the temporal object to convert, not null
       
   156      * @return the date-time, not null
       
   157      * @throws DateTimeException if unable to convert to a {@code ChronoLocalDateTime}
       
   158      * @see Chronology#localDateTime(TemporalAccessor)
       
   159      */
       
   160     static ChronoLocalDateTime<?> from(TemporalAccessor temporal) {
       
   161         if (temporal instanceof ChronoLocalDateTime) {
       
   162             return (ChronoLocalDateTime<?>) temporal;
   142         }
   163         }
   143     };
   164         Chronology chrono = temporal.query(TemporalQuery.chronology());
   144 
   165         if (chrono == null) {
       
   166             throw new DateTimeException("Unable to obtain ChronoLocalDateTime from TemporalAccessor: " + temporal.getClass());
       
   167         }
       
   168         return chrono.localDateTime(temporal);
       
   169     }
       
   170 
       
   171     //-----------------------------------------------------------------------
   145     /**
   172     /**
   146      * Gets the local date part of this date-time.
   173      * Gets the local date part of this date-time.
   147      * <p>
   174      * <p>
   148      * This returns a local date with the same year, month and day
   175      * This returns a local date with the same year, month and day
   149      * as this date-time.
   176      * as this date-time.
   161      * @return the time part of this date-time, not null
   188      * @return the time part of this date-time, not null
   162      */
   189      */
   163     LocalTime toLocalTime();
   190     LocalTime toLocalTime();
   164 
   191 
   165     @Override   // Override to provide javadoc
   192     @Override   // Override to provide javadoc
   166     public boolean isSupported(TemporalField field);
   193     boolean isSupported(TemporalField field);
   167 
   194 
   168     //-----------------------------------------------------------------------
   195     //-----------------------------------------------------------------------
   169     // override for covariant return type
   196     // override for covariant return type
   170     /**
   197     /**
   171      * {@inheritDoc}
   198      * {@inheritDoc}
   172      * @throws DateTimeException {@inheritDoc}
   199      * @throws DateTimeException {@inheritDoc}
   173      * @throws ArithmeticException {@inheritDoc}
   200      * @throws ArithmeticException {@inheritDoc}
   174      */
   201      */
   175     @Override
   202     @Override
   176     public default ChronoLocalDateTime<D> with(TemporalAdjuster adjuster) {
   203     default ChronoLocalDateTime<D> with(TemporalAdjuster adjuster) {
   177         return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.with(adjuster)));
   204         return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.with(adjuster)));
   178     }
   205     }
   179 
   206 
   180     /**
   207     /**
   181      * {@inheritDoc}
   208      * {@inheritDoc}
   189      * {@inheritDoc}
   216      * {@inheritDoc}
   190      * @throws DateTimeException {@inheritDoc}
   217      * @throws DateTimeException {@inheritDoc}
   191      * @throws ArithmeticException {@inheritDoc}
   218      * @throws ArithmeticException {@inheritDoc}
   192      */
   219      */
   193     @Override
   220     @Override
   194     public default ChronoLocalDateTime<D> plus(TemporalAmount amount) {
   221     default ChronoLocalDateTime<D> plus(TemporalAmount amount) {
   195         return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.plus(amount)));
   222         return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.plus(amount)));
   196     }
   223     }
   197 
   224 
   198     /**
   225     /**
   199      * {@inheritDoc}
   226      * {@inheritDoc}
   207      * {@inheritDoc}
   234      * {@inheritDoc}
   208      * @throws DateTimeException {@inheritDoc}
   235      * @throws DateTimeException {@inheritDoc}
   209      * @throws ArithmeticException {@inheritDoc}
   236      * @throws ArithmeticException {@inheritDoc}
   210      */
   237      */
   211     @Override
   238     @Override
   212     public default ChronoLocalDateTime<D> minus(TemporalAmount amount) {
   239     default ChronoLocalDateTime<D> minus(TemporalAmount amount) {
   213         return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.minus(amount)));
   240         return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.minus(amount)));
   214     }
   241     }
   215 
   242 
   216     /**
   243     /**
   217      * {@inheritDoc}
   244      * {@inheritDoc}
   218      * @throws DateTimeException {@inheritDoc}
   245      * @throws DateTimeException {@inheritDoc}
   219      * @throws ArithmeticException {@inheritDoc}
   246      * @throws ArithmeticException {@inheritDoc}
   220      */
   247      */
   221     @Override
   248     @Override
   222     public default ChronoLocalDateTime<D> minus(long amountToSubtract, TemporalUnit unit) {
   249     default ChronoLocalDateTime<D> minus(long amountToSubtract, TemporalUnit unit) {
   223         return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.minus(amountToSubtract, unit)));
   250         return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.minus(amountToSubtract, unit)));
   224     }
   251     }
   225 
   252 
   226     //-----------------------------------------------------------------------
   253     //-----------------------------------------------------------------------
   227     /**
   254     /**
   242      * @throws DateTimeException if unable to query (defined by the query)
   269      * @throws DateTimeException if unable to query (defined by the query)
   243      * @throws ArithmeticException if numeric overflow occurs (defined by the query)
   270      * @throws ArithmeticException if numeric overflow occurs (defined by the query)
   244      */
   271      */
   245     @SuppressWarnings("unchecked")
   272     @SuppressWarnings("unchecked")
   246     @Override
   273     @Override
   247     public default <R> R query(TemporalQuery<R> query) {
   274     default <R> R query(TemporalQuery<R> query) {
   248         if (query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
   275         if (query == TemporalQuery.zoneId() || query == TemporalQuery.zone() || query == TemporalQuery.offset()) {
   249             return null;
   276             return null;
   250         } else if (query == Queries.localTime()) {
   277         } else if (query == TemporalQuery.localTime()) {
   251             return (R) toLocalTime();
   278             return (R) toLocalTime();
   252         } else if (query == Queries.chronology()) {
   279         } else if (query == TemporalQuery.chronology()) {
   253             return (R) toLocalDate().getChronology();
   280             return (R) toLocalDate().getChronology();
   254         } else if (query == Queries.precision()) {
   281         } else if (query == TemporalQuery.precision()) {
   255             return (R) NANOS;
   282             return (R) NANOS;
   256         }
   283         }
   257         // inline TemporalAccessor.super.query(query) as an optimization
   284         // inline TemporalAccessor.super.query(query) as an optimization
   258         // non-JDK classes are not permitted to make this optimization
   285         // non-JDK classes are not permitted to make this optimization
   259         return query.queryFrom(this);
   286         return query.queryFrom(this);
   283      * @return the adjusted object, not null
   310      * @return the adjusted object, not null
   284      * @throws DateTimeException if unable to make the adjustment
   311      * @throws DateTimeException if unable to make the adjustment
   285      * @throws ArithmeticException if numeric overflow occurs
   312      * @throws ArithmeticException if numeric overflow occurs
   286      */
   313      */
   287     @Override
   314     @Override
   288     public default Temporal adjustInto(Temporal temporal) {
   315     default Temporal adjustInto(Temporal temporal) {
   289         return temporal
   316         return temporal
   290                 .with(EPOCH_DAY, toLocalDate().toEpochDay())
   317                 .with(EPOCH_DAY, toLocalDate().toEpochDay())
   291                 .with(NANO_OF_DAY, toLocalTime().toNanoOfDay());
   318                 .with(NANO_OF_DAY, toLocalTime().toNanoOfDay());
       
   319     }
       
   320 
       
   321     /**
       
   322      * Formats this date-time using the specified formatter.
       
   323      * <p>
       
   324      * This date-time will be passed to the formatter to produce a string.
       
   325      * <p>
       
   326      * The default implementation must behave as follows:
       
   327      * <pre>
       
   328      *  return formatter.format(this);
       
   329      * </pre>
       
   330      *
       
   331      * @param formatter  the formatter to use, not null
       
   332      * @return the formatted date-time string, not null
       
   333      * @throws DateTimeException if an error occurs during printing
       
   334      */
       
   335     default String format(DateTimeFormatter formatter) {
       
   336         Objects.requireNonNull(formatter, "formatter");
       
   337         return formatter.format(this);
   292     }
   338     }
   293 
   339 
   294     //-----------------------------------------------------------------------
   340     //-----------------------------------------------------------------------
   295     /**
   341     /**
   296      * Combines this time with a time-zone to create a {@code ChronoZonedDateTime}.
   342      * Combines this time with a time-zone to create a {@code ChronoZonedDateTime}.
   332      * second-of-day of the time.
   378      * second-of-day of the time.
   333      *
   379      *
   334      * @param offset  the offset to use for the conversion, not null
   380      * @param offset  the offset to use for the conversion, not null
   335      * @return an {@code Instant} representing the same instant, not null
   381      * @return an {@code Instant} representing the same instant, not null
   336      */
   382      */
   337     public default Instant toInstant(ZoneOffset offset) {
   383     default Instant toInstant(ZoneOffset offset) {
   338         return Instant.ofEpochSecond(toEpochSecond(offset), toLocalTime().getNano());
   384         return Instant.ofEpochSecond(toEpochSecond(offset), toLocalTime().getNano());
   339     }
   385     }
   340 
   386 
   341     /**
   387     /**
   342      * Converts this date-time to the number of seconds from the epoch
   388      * Converts this date-time to the number of seconds from the epoch
   350      * second-of-day of the time.
   396      * second-of-day of the time.
   351      *
   397      *
   352      * @param offset  the offset to use for the conversion, not null
   398      * @param offset  the offset to use for the conversion, not null
   353      * @return the number of seconds from the epoch of 1970-01-01T00:00:00Z
   399      * @return the number of seconds from the epoch of 1970-01-01T00:00:00Z
   354      */
   400      */
   355     public default long toEpochSecond(ZoneOffset offset) {
   401     default long toEpochSecond(ZoneOffset offset) {
   356         Objects.requireNonNull(offset, "offset");
   402         Objects.requireNonNull(offset, "offset");
   357         long epochDay = toLocalDate().toEpochDay();
   403         long epochDay = toLocalDate().toEpochDay();
   358         long secs = epochDay * 86400 + toLocalTime().toSecondOfDay();
   404         long secs = epochDay * 86400 + toLocalTime().toSecondOfDay();
   359         secs -= offset.getTotalSeconds();
   405         secs -= offset.getTotalSeconds();
   360         return secs;
   406         return secs;
   386      *
   432      *
   387      * @param other  the other date-time to compare to, not null
   433      * @param other  the other date-time to compare to, not null
   388      * @return the comparator value, negative if less, positive if greater
   434      * @return the comparator value, negative if less, positive if greater
   389      */
   435      */
   390     @Override
   436     @Override
   391     public default int compareTo(ChronoLocalDateTime<?> other) {
   437     default int compareTo(ChronoLocalDateTime<?> other) {
   392         int cmp = toLocalDate().compareTo(other.toLocalDate());
   438         int cmp = toLocalDate().compareTo(other.toLocalDate());
   393         if (cmp == 0) {
   439         if (cmp == 0) {
   394             cmp = toLocalTime().compareTo(other.toLocalTime());
   440             cmp = toLocalTime().compareTo(other.toLocalTime());
   395             if (cmp == 0) {
   441             if (cmp == 0) {
   396                 cmp = toLocalDate().getChronology().compareTo(other.toLocalDate().getChronology());
   442                 cmp = toLocalDate().getChronology().compareTo(other.toLocalDate().getChronology());
   411      * and nano-of-day.
   457      * and nano-of-day.
   412      *
   458      *
   413      * @param other  the other date-time to compare to, not null
   459      * @param other  the other date-time to compare to, not null
   414      * @return true if this is after the specified date-time
   460      * @return true if this is after the specified date-time
   415      */
   461      */
   416     public default boolean isAfter(ChronoLocalDateTime<?> other) {
   462     default boolean isAfter(ChronoLocalDateTime<?> other) {
   417         long thisEpDay = this.toLocalDate().toEpochDay();
   463         long thisEpDay = this.toLocalDate().toEpochDay();
   418         long otherEpDay = other.toLocalDate().toEpochDay();
   464         long otherEpDay = other.toLocalDate().toEpochDay();
   419         return thisEpDay > otherEpDay ||
   465         return thisEpDay > otherEpDay ||
   420             (thisEpDay == otherEpDay && this.toLocalTime().toNanoOfDay() > other.toLocalTime().toNanoOfDay());
   466             (thisEpDay == otherEpDay && this.toLocalTime().toNanoOfDay() > other.toLocalTime().toNanoOfDay());
   421     }
   467     }
   432      * and nano-of-day.
   478      * and nano-of-day.
   433      *
   479      *
   434      * @param other  the other date-time to compare to, not null
   480      * @param other  the other date-time to compare to, not null
   435      * @return true if this is before the specified date-time
   481      * @return true if this is before the specified date-time
   436      */
   482      */
   437     public default boolean isBefore(ChronoLocalDateTime<?> other) {
   483     default boolean isBefore(ChronoLocalDateTime<?> other) {
   438         long thisEpDay = this.toLocalDate().toEpochDay();
   484         long thisEpDay = this.toLocalDate().toEpochDay();
   439         long otherEpDay = other.toLocalDate().toEpochDay();
   485         long otherEpDay = other.toLocalDate().toEpochDay();
   440         return thisEpDay < otherEpDay ||
   486         return thisEpDay < otherEpDay ||
   441             (thisEpDay == otherEpDay && this.toLocalTime().toNanoOfDay() < other.toLocalTime().toNanoOfDay());
   487             (thisEpDay == otherEpDay && this.toLocalTime().toNanoOfDay() < other.toLocalTime().toNanoOfDay());
   442     }
   488     }
   453      * and nano-of-day.
   499      * and nano-of-day.
   454      *
   500      *
   455      * @param other  the other date-time to compare to, not null
   501      * @param other  the other date-time to compare to, not null
   456      * @return true if the underlying date-time is equal to the specified date-time on the timeline
   502      * @return true if the underlying date-time is equal to the specified date-time on the timeline
   457      */
   503      */
   458     public default boolean isEqual(ChronoLocalDateTime<?> other) {
   504     default boolean isEqual(ChronoLocalDateTime<?> other) {
   459         // Do the time check first, it is cheaper than computing EPOCH day.
   505         // Do the time check first, it is cheaper than computing EPOCH day.
   460         return this.toLocalTime().toNanoOfDay() == other.toLocalTime().toNanoOfDay() &&
   506         return this.toLocalTime().toNanoOfDay() == other.toLocalTime().toNanoOfDay() &&
   461                this.toLocalDate().toEpochDay() == other.toLocalDate().toEpochDay();
   507                this.toLocalDate().toEpochDay() == other.toLocalDate().toEpochDay();
   462     }
   508     }
   463 
   509 
   482 
   528 
   483     //-----------------------------------------------------------------------
   529     //-----------------------------------------------------------------------
   484     /**
   530     /**
   485      * Outputs this date-time as a {@code String}.
   531      * Outputs this date-time as a {@code String}.
   486      * <p>
   532      * <p>
   487      * The output will include the full local date-time and the chronology ID.
   533      * The output will include the full local date-time.
   488      *
   534      *
   489      * @return a string representation of this date-time, not null
   535      * @return a string representation of this date-time, not null
   490      */
   536      */
   491     @Override
   537     @Override
   492     String toString();
   538     String toString();
   493 
   539 
   494     /**
       
   495      * Outputs this date-time as a {@code String} using the formatter.
       
   496      * <p>
       
   497      * The default implementation must behave as follows:
       
   498      * <pre>
       
   499      *  return formatter.format(this);
       
   500      * </pre>
       
   501      *
       
   502      * @param formatter  the formatter to use, not null
       
   503      * @return the formatted date-time string, not null
       
   504      * @throws DateTimeException if an error occurs during printing
       
   505      */
       
   506     public default String toString(DateTimeFormatter formatter) {
       
   507         Objects.requireNonNull(formatter, "formatter");
       
   508         return formatter.format(this);
       
   509     }
       
   510 }
   540 }