Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTime.java
38918 views
/*1* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* This file is available under and governed by the GNU General Public27* License version 2 only, as published by the Free Software Foundation.28* However, the following notice accompanied the original version of this29* file:30*31* Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos32*33* All rights reserved.34*35* Redistribution and use in source and binary forms, with or without36* modification, are permitted provided that the following conditions are met:37*38* * Redistributions of source code must retain the above copyright notice,39* this list of conditions and the following disclaimer.40*41* * Redistributions in binary form must reproduce the above copyright notice,42* this list of conditions and the following disclaimer in the documentation43* and/or other materials provided with the distribution.44*45* * Neither the name of JSR-310 nor the names of its contributors46* may be used to endorse or promote products derived from this software47* without specific prior written permission.48*49* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS50* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT51* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR52* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR53* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,54* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,55* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR56* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF57* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING58* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS59* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.60*/61package java.time.chrono;6263import static java.time.temporal.ChronoField.EPOCH_DAY;64import static java.time.temporal.ChronoField.NANO_OF_DAY;65import static java.time.temporal.ChronoUnit.FOREVER;66import static java.time.temporal.ChronoUnit.NANOS;6768import java.time.DateTimeException;69import java.time.Instant;70import java.time.LocalDateTime;71import java.time.LocalTime;72import java.time.ZoneId;73import java.time.ZoneOffset;74import java.time.format.DateTimeFormatter;75import java.time.temporal.ChronoField;76import java.time.temporal.ChronoUnit;77import java.time.temporal.Temporal;78import java.time.temporal.TemporalAccessor;79import java.time.temporal.TemporalAdjuster;80import java.time.temporal.TemporalAmount;81import java.time.temporal.TemporalField;82import java.time.temporal.TemporalQueries;83import java.time.temporal.TemporalQuery;84import java.time.temporal.TemporalUnit;85import java.time.zone.ZoneRules;86import java.util.Comparator;87import java.util.Objects;8889/**90* A date-time without a time-zone in an arbitrary chronology, intended91* for advanced globalization use cases.92* <p>93* <b>Most applications should declare method signatures, fields and variables94* as {@link LocalDateTime}, not this interface.</b>95* <p>96* A {@code ChronoLocalDateTime} is the abstract representation of a local date-time97* where the {@code Chronology chronology}, or calendar system, is pluggable.98* The date-time is defined in terms of fields expressed by {@link TemporalField},99* where most common implementations are defined in {@link ChronoField}.100* The chronology defines how the calendar system operates and the meaning of101* the standard fields.102*103* <h3>When to use this interface</h3>104* The design of the API encourages the use of {@code LocalDateTime} rather than this105* interface, even in the case where the application needs to deal with multiple106* calendar systems. The rationale for this is explored in detail in {@link ChronoLocalDate}.107* <p>108* Ensure that the discussion in {@code ChronoLocalDate} has been read and understood109* before using this interface.110*111* @implSpec112* This interface must be implemented with care to ensure other classes operate correctly.113* All implementations that can be instantiated must be final, immutable and thread-safe.114* Subclasses should be Serializable wherever possible.115*116* @param <D> the concrete type for the date of this date-time117* @since 1.8118*/119public interface ChronoLocalDateTime<D extends ChronoLocalDate>120extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDateTime<?>> {121122/**123* Gets a comparator that compares {@code ChronoLocalDateTime} in124* time-line order ignoring the chronology.125* <p>126* This comparator differs from the comparison in {@link #compareTo} in that it127* only compares the underlying date-time and not the chronology.128* This allows dates in different calendar systems to be compared based129* on the position of the date-time on the local time-line.130* The underlying comparison is equivalent to comparing the epoch-day and nano-of-day.131*132* @return a comparator that compares in time-line order ignoring the chronology133* @see #isAfter134* @see #isBefore135* @see #isEqual136*/137static Comparator<ChronoLocalDateTime<?>> timeLineOrder() {138return AbstractChronology.DATE_TIME_ORDER;139}140141//-----------------------------------------------------------------------142/**143* Obtains an instance of {@code ChronoLocalDateTime} from a temporal object.144* <p>145* This obtains a local date-time based on the specified temporal.146* A {@code TemporalAccessor} represents an arbitrary set of date and time information,147* which this factory converts to an instance of {@code ChronoLocalDateTime}.148* <p>149* The conversion extracts and combines the chronology and the date-time150* from the temporal object. The behavior is equivalent to using151* {@link Chronology#localDateTime(TemporalAccessor)} with the extracted chronology.152* Implementations are permitted to perform optimizations such as accessing153* those fields that are equivalent to the relevant objects.154* <p>155* This method matches the signature of the functional interface {@link TemporalQuery}156* allowing it to be used as a query via method reference, {@code ChronoLocalDateTime::from}.157*158* @param temporal the temporal object to convert, not null159* @return the date-time, not null160* @throws DateTimeException if unable to convert to a {@code ChronoLocalDateTime}161* @see Chronology#localDateTime(TemporalAccessor)162*/163static ChronoLocalDateTime<?> from(TemporalAccessor temporal) {164if (temporal instanceof ChronoLocalDateTime) {165return (ChronoLocalDateTime<?>) temporal;166}167Objects.requireNonNull(temporal, "temporal");168Chronology chrono = temporal.query(TemporalQueries.chronology());169if (chrono == null) {170throw new DateTimeException("Unable to obtain ChronoLocalDateTime from TemporalAccessor: " + temporal.getClass());171}172return chrono.localDateTime(temporal);173}174175//-----------------------------------------------------------------------176/**177* Gets the chronology of this date-time.178* <p>179* The {@code Chronology} represents the calendar system in use.180* The era and other fields in {@link ChronoField} are defined by the chronology.181*182* @return the chronology, not null183*/184default Chronology getChronology() {185return toLocalDate().getChronology();186}187188/**189* Gets the local date part of this date-time.190* <p>191* This returns a local date with the same year, month and day192* as this date-time.193*194* @return the date part of this date-time, not null195*/196D toLocalDate() ;197198/**199* Gets the local time part of this date-time.200* <p>201* This returns a local time with the same hour, minute, second and202* nanosecond as this date-time.203*204* @return the time part of this date-time, not null205*/206LocalTime toLocalTime();207208/**209* Checks if the specified field is supported.210* <p>211* This checks if the specified field can be queried on this date-time.212* If false, then calling the {@link #range(TemporalField) range},213* {@link #get(TemporalField) get} and {@link #with(TemporalField, long)}214* methods will throw an exception.215* <p>216* The set of supported fields is defined by the chronology and normally includes217* all {@code ChronoField} date and time fields.218* <p>219* If the field is not a {@code ChronoField}, then the result of this method220* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}221* passing {@code this} as the argument.222* Whether the field is supported is determined by the field.223*224* @param field the field to check, null returns false225* @return true if the field can be queried, false if not226*/227@Override228boolean isSupported(TemporalField field);229230/**231* Checks if the specified unit is supported.232* <p>233* This checks if the specified unit can be added to or subtracted from this date-time.234* If false, then calling the {@link #plus(long, TemporalUnit)} and235* {@link #minus(long, TemporalUnit) minus} methods will throw an exception.236* <p>237* The set of supported units is defined by the chronology and normally includes238* all {@code ChronoUnit} units except {@code FOREVER}.239* <p>240* If the unit is not a {@code ChronoUnit}, then the result of this method241* is obtained by invoking {@code TemporalUnit.isSupportedBy(Temporal)}242* passing {@code this} as the argument.243* Whether the unit is supported is determined by the unit.244*245* @param unit the unit to check, null returns false246* @return true if the unit can be added/subtracted, false if not247*/248@Override249default boolean isSupported(TemporalUnit unit) {250if (unit instanceof ChronoUnit) {251return unit != FOREVER;252}253return unit != null && unit.isSupportedBy(this);254}255256//-----------------------------------------------------------------------257// override for covariant return type258/**259* {@inheritDoc}260* @throws DateTimeException {@inheritDoc}261* @throws ArithmeticException {@inheritDoc}262*/263@Override264default ChronoLocalDateTime<D> with(TemporalAdjuster adjuster) {265return ChronoLocalDateTimeImpl.ensureValid(getChronology(), Temporal.super.with(adjuster));266}267268/**269* {@inheritDoc}270* @throws DateTimeException {@inheritDoc}271* @throws ArithmeticException {@inheritDoc}272*/273@Override274ChronoLocalDateTime<D> with(TemporalField field, long newValue);275276/**277* {@inheritDoc}278* @throws DateTimeException {@inheritDoc}279* @throws ArithmeticException {@inheritDoc}280*/281@Override282default ChronoLocalDateTime<D> plus(TemporalAmount amount) {283return ChronoLocalDateTimeImpl.ensureValid(getChronology(), Temporal.super.plus(amount));284}285286/**287* {@inheritDoc}288* @throws DateTimeException {@inheritDoc}289* @throws ArithmeticException {@inheritDoc}290*/291@Override292ChronoLocalDateTime<D> plus(long amountToAdd, TemporalUnit unit);293294/**295* {@inheritDoc}296* @throws DateTimeException {@inheritDoc}297* @throws ArithmeticException {@inheritDoc}298*/299@Override300default ChronoLocalDateTime<D> minus(TemporalAmount amount) {301return ChronoLocalDateTimeImpl.ensureValid(getChronology(), Temporal.super.minus(amount));302}303304/**305* {@inheritDoc}306* @throws DateTimeException {@inheritDoc}307* @throws ArithmeticException {@inheritDoc}308*/309@Override310default ChronoLocalDateTime<D> minus(long amountToSubtract, TemporalUnit unit) {311return ChronoLocalDateTimeImpl.ensureValid(getChronology(), Temporal.super.minus(amountToSubtract, unit));312}313314//-----------------------------------------------------------------------315/**316* Queries this date-time using the specified query.317* <p>318* This queries this date-time using the specified query strategy object.319* The {@code TemporalQuery} object defines the logic to be used to320* obtain the result. Read the documentation of the query to understand321* what the result of this method will be.322* <p>323* The result of this method is obtained by invoking the324* {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the325* specified query passing {@code this} as the argument.326*327* @param <R> the type of the result328* @param query the query to invoke, not null329* @return the query result, null may be returned (defined by the query)330* @throws DateTimeException if unable to query (defined by the query)331* @throws ArithmeticException if numeric overflow occurs (defined by the query)332*/333@SuppressWarnings("unchecked")334@Override335default <R> R query(TemporalQuery<R> query) {336if (query == TemporalQueries.zoneId() || query == TemporalQueries.zone() || query == TemporalQueries.offset()) {337return null;338} else if (query == TemporalQueries.localTime()) {339return (R) toLocalTime();340} else if (query == TemporalQueries.chronology()) {341return (R) getChronology();342} else if (query == TemporalQueries.precision()) {343return (R) NANOS;344}345// inline TemporalAccessor.super.query(query) as an optimization346// non-JDK classes are not permitted to make this optimization347return query.queryFrom(this);348}349350/**351* Adjusts the specified temporal object to have the same date and time as this object.352* <p>353* This returns a temporal object of the same observable type as the input354* with the date and time changed to be the same as this.355* <p>356* The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}357* twice, passing {@link ChronoField#EPOCH_DAY} and358* {@link ChronoField#NANO_OF_DAY} as the fields.359* <p>360* In most cases, it is clearer to reverse the calling pattern by using361* {@link Temporal#with(TemporalAdjuster)}:362* <pre>363* // these two lines are equivalent, but the second approach is recommended364* temporal = thisLocalDateTime.adjustInto(temporal);365* temporal = temporal.with(thisLocalDateTime);366* </pre>367* <p>368* This instance is immutable and unaffected by this method call.369*370* @param temporal the target object to be adjusted, not null371* @return the adjusted object, not null372* @throws DateTimeException if unable to make the adjustment373* @throws ArithmeticException if numeric overflow occurs374*/375@Override376default Temporal adjustInto(Temporal temporal) {377return temporal378.with(EPOCH_DAY, toLocalDate().toEpochDay())379.with(NANO_OF_DAY, toLocalTime().toNanoOfDay());380}381382/**383* Formats this date-time using the specified formatter.384* <p>385* This date-time will be passed to the formatter to produce a string.386* <p>387* The default implementation must behave as follows:388* <pre>389* return formatter.format(this);390* </pre>391*392* @param formatter the formatter to use, not null393* @return the formatted date-time string, not null394* @throws DateTimeException if an error occurs during printing395*/396default String format(DateTimeFormatter formatter) {397Objects.requireNonNull(formatter, "formatter");398return formatter.format(this);399}400401//-----------------------------------------------------------------------402/**403* Combines this time with a time-zone to create a {@code ChronoZonedDateTime}.404* <p>405* This returns a {@code ChronoZonedDateTime} formed from this date-time at the406* specified time-zone. The result will match this date-time as closely as possible.407* Time-zone rules, such as daylight savings, mean that not every local date-time408* is valid for the specified zone, thus the local date-time may be adjusted.409* <p>410* The local date-time is resolved to a single instant on the time-line.411* This is achieved by finding a valid offset from UTC/Greenwich for the local412* date-time as defined by the {@link ZoneRules rules} of the zone ID.413*<p>414* In most cases, there is only one valid offset for a local date-time.415* In the case of an overlap, where clocks are set back, there are two valid offsets.416* This method uses the earlier offset typically corresponding to "summer".417* <p>418* In the case of a gap, where clocks jump forward, there is no valid offset.419* Instead, the local date-time is adjusted to be later by the length of the gap.420* For a typical one hour daylight savings change, the local date-time will be421* moved one hour later into the offset typically corresponding to "summer".422* <p>423* To obtain the later offset during an overlap, call424* {@link ChronoZonedDateTime#withLaterOffsetAtOverlap()} on the result of this method.425*426* @param zone the time-zone to use, not null427* @return the zoned date-time formed from this date-time, not null428*/429ChronoZonedDateTime<D> atZone(ZoneId zone);430431//-----------------------------------------------------------------------432/**433* Converts this date-time to an {@code Instant}.434* <p>435* This combines this local date-time and the specified offset to form436* an {@code Instant}.437* <p>438* This default implementation calculates from the epoch-day of the date and the439* second-of-day of the time.440*441* @param offset the offset to use for the conversion, not null442* @return an {@code Instant} representing the same instant, not null443*/444default Instant toInstant(ZoneOffset offset) {445return Instant.ofEpochSecond(toEpochSecond(offset), toLocalTime().getNano());446}447448/**449* Converts this date-time to the number of seconds from the epoch450* of 1970-01-01T00:00:00Z.451* <p>452* This combines this local date-time and the specified offset to calculate the453* epoch-second value, which is the number of elapsed seconds from 1970-01-01T00:00:00Z.454* Instants on the time-line after the epoch are positive, earlier are negative.455* <p>456* This default implementation calculates from the epoch-day of the date and the457* second-of-day of the time.458*459* @param offset the offset to use for the conversion, not null460* @return the number of seconds from the epoch of 1970-01-01T00:00:00Z461*/462default long toEpochSecond(ZoneOffset offset) {463Objects.requireNonNull(offset, "offset");464long epochDay = toLocalDate().toEpochDay();465long secs = epochDay * 86400 + toLocalTime().toSecondOfDay();466secs -= offset.getTotalSeconds();467return secs;468}469470//-----------------------------------------------------------------------471/**472* Compares this date-time to another date-time, including the chronology.473* <p>474* The comparison is based first on the underlying time-line date-time, then475* on the chronology.476* It is "consistent with equals", as defined by {@link Comparable}.477* <p>478* For example, the following is the comparator order:479* <ol>480* <li>{@code 2012-12-03T12:00 (ISO)}</li>481* <li>{@code 2012-12-04T12:00 (ISO)}</li>482* <li>{@code 2555-12-04T12:00 (ThaiBuddhist)}</li>483* <li>{@code 2012-12-05T12:00 (ISO)}</li>484* </ol>485* Values #2 and #3 represent the same date-time on the time-line.486* When two values represent the same date-time, the chronology ID is compared to distinguish them.487* This step is needed to make the ordering "consistent with equals".488* <p>489* If all the date-time objects being compared are in the same chronology, then the490* additional chronology stage is not required and only the local date-time is used.491* <p>492* This default implementation performs the comparison defined above.493*494* @param other the other date-time to compare to, not null495* @return the comparator value, negative if less, positive if greater496*/497@Override498default int compareTo(ChronoLocalDateTime<?> other) {499int cmp = toLocalDate().compareTo(other.toLocalDate());500if (cmp == 0) {501cmp = toLocalTime().compareTo(other.toLocalTime());502if (cmp == 0) {503cmp = getChronology().compareTo(other.getChronology());504}505}506return cmp;507}508509/**510* Checks if this date-time is after the specified date-time ignoring the chronology.511* <p>512* This method differs from the comparison in {@link #compareTo} in that it513* only compares the underlying date-time and not the chronology.514* This allows dates in different calendar systems to be compared based515* on the time-line position.516* <p>517* This default implementation performs the comparison based on the epoch-day518* and nano-of-day.519*520* @param other the other date-time to compare to, not null521* @return true if this is after the specified date-time522*/523default boolean isAfter(ChronoLocalDateTime<?> other) {524long thisEpDay = this.toLocalDate().toEpochDay();525long otherEpDay = other.toLocalDate().toEpochDay();526return thisEpDay > otherEpDay ||527(thisEpDay == otherEpDay && this.toLocalTime().toNanoOfDay() > other.toLocalTime().toNanoOfDay());528}529530/**531* Checks if this date-time is before the specified date-time ignoring the chronology.532* <p>533* This method differs from the comparison in {@link #compareTo} in that it534* only compares the underlying date-time and not the chronology.535* This allows dates in different calendar systems to be compared based536* on the time-line position.537* <p>538* This default implementation performs the comparison based on the epoch-day539* and nano-of-day.540*541* @param other the other date-time to compare to, not null542* @return true if this is before the specified date-time543*/544default boolean isBefore(ChronoLocalDateTime<?> other) {545long thisEpDay = this.toLocalDate().toEpochDay();546long otherEpDay = other.toLocalDate().toEpochDay();547return thisEpDay < otherEpDay ||548(thisEpDay == otherEpDay && this.toLocalTime().toNanoOfDay() < other.toLocalTime().toNanoOfDay());549}550551/**552* Checks if this date-time is equal to the specified date-time ignoring the chronology.553* <p>554* This method differs from the comparison in {@link #compareTo} in that it555* only compares the underlying date and time and not the chronology.556* This allows date-times in different calendar systems to be compared based557* on the time-line position.558* <p>559* This default implementation performs the comparison based on the epoch-day560* and nano-of-day.561*562* @param other the other date-time to compare to, not null563* @return true if the underlying date-time is equal to the specified date-time on the timeline564*/565default boolean isEqual(ChronoLocalDateTime<?> other) {566// Do the time check first, it is cheaper than computing EPOCH day.567return this.toLocalTime().toNanoOfDay() == other.toLocalTime().toNanoOfDay() &&568this.toLocalDate().toEpochDay() == other.toLocalDate().toEpochDay();569}570571/**572* Checks if this date-time is equal to another date-time, including the chronology.573* <p>574* Compares this date-time with another ensuring that the date-time and chronology are the same.575*576* @param obj the object to check, null returns false577* @return true if this is equal to the other date578*/579@Override580boolean equals(Object obj);581582/**583* A hash code for this date-time.584*585* @return a suitable hash code586*/587@Override588int hashCode();589590//-----------------------------------------------------------------------591/**592* Outputs this date-time as a {@code String}.593* <p>594* The output will include the full local date-time.595*596* @return a string representation of this date-time, not null597*/598@Override599String toString();600601}602603604