Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/time/ZonedDateTime.java
38829 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;6263import static java.time.temporal.ChronoField.INSTANT_SECONDS;64import static java.time.temporal.ChronoField.NANO_OF_SECOND;65import static java.time.temporal.ChronoField.OFFSET_SECONDS;6667import java.io.DataOutput;68import java.io.IOException;69import java.io.ObjectInput;70import java.io.InvalidObjectException;71import java.io.ObjectInputStream;72import java.io.Serializable;73import java.time.chrono.ChronoZonedDateTime;74import java.time.format.DateTimeFormatter;75import java.time.format.DateTimeParseException;76import java.time.temporal.ChronoField;77import java.time.temporal.ChronoUnit;78import java.time.temporal.Temporal;79import java.time.temporal.TemporalAccessor;80import java.time.temporal.TemporalAdjuster;81import java.time.temporal.TemporalAmount;82import java.time.temporal.TemporalField;83import java.time.temporal.TemporalQueries;84import java.time.temporal.TemporalQuery;85import java.time.temporal.TemporalUnit;86import java.time.temporal.UnsupportedTemporalTypeException;87import java.time.temporal.ValueRange;88import java.time.zone.ZoneOffsetTransition;89import java.time.zone.ZoneRules;90import java.util.List;91import java.util.Objects;9293/**94* A date-time with a time-zone in the ISO-8601 calendar system,95* such as {@code 2007-12-03T10:15:30+01:00 Europe/Paris}.96* <p>97* {@code ZonedDateTime} is an immutable representation of a date-time with a time-zone.98* This class stores all date and time fields, to a precision of nanoseconds,99* and a time-zone, with a zone offset used to handle ambiguous local date-times.100* For example, the value101* "2nd October 2007 at 13:45.30.123456789 +02:00 in the Europe/Paris time-zone"102* can be stored in a {@code ZonedDateTime}.103* <p>104* This class handles conversion from the local time-line of {@code LocalDateTime}105* to the instant time-line of {@code Instant}.106* The difference between the two time-lines is the offset from UTC/Greenwich,107* represented by a {@code ZoneOffset}.108* <p>109* Converting between the two time-lines involves calculating the offset using the110* {@link ZoneRules rules} accessed from the {@code ZoneId}.111* Obtaining the offset for an instant is simple, as there is exactly one valid112* offset for each instant. By contrast, obtaining the offset for a local date-time113* is not straightforward. There are three cases:114* <ul>115* <li>Normal, with one valid offset. For the vast majority of the year, the normal116* case applies, where there is a single valid offset for the local date-time.</li>117* <li>Gap, with zero valid offsets. This is when clocks jump forward typically118* due to the spring daylight savings change from "winter" to "summer".119* In a gap there are local date-time values with no valid offset.</li>120* <li>Overlap, with two valid offsets. This is when clocks are set back typically121* due to the autumn daylight savings change from "summer" to "winter".122* In an overlap there are local date-time values with two valid offsets.</li>123* </ul>124* <p>125* Any method that converts directly or implicitly from a local date-time to an126* instant by obtaining the offset has the potential to be complicated.127* <p>128* For Gaps, the general strategy is that if the local date-time falls in the129* middle of a Gap, then the resulting zoned date-time will have a local date-time130* shifted forwards by the length of the Gap, resulting in a date-time in the later131* offset, typically "summer" time.132* <p>133* For Overlaps, the general strategy is that if the local date-time falls in the134* middle of an Overlap, then the previous offset will be retained. If there is no135* previous offset, or the previous offset is invalid, then the earlier offset is136* used, typically "summer" time.. Two additional methods,137* {@link #withEarlierOffsetAtOverlap()} and {@link #withLaterOffsetAtOverlap()},138* help manage the case of an overlap.139* <p>140* In terms of design, this class should be viewed primarily as the combination141* of a {@code LocalDateTime} and a {@code ZoneId}. The {@code ZoneOffset} is142* a vital, but secondary, piece of information, used to ensure that the class143* represents an instant, especially during a daylight savings overlap.144*145* <p>146* This is a <a href="{@docRoot}/java/lang/doc-files/ValueBased.html">value-based</a>147* class; use of identity-sensitive operations (including reference equality148* ({@code ==}), identity hash code, or synchronization) on instances of149* {@code ZonedDateTime} may have unpredictable results and should be avoided.150* The {@code equals} method should be used for comparisons.151*152* @implSpec153* A {@code ZonedDateTime} holds state equivalent to three separate objects,154* a {@code LocalDateTime}, a {@code ZoneId} and the resolved {@code ZoneOffset}.155* The offset and local date-time are used to define an instant when necessary.156* The zone ID is used to obtain the rules for how and when the offset changes.157* The offset cannot be freely set, as the zone controls which offsets are valid.158* <p>159* This class is immutable and thread-safe.160*161* @since 1.8162*/163public final class ZonedDateTime164implements Temporal, ChronoZonedDateTime<LocalDate>, Serializable {165166/**167* Serialization version.168*/169private static final long serialVersionUID = -6260982410461394882L;170171/**172* The local date-time.173*/174private final LocalDateTime dateTime;175/**176* The offset from UTC/Greenwich.177*/178private final ZoneOffset offset;179/**180* The time-zone.181*/182private final ZoneId zone;183184//-----------------------------------------------------------------------185/**186* Obtains the current date-time from the system clock in the default time-zone.187* <p>188* This will query the {@link Clock#systemDefaultZone() system clock} in the default189* time-zone to obtain the current date-time.190* The zone and offset will be set based on the time-zone in the clock.191* <p>192* Using this method will prevent the ability to use an alternate clock for testing193* because the clock is hard-coded.194*195* @return the current date-time using the system clock, not null196*/197public static ZonedDateTime now() {198return now(Clock.systemDefaultZone());199}200201/**202* Obtains the current date-time from the system clock in the specified time-zone.203* <p>204* This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date-time.205* Specifying the time-zone avoids dependence on the default time-zone.206* The offset will be calculated from the specified time-zone.207* <p>208* Using this method will prevent the ability to use an alternate clock for testing209* because the clock is hard-coded.210*211* @param zone the zone ID to use, not null212* @return the current date-time using the system clock, not null213*/214public static ZonedDateTime now(ZoneId zone) {215return now(Clock.system(zone));216}217218/**219* Obtains the current date-time from the specified clock.220* <p>221* This will query the specified clock to obtain the current date-time.222* The zone and offset will be set based on the time-zone in the clock.223* <p>224* Using this method allows the use of an alternate clock for testing.225* The alternate clock may be introduced using {@link Clock dependency injection}.226*227* @param clock the clock to use, not null228* @return the current date-time, not null229*/230public static ZonedDateTime now(Clock clock) {231Objects.requireNonNull(clock, "clock");232final Instant now = clock.instant(); // called once233return ofInstant(now, clock.getZone());234}235236//-----------------------------------------------------------------------237/**238* Obtains an instance of {@code ZonedDateTime} from a local date and time.239* <p>240* This creates a zoned date-time matching the input local date and time as closely as possible.241* Time-zone rules, such as daylight savings, mean that not every local date-time242* is valid for the specified zone, thus the local date-time may be adjusted.243* <p>244* The local date time and first combined to form a local date-time.245* The local date-time is then resolved to a single instant on the time-line.246* This is achieved by finding a valid offset from UTC/Greenwich for the local247* date-time as defined by the {@link ZoneRules rules} of the zone ID.248*<p>249* In most cases, there is only one valid offset for a local date-time.250* In the case of an overlap, when clocks are set back, there are two valid offsets.251* This method uses the earlier offset typically corresponding to "summer".252* <p>253* In the case of a gap, when clocks jump forward, there is no valid offset.254* Instead, the local date-time is adjusted to be later by the length of the gap.255* For a typical one hour daylight savings change, the local date-time will be256* moved one hour later into the offset typically corresponding to "summer".257*258* @param date the local date, not null259* @param time the local time, not null260* @param zone the time-zone, not null261* @return the offset date-time, not null262*/263public static ZonedDateTime of(LocalDate date, LocalTime time, ZoneId zone) {264return of(LocalDateTime.of(date, time), zone);265}266267/**268* Obtains an instance of {@code ZonedDateTime} from a local date-time.269* <p>270* This creates a zoned date-time matching the input local date-time as closely as possible.271* Time-zone rules, such as daylight savings, mean that not every local date-time272* is valid for the specified zone, thus the local date-time may be adjusted.273* <p>274* The local date-time is resolved to a single instant on the time-line.275* This is achieved by finding a valid offset from UTC/Greenwich for the local276* date-time as defined by the {@link ZoneRules rules} of the zone ID.277*<p>278* In most cases, there is only one valid offset for a local date-time.279* In the case of an overlap, when clocks are set back, there are two valid offsets.280* This method uses the earlier offset typically corresponding to "summer".281* <p>282* In the case of a gap, when clocks jump forward, there is no valid offset.283* Instead, the local date-time is adjusted to be later by the length of the gap.284* For a typical one hour daylight savings change, the local date-time will be285* moved one hour later into the offset typically corresponding to "summer".286*287* @param localDateTime the local date-time, not null288* @param zone the time-zone, not null289* @return the zoned date-time, not null290*/291public static ZonedDateTime of(LocalDateTime localDateTime, ZoneId zone) {292return ofLocal(localDateTime, zone, null);293}294295/**296* Obtains an instance of {@code ZonedDateTime} from a year, month, day,297* hour, minute, second, nanosecond and time-zone.298* <p>299* This creates a zoned date-time matching the local date-time of the seven300* specified fields as closely as possible.301* Time-zone rules, such as daylight savings, mean that not every local date-time302* is valid for the specified zone, thus the local date-time may be adjusted.303* <p>304* The local date-time is resolved to a single instant on the time-line.305* This is achieved by finding a valid offset from UTC/Greenwich for the local306* date-time as defined by the {@link ZoneRules rules} of the zone ID.307*<p>308* In most cases, there is only one valid offset for a local date-time.309* In the case of an overlap, when clocks are set back, there are two valid offsets.310* This method uses the earlier offset typically corresponding to "summer".311* <p>312* In the case of a gap, when clocks jump forward, there is no valid offset.313* Instead, the local date-time is adjusted to be later by the length of the gap.314* For a typical one hour daylight savings change, the local date-time will be315* moved one hour later into the offset typically corresponding to "summer".316* <p>317* This method exists primarily for writing test cases.318* Non test-code will typically use other methods to create an offset time.319* {@code LocalDateTime} has five additional convenience variants of the320* equivalent factory method taking fewer arguments.321* They are not provided here to reduce the footprint of the API.322*323* @param year the year to represent, from MIN_YEAR to MAX_YEAR324* @param month the month-of-year to represent, from 1 (January) to 12 (December)325* @param dayOfMonth the day-of-month to represent, from 1 to 31326* @param hour the hour-of-day to represent, from 0 to 23327* @param minute the minute-of-hour to represent, from 0 to 59328* @param second the second-of-minute to represent, from 0 to 59329* @param nanoOfSecond the nano-of-second to represent, from 0 to 999,999,999330* @param zone the time-zone, not null331* @return the offset date-time, not null332* @throws DateTimeException if the value of any field is out of range, or333* if the day-of-month is invalid for the month-year334*/335public static ZonedDateTime of(336int year, int month, int dayOfMonth,337int hour, int minute, int second, int nanoOfSecond, ZoneId zone) {338LocalDateTime dt = LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nanoOfSecond);339return ofLocal(dt, zone, null);340}341342/**343* Obtains an instance of {@code ZonedDateTime} from a local date-time344* using the preferred offset if possible.345* <p>346* The local date-time is resolved to a single instant on the time-line.347* This is achieved by finding a valid offset from UTC/Greenwich for the local348* date-time as defined by the {@link ZoneRules rules} of the zone ID.349*<p>350* In most cases, there is only one valid offset for a local date-time.351* In the case of an overlap, where clocks are set back, there are two valid offsets.352* If the preferred offset is one of the valid offsets then it is used.353* Otherwise the earlier valid offset is used, typically corresponding to "summer".354* <p>355* In the case of a gap, where clocks jump forward, there is no valid offset.356* Instead, the local date-time is adjusted to be later by the length of the gap.357* For a typical one hour daylight savings change, the local date-time will be358* moved one hour later into the offset typically corresponding to "summer".359*360* @param localDateTime the local date-time, not null361* @param zone the time-zone, not null362* @param preferredOffset the zone offset, null if no preference363* @return the zoned date-time, not null364*/365public static ZonedDateTime ofLocal(LocalDateTime localDateTime, ZoneId zone, ZoneOffset preferredOffset) {366Objects.requireNonNull(localDateTime, "localDateTime");367Objects.requireNonNull(zone, "zone");368if (zone instanceof ZoneOffset) {369return new ZonedDateTime(localDateTime, (ZoneOffset) zone, zone);370}371ZoneRules rules = zone.getRules();372List<ZoneOffset> validOffsets = rules.getValidOffsets(localDateTime);373ZoneOffset offset;374if (validOffsets.size() == 1) {375offset = validOffsets.get(0);376} else if (validOffsets.size() == 0) {377ZoneOffsetTransition trans = rules.getTransition(localDateTime);378localDateTime = localDateTime.plusSeconds(trans.getDuration().getSeconds());379offset = trans.getOffsetAfter();380} else {381if (preferredOffset != null && validOffsets.contains(preferredOffset)) {382offset = preferredOffset;383} else {384offset = Objects.requireNonNull(validOffsets.get(0), "offset"); // protect against bad ZoneRules385}386}387return new ZonedDateTime(localDateTime, offset, zone);388}389390//-----------------------------------------------------------------------391/**392* Obtains an instance of {@code ZonedDateTime} from an {@code Instant}.393* <p>394* This creates a zoned date-time with the same instant as that specified.395* Calling {@link #toInstant()} will return an instant equal to the one used here.396* <p>397* Converting an instant to a zoned date-time is simple as there is only one valid398* offset for each instant.399*400* @param instant the instant to create the date-time from, not null401* @param zone the time-zone, not null402* @return the zoned date-time, not null403* @throws DateTimeException if the result exceeds the supported range404*/405public static ZonedDateTime ofInstant(Instant instant, ZoneId zone) {406Objects.requireNonNull(instant, "instant");407Objects.requireNonNull(zone, "zone");408return create(instant.getEpochSecond(), instant.getNano(), zone);409}410411/**412* Obtains an instance of {@code ZonedDateTime} from the instant formed by combining413* the local date-time and offset.414* <p>415* This creates a zoned date-time by {@link LocalDateTime#toInstant(ZoneOffset) combining}416* the {@code LocalDateTime} and {@code ZoneOffset}.417* This combination uniquely specifies an instant without ambiguity.418* <p>419* Converting an instant to a zoned date-time is simple as there is only one valid420* offset for each instant. If the valid offset is different to the offset specified,421* then the date-time and offset of the zoned date-time will differ from those specified.422* <p>423* If the {@code ZoneId} to be used is a {@code ZoneOffset}, this method is equivalent424* to {@link #of(LocalDateTime, ZoneId)}.425*426* @param localDateTime the local date-time, not null427* @param offset the zone offset, not null428* @param zone the time-zone, not null429* @return the zoned date-time, not null430*/431public static ZonedDateTime ofInstant(LocalDateTime localDateTime, ZoneOffset offset, ZoneId zone) {432Objects.requireNonNull(localDateTime, "localDateTime");433Objects.requireNonNull(offset, "offset");434Objects.requireNonNull(zone, "zone");435if (zone.getRules().isValidOffset(localDateTime, offset)) {436return new ZonedDateTime(localDateTime, offset, zone);437}438return create(localDateTime.toEpochSecond(offset), localDateTime.getNano(), zone);439}440441/**442* Obtains an instance of {@code ZonedDateTime} using seconds from the443* epoch of 1970-01-01T00:00:00Z.444*445* @param epochSecond the number of seconds from the epoch of 1970-01-01T00:00:00Z446* @param nanoOfSecond the nanosecond within the second, from 0 to 999,999,999447* @param zone the time-zone, not null448* @return the zoned date-time, not null449* @throws DateTimeException if the result exceeds the supported range450*/451private static ZonedDateTime create(long epochSecond, int nanoOfSecond, ZoneId zone) {452ZoneRules rules = zone.getRules();453Instant instant = Instant.ofEpochSecond(epochSecond, nanoOfSecond); // TODO: rules should be queryable by epochSeconds454ZoneOffset offset = rules.getOffset(instant);455LocalDateTime ldt = LocalDateTime.ofEpochSecond(epochSecond, nanoOfSecond, offset);456return new ZonedDateTime(ldt, offset, zone);457}458459//-----------------------------------------------------------------------460/**461* Obtains an instance of {@code ZonedDateTime} strictly validating the462* combination of local date-time, offset and zone ID.463* <p>464* This creates a zoned date-time ensuring that the offset is valid for the465* local date-time according to the rules of the specified zone.466* If the offset is invalid, an exception is thrown.467*468* @param localDateTime the local date-time, not null469* @param offset the zone offset, not null470* @param zone the time-zone, not null471* @return the zoned date-time, not null472*/473public static ZonedDateTime ofStrict(LocalDateTime localDateTime, ZoneOffset offset, ZoneId zone) {474Objects.requireNonNull(localDateTime, "localDateTime");475Objects.requireNonNull(offset, "offset");476Objects.requireNonNull(zone, "zone");477ZoneRules rules = zone.getRules();478if (rules.isValidOffset(localDateTime, offset) == false) {479ZoneOffsetTransition trans = rules.getTransition(localDateTime);480if (trans != null && trans.isGap()) {481// error message says daylight savings for simplicity482// even though there are other kinds of gaps483throw new DateTimeException("LocalDateTime '" + localDateTime +484"' does not exist in zone '" + zone +485"' due to a gap in the local time-line, typically caused by daylight savings");486}487throw new DateTimeException("ZoneOffset '" + offset + "' is not valid for LocalDateTime '" +488localDateTime + "' in zone '" + zone + "'");489}490return new ZonedDateTime(localDateTime, offset, zone);491}492493/**494* Obtains an instance of {@code ZonedDateTime} leniently, for advanced use cases,495* allowing any combination of local date-time, offset and zone ID.496* <p>497* This creates a zoned date-time with no checks other than no nulls.498* This means that the resulting zoned date-time may have an offset that is in conflict499* with the zone ID.500* <p>501* This method is intended for advanced use cases.502* For example, consider the case where a zoned date-time with valid fields is created503* and then stored in a database or serialization-based store. At some later point,504* the object is then re-loaded. However, between those points in time, the government505* that defined the time-zone has changed the rules, such that the originally stored506* local date-time now does not occur. This method can be used to create the object507* in an "invalid" state, despite the change in rules.508*509* @param localDateTime the local date-time, not null510* @param offset the zone offset, not null511* @param zone the time-zone, not null512* @return the zoned date-time, not null513*/514private static ZonedDateTime ofLenient(LocalDateTime localDateTime, ZoneOffset offset, ZoneId zone) {515Objects.requireNonNull(localDateTime, "localDateTime");516Objects.requireNonNull(offset, "offset");517Objects.requireNonNull(zone, "zone");518if (zone instanceof ZoneOffset && offset.equals(zone) == false) {519throw new IllegalArgumentException("ZoneId must match ZoneOffset");520}521return new ZonedDateTime(localDateTime, offset, zone);522}523524//-----------------------------------------------------------------------525/**526* Obtains an instance of {@code ZonedDateTime} from a temporal object.527* <p>528* This obtains a zoned date-time based on the specified temporal.529* A {@code TemporalAccessor} represents an arbitrary set of date and time information,530* which this factory converts to an instance of {@code ZonedDateTime}.531* <p>532* The conversion will first obtain a {@code ZoneId} from the temporal object,533* falling back to a {@code ZoneOffset} if necessary. It will then try to obtain534* an {@code Instant}, falling back to a {@code LocalDateTime} if necessary.535* The result will be either the combination of {@code ZoneId} or {@code ZoneOffset}536* with {@code Instant} or {@code LocalDateTime}.537* Implementations are permitted to perform optimizations such as accessing538* those fields that are equivalent to the relevant objects.539* <p>540* This method matches the signature of the functional interface {@link TemporalQuery}541* allowing it to be used as a query via method reference, {@code ZonedDateTime::from}.542*543* @param temporal the temporal object to convert, not null544* @return the zoned date-time, not null545* @throws DateTimeException if unable to convert to an {@code ZonedDateTime}546*/547public static ZonedDateTime from(TemporalAccessor temporal) {548if (temporal instanceof ZonedDateTime) {549return (ZonedDateTime) temporal;550}551try {552ZoneId zone = ZoneId.from(temporal);553if (temporal.isSupported(INSTANT_SECONDS)) {554long epochSecond = temporal.getLong(INSTANT_SECONDS);555int nanoOfSecond = temporal.get(NANO_OF_SECOND);556return create(epochSecond, nanoOfSecond, zone);557} else {558LocalDate date = LocalDate.from(temporal);559LocalTime time = LocalTime.from(temporal);560return of(date, time, zone);561}562} catch (DateTimeException ex) {563throw new DateTimeException("Unable to obtain ZonedDateTime from TemporalAccessor: " +564temporal + " of type " + temporal.getClass().getName(), ex);565}566}567568//-----------------------------------------------------------------------569/**570* Obtains an instance of {@code ZonedDateTime} from a text string such as571* {@code 2007-12-03T10:15:30+01:00[Europe/Paris]}.572* <p>573* The string must represent a valid date-time and is parsed using574* {@link java.time.format.DateTimeFormatter#ISO_ZONED_DATE_TIME}.575*576* @param text the text to parse such as "2007-12-03T10:15:30+01:00[Europe/Paris]", not null577* @return the parsed zoned date-time, not null578* @throws DateTimeParseException if the text cannot be parsed579*/580public static ZonedDateTime parse(CharSequence text) {581return parse(text, DateTimeFormatter.ISO_ZONED_DATE_TIME);582}583584/**585* Obtains an instance of {@code ZonedDateTime} from a text string using a specific formatter.586* <p>587* The text is parsed using the formatter, returning a date-time.588*589* @param text the text to parse, not null590* @param formatter the formatter to use, not null591* @return the parsed zoned date-time, not null592* @throws DateTimeParseException if the text cannot be parsed593*/594public static ZonedDateTime parse(CharSequence text, DateTimeFormatter formatter) {595Objects.requireNonNull(formatter, "formatter");596return formatter.parse(text, ZonedDateTime::from);597}598599//-----------------------------------------------------------------------600/**601* Constructor.602*603* @param dateTime the date-time, validated as not null604* @param offset the zone offset, validated as not null605* @param zone the time-zone, validated as not null606*/607private ZonedDateTime(LocalDateTime dateTime, ZoneOffset offset, ZoneId zone) {608this.dateTime = dateTime;609this.offset = offset;610this.zone = zone;611}612613/**614* Resolves the new local date-time using this zone ID, retaining the offset if possible.615*616* @param newDateTime the new local date-time, not null617* @return the zoned date-time, not null618*/619private ZonedDateTime resolveLocal(LocalDateTime newDateTime) {620return ofLocal(newDateTime, zone, offset);621}622623/**624* Resolves the new local date-time using the offset to identify the instant.625*626* @param newDateTime the new local date-time, not null627* @return the zoned date-time, not null628*/629private ZonedDateTime resolveInstant(LocalDateTime newDateTime) {630return ofInstant(newDateTime, offset, zone);631}632633/**634* Resolves the offset into this zoned date-time for the with methods.635* <p>636* This typically ignores the offset, unless it can be used to switch offset in a DST overlap.637*638* @param offset the offset, not null639* @return the zoned date-time, not null640*/641private ZonedDateTime resolveOffset(ZoneOffset offset) {642if (offset.equals(this.offset) == false && zone.getRules().isValidOffset(dateTime, offset)) {643return new ZonedDateTime(dateTime, offset, zone);644}645return this;646}647648//-----------------------------------------------------------------------649/**650* Checks if the specified field is supported.651* <p>652* This checks if this date-time can be queried for the specified field.653* If false, then calling the {@link #range(TemporalField) range},654* {@link #get(TemporalField) get} and {@link #with(TemporalField, long)}655* methods will throw an exception.656* <p>657* If the field is a {@link ChronoField} then the query is implemented here.658* The supported fields are:659* <ul>660* <li>{@code NANO_OF_SECOND}661* <li>{@code NANO_OF_DAY}662* <li>{@code MICRO_OF_SECOND}663* <li>{@code MICRO_OF_DAY}664* <li>{@code MILLI_OF_SECOND}665* <li>{@code MILLI_OF_DAY}666* <li>{@code SECOND_OF_MINUTE}667* <li>{@code SECOND_OF_DAY}668* <li>{@code MINUTE_OF_HOUR}669* <li>{@code MINUTE_OF_DAY}670* <li>{@code HOUR_OF_AMPM}671* <li>{@code CLOCK_HOUR_OF_AMPM}672* <li>{@code HOUR_OF_DAY}673* <li>{@code CLOCK_HOUR_OF_DAY}674* <li>{@code AMPM_OF_DAY}675* <li>{@code DAY_OF_WEEK}676* <li>{@code ALIGNED_DAY_OF_WEEK_IN_MONTH}677* <li>{@code ALIGNED_DAY_OF_WEEK_IN_YEAR}678* <li>{@code DAY_OF_MONTH}679* <li>{@code DAY_OF_YEAR}680* <li>{@code EPOCH_DAY}681* <li>{@code ALIGNED_WEEK_OF_MONTH}682* <li>{@code ALIGNED_WEEK_OF_YEAR}683* <li>{@code MONTH_OF_YEAR}684* <li>{@code PROLEPTIC_MONTH}685* <li>{@code YEAR_OF_ERA}686* <li>{@code YEAR}687* <li>{@code ERA}688* <li>{@code INSTANT_SECONDS}689* <li>{@code OFFSET_SECONDS}690* </ul>691* All other {@code ChronoField} instances will return false.692* <p>693* If the field is not a {@code ChronoField}, then the result of this method694* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}695* passing {@code this} as the argument.696* Whether the field is supported is determined by the field.697*698* @param field the field to check, null returns false699* @return true if the field is supported on this date-time, false if not700*/701@Override702public boolean isSupported(TemporalField field) {703return field instanceof ChronoField || (field != null && field.isSupportedBy(this));704}705706/**707* Checks if the specified unit is supported.708* <p>709* This checks if the specified unit can be added to, or subtracted from, this date-time.710* If false, then calling the {@link #plus(long, TemporalUnit)} and711* {@link #minus(long, TemporalUnit) minus} methods will throw an exception.712* <p>713* If the unit is a {@link ChronoUnit} then the query is implemented here.714* The supported units are:715* <ul>716* <li>{@code NANOS}717* <li>{@code MICROS}718* <li>{@code MILLIS}719* <li>{@code SECONDS}720* <li>{@code MINUTES}721* <li>{@code HOURS}722* <li>{@code HALF_DAYS}723* <li>{@code DAYS}724* <li>{@code WEEKS}725* <li>{@code MONTHS}726* <li>{@code YEARS}727* <li>{@code DECADES}728* <li>{@code CENTURIES}729* <li>{@code MILLENNIA}730* <li>{@code ERAS}731* </ul>732* All other {@code ChronoUnit} instances will return false.733* <p>734* If the unit is not a {@code ChronoUnit}, then the result of this method735* is obtained by invoking {@code TemporalUnit.isSupportedBy(Temporal)}736* passing {@code this} as the argument.737* Whether the unit is supported is determined by the unit.738*739* @param unit the unit to check, null returns false740* @return true if the unit can be added/subtracted, false if not741*/742@Override // override for Javadoc743public boolean isSupported(TemporalUnit unit) {744return ChronoZonedDateTime.super.isSupported(unit);745}746747//-----------------------------------------------------------------------748/**749* Gets the range of valid values for the specified field.750* <p>751* The range object expresses the minimum and maximum valid values for a field.752* This date-time is used to enhance the accuracy of the returned range.753* If it is not possible to return the range, because the field is not supported754* or for some other reason, an exception is thrown.755* <p>756* If the field is a {@link ChronoField} then the query is implemented here.757* The {@link #isSupported(TemporalField) supported fields} will return758* appropriate range instances.759* All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.760* <p>761* If the field is not a {@code ChronoField}, then the result of this method762* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}763* passing {@code this} as the argument.764* Whether the range can be obtained is determined by the field.765*766* @param field the field to query the range for, not null767* @return the range of valid values for the field, not null768* @throws DateTimeException if the range for the field cannot be obtained769* @throws UnsupportedTemporalTypeException if the field is not supported770*/771@Override772public ValueRange range(TemporalField field) {773if (field instanceof ChronoField) {774if (field == INSTANT_SECONDS || field == OFFSET_SECONDS) {775return field.range();776}777return dateTime.range(field);778}779return field.rangeRefinedBy(this);780}781782/**783* Gets the value of the specified field from this date-time as an {@code int}.784* <p>785* This queries this date-time for the value of the specified field.786* The returned value will always be within the valid range of values for the field.787* If it is not possible to return the value, because the field is not supported788* or for some other reason, an exception is thrown.789* <p>790* If the field is a {@link ChronoField} then the query is implemented here.791* The {@link #isSupported(TemporalField) supported fields} will return valid792* values based on this date-time, except {@code NANO_OF_DAY}, {@code MICRO_OF_DAY},793* {@code EPOCH_DAY}, {@code PROLEPTIC_MONTH} and {@code INSTANT_SECONDS} which are too794* large to fit in an {@code int} and throw a {@code DateTimeException}.795* All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.796* <p>797* If the field is not a {@code ChronoField}, then the result of this method798* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}799* passing {@code this} as the argument. Whether the value can be obtained,800* and what the value represents, is determined by the field.801*802* @param field the field to get, not null803* @return the value for the field804* @throws DateTimeException if a value for the field cannot be obtained or805* the value is outside the range of valid values for the field806* @throws UnsupportedTemporalTypeException if the field is not supported or807* the range of values exceeds an {@code int}808* @throws ArithmeticException if numeric overflow occurs809*/810@Override // override for Javadoc and performance811public int get(TemporalField field) {812if (field instanceof ChronoField) {813switch ((ChronoField) field) {814case INSTANT_SECONDS:815throw new UnsupportedTemporalTypeException("Invalid field 'InstantSeconds' for get() method, use getLong() instead");816case OFFSET_SECONDS:817return getOffset().getTotalSeconds();818}819return dateTime.get(field);820}821return ChronoZonedDateTime.super.get(field);822}823824/**825* Gets the value of the specified field from this date-time as a {@code long}.826* <p>827* This queries this date-time for the value of the specified field.828* If it is not possible to return the value, because the field is not supported829* or for some other reason, an exception is thrown.830* <p>831* If the field is a {@link ChronoField} then the query is implemented here.832* The {@link #isSupported(TemporalField) supported fields} will return valid833* values based on this date-time.834* All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.835* <p>836* If the field is not a {@code ChronoField}, then the result of this method837* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}838* passing {@code this} as the argument. Whether the value can be obtained,839* and what the value represents, is determined by the field.840*841* @param field the field to get, not null842* @return the value for the field843* @throws DateTimeException if a value for the field cannot be obtained844* @throws UnsupportedTemporalTypeException if the field is not supported845* @throws ArithmeticException if numeric overflow occurs846*/847@Override848public long getLong(TemporalField field) {849if (field instanceof ChronoField) {850switch ((ChronoField) field) {851case INSTANT_SECONDS: return toEpochSecond();852case OFFSET_SECONDS: return getOffset().getTotalSeconds();853}854return dateTime.getLong(field);855}856return field.getFrom(this);857}858859//-----------------------------------------------------------------------860/**861* Gets the zone offset, such as '+01:00'.862* <p>863* This is the offset of the local date-time from UTC/Greenwich.864*865* @return the zone offset, not null866*/867@Override868public ZoneOffset getOffset() {869return offset;870}871872/**873* Returns a copy of this date-time changing the zone offset to the874* earlier of the two valid offsets at a local time-line overlap.875* <p>876* This method only has any effect when the local time-line overlaps, such as877* at an autumn daylight savings cutover. In this scenario, there are two878* valid offsets for the local date-time. Calling this method will return879* a zoned date-time with the earlier of the two selected.880* <p>881* If this method is called when it is not an overlap, {@code this}882* is returned.883* <p>884* This instance is immutable and unaffected by this method call.885*886* @return a {@code ZonedDateTime} based on this date-time with the earlier offset, not null887*/888@Override889public ZonedDateTime withEarlierOffsetAtOverlap() {890ZoneOffsetTransition trans = getZone().getRules().getTransition(dateTime);891if (trans != null && trans.isOverlap()) {892ZoneOffset earlierOffset = trans.getOffsetBefore();893if (earlierOffset.equals(offset) == false) {894return new ZonedDateTime(dateTime, earlierOffset, zone);895}896}897return this;898}899900/**901* Returns a copy of this date-time changing the zone offset to the902* later of the two valid offsets at a local time-line overlap.903* <p>904* This method only has any effect when the local time-line overlaps, such as905* at an autumn daylight savings cutover. In this scenario, there are two906* valid offsets for the local date-time. Calling this method will return907* a zoned date-time with the later of the two selected.908* <p>909* If this method is called when it is not an overlap, {@code this}910* is returned.911* <p>912* This instance is immutable and unaffected by this method call.913*914* @return a {@code ZonedDateTime} based on this date-time with the later offset, not null915*/916@Override917public ZonedDateTime withLaterOffsetAtOverlap() {918ZoneOffsetTransition trans = getZone().getRules().getTransition(toLocalDateTime());919if (trans != null) {920ZoneOffset laterOffset = trans.getOffsetAfter();921if (laterOffset.equals(offset) == false) {922return new ZonedDateTime(dateTime, laterOffset, zone);923}924}925return this;926}927928//-----------------------------------------------------------------------929/**930* Gets the time-zone, such as 'Europe/Paris'.931* <p>932* This returns the zone ID. This identifies the time-zone {@link ZoneRules rules}933* that determine when and how the offset from UTC/Greenwich changes.934* <p>935* The zone ID may be same as the {@linkplain #getOffset() offset}.936* If this is true, then any future calculations, such as addition or subtraction,937* have no complex edge cases due to time-zone rules.938* See also {@link #withFixedOffsetZone()}.939*940* @return the time-zone, not null941*/942@Override943public ZoneId getZone() {944return zone;945}946947/**948* Returns a copy of this date-time with a different time-zone,949* retaining the local date-time if possible.950* <p>951* This method changes the time-zone and retains the local date-time.952* The local date-time is only changed if it is invalid for the new zone,953* determined using the same approach as954* {@link #ofLocal(LocalDateTime, ZoneId, ZoneOffset)}.955* <p>956* To change the zone and adjust the local date-time,957* use {@link #withZoneSameInstant(ZoneId)}.958* <p>959* This instance is immutable and unaffected by this method call.960*961* @param zone the time-zone to change to, not null962* @return a {@code ZonedDateTime} based on this date-time with the requested zone, not null963*/964@Override965public ZonedDateTime withZoneSameLocal(ZoneId zone) {966Objects.requireNonNull(zone, "zone");967return this.zone.equals(zone) ? this : ofLocal(dateTime, zone, offset);968}969970/**971* Returns a copy of this date-time with a different time-zone,972* retaining the instant.973* <p>974* This method changes the time-zone and retains the instant.975* This normally results in a change to the local date-time.976* <p>977* This method is based on retaining the same instant, thus gaps and overlaps978* in the local time-line have no effect on the result.979* <p>980* To change the offset while keeping the local time,981* use {@link #withZoneSameLocal(ZoneId)}.982*983* @param zone the time-zone to change to, not null984* @return a {@code ZonedDateTime} based on this date-time with the requested zone, not null985* @throws DateTimeException if the result exceeds the supported date range986*/987@Override988public ZonedDateTime withZoneSameInstant(ZoneId zone) {989Objects.requireNonNull(zone, "zone");990return this.zone.equals(zone) ? this :991create(dateTime.toEpochSecond(offset), dateTime.getNano(), zone);992}993994/**995* Returns a copy of this date-time with the zone ID set to the offset.996* <p>997* This returns a zoned date-time where the zone ID is the same as {@link #getOffset()}.998* The local date-time, offset and instant of the result will be the same as in this date-time.999* <p>1000* Setting the date-time to a fixed single offset means that any future1001* calculations, such as addition or subtraction, have no complex edge cases1002* due to time-zone rules.1003* This might also be useful when sending a zoned date-time across a network,1004* as most protocols, such as ISO-8601, only handle offsets,1005* and not region-based zone IDs.1006* <p>1007* This is equivalent to {@code ZonedDateTime.of(zdt.toLocalDateTime(), zdt.getOffset())}.1008*1009* @return a {@code ZonedDateTime} with the zone ID set to the offset, not null1010*/1011public ZonedDateTime withFixedOffsetZone() {1012return this.zone.equals(offset) ? this : new ZonedDateTime(dateTime, offset, offset);1013}10141015//-----------------------------------------------------------------------1016/**1017* Gets the {@code LocalDateTime} part of this date-time.1018* <p>1019* This returns a {@code LocalDateTime} with the same year, month, day and time1020* as this date-time.1021*1022* @return the local date-time part of this date-time, not null1023*/1024@Override // override for return type1025public LocalDateTime toLocalDateTime() {1026return dateTime;1027}10281029//-----------------------------------------------------------------------1030/**1031* Gets the {@code LocalDate} part of this date-time.1032* <p>1033* This returns a {@code LocalDate} with the same year, month and day1034* as this date-time.1035*1036* @return the date part of this date-time, not null1037*/1038@Override // override for return type1039public LocalDate toLocalDate() {1040return dateTime.toLocalDate();1041}10421043/**1044* Gets the year field.1045* <p>1046* This method returns the primitive {@code int} value for the year.1047* <p>1048* The year returned by this method is proleptic as per {@code get(YEAR)}.1049* To obtain the year-of-era, use {@code get(YEAR_OF_ERA)}.1050*1051* @return the year, from MIN_YEAR to MAX_YEAR1052*/1053public int getYear() {1054return dateTime.getYear();1055}10561057/**1058* Gets the month-of-year field from 1 to 12.1059* <p>1060* This method returns the month as an {@code int} from 1 to 12.1061* Application code is frequently clearer if the enum {@link Month}1062* is used by calling {@link #getMonth()}.1063*1064* @return the month-of-year, from 1 to 121065* @see #getMonth()1066*/1067public int getMonthValue() {1068return dateTime.getMonthValue();1069}10701071/**1072* Gets the month-of-year field using the {@code Month} enum.1073* <p>1074* This method returns the enum {@link Month} for the month.1075* This avoids confusion as to what {@code int} values mean.1076* If you need access to the primitive {@code int} value then the enum1077* provides the {@link Month#getValue() int value}.1078*1079* @return the month-of-year, not null1080* @see #getMonthValue()1081*/1082public Month getMonth() {1083return dateTime.getMonth();1084}10851086/**1087* Gets the day-of-month field.1088* <p>1089* This method returns the primitive {@code int} value for the day-of-month.1090*1091* @return the day-of-month, from 1 to 311092*/1093public int getDayOfMonth() {1094return dateTime.getDayOfMonth();1095}10961097/**1098* Gets the day-of-year field.1099* <p>1100* This method returns the primitive {@code int} value for the day-of-year.1101*1102* @return the day-of-year, from 1 to 365, or 366 in a leap year1103*/1104public int getDayOfYear() {1105return dateTime.getDayOfYear();1106}11071108/**1109* Gets the day-of-week field, which is an enum {@code DayOfWeek}.1110* <p>1111* This method returns the enum {@link DayOfWeek} for the day-of-week.1112* This avoids confusion as to what {@code int} values mean.1113* If you need access to the primitive {@code int} value then the enum1114* provides the {@link DayOfWeek#getValue() int value}.1115* <p>1116* Additional information can be obtained from the {@code DayOfWeek}.1117* This includes textual names of the values.1118*1119* @return the day-of-week, not null1120*/1121public DayOfWeek getDayOfWeek() {1122return dateTime.getDayOfWeek();1123}11241125//-----------------------------------------------------------------------1126/**1127* Gets the {@code LocalTime} part of this date-time.1128* <p>1129* This returns a {@code LocalTime} with the same hour, minute, second and1130* nanosecond as this date-time.1131*1132* @return the time part of this date-time, not null1133*/1134@Override // override for Javadoc and performance1135public LocalTime toLocalTime() {1136return dateTime.toLocalTime();1137}11381139/**1140* Gets the hour-of-day field.1141*1142* @return the hour-of-day, from 0 to 231143*/1144public int getHour() {1145return dateTime.getHour();1146}11471148/**1149* Gets the minute-of-hour field.1150*1151* @return the minute-of-hour, from 0 to 591152*/1153public int getMinute() {1154return dateTime.getMinute();1155}11561157/**1158* Gets the second-of-minute field.1159*1160* @return the second-of-minute, from 0 to 591161*/1162public int getSecond() {1163return dateTime.getSecond();1164}11651166/**1167* Gets the nano-of-second field.1168*1169* @return the nano-of-second, from 0 to 999,999,9991170*/1171public int getNano() {1172return dateTime.getNano();1173}11741175//-----------------------------------------------------------------------1176/**1177* Returns an adjusted copy of this date-time.1178* <p>1179* This returns a {@code ZonedDateTime}, based on this one, with the date-time adjusted.1180* The adjustment takes place using the specified adjuster strategy object.1181* Read the documentation of the adjuster to understand what adjustment will be made.1182* <p>1183* A simple adjuster might simply set the one of the fields, such as the year field.1184* A more complex adjuster might set the date to the last day of the month.1185* A selection of common adjustments is provided in1186* {@link java.time.temporal.TemporalAdjusters TemporalAdjusters}.1187* These include finding the "last day of the month" and "next Wednesday".1188* Key date-time classes also implement the {@code TemporalAdjuster} interface,1189* such as {@link Month} and {@link java.time.MonthDay MonthDay}.1190* The adjuster is responsible for handling special cases, such as the varying1191* lengths of month and leap years.1192* <p>1193* For example this code returns a date on the last day of July:1194* <pre>1195* import static java.time.Month.*;1196* import static java.time.temporal.TemporalAdjusters.*;1197*1198* result = zonedDateTime.with(JULY).with(lastDayOfMonth());1199* </pre>1200* <p>1201* The classes {@link LocalDate} and {@link LocalTime} implement {@code TemporalAdjuster},1202* thus this method can be used to change the date, time or offset:1203* <pre>1204* result = zonedDateTime.with(date);1205* result = zonedDateTime.with(time);1206* </pre>1207* <p>1208* {@link ZoneOffset} also implements {@code TemporalAdjuster} however using it1209* as an argument typically has no effect. The offset of a {@code ZonedDateTime} is1210* controlled primarily by the time-zone. As such, changing the offset does not generally1211* make sense, because there is only one valid offset for the local date-time and zone.1212* If the zoned date-time is in a daylight savings overlap, then the offset is used1213* to switch between the two valid offsets. In all other cases, the offset is ignored.1214* <p>1215* The result of this method is obtained by invoking the1216* {@link TemporalAdjuster#adjustInto(Temporal)} method on the1217* specified adjuster passing {@code this} as the argument.1218* <p>1219* This instance is immutable and unaffected by this method call.1220*1221* @param adjuster the adjuster to use, not null1222* @return a {@code ZonedDateTime} based on {@code this} with the adjustment made, not null1223* @throws DateTimeException if the adjustment cannot be made1224* @throws ArithmeticException if numeric overflow occurs1225*/1226@Override1227public ZonedDateTime with(TemporalAdjuster adjuster) {1228// optimizations1229if (adjuster instanceof LocalDate) {1230return resolveLocal(LocalDateTime.of((LocalDate) adjuster, dateTime.toLocalTime()));1231} else if (adjuster instanceof LocalTime) {1232return resolveLocal(LocalDateTime.of(dateTime.toLocalDate(), (LocalTime) adjuster));1233} else if (adjuster instanceof LocalDateTime) {1234return resolveLocal((LocalDateTime) adjuster);1235} else if (adjuster instanceof OffsetDateTime) {1236OffsetDateTime odt = (OffsetDateTime) adjuster;1237return ofLocal(odt.toLocalDateTime(), zone, odt.getOffset());1238} else if (adjuster instanceof Instant) {1239Instant instant = (Instant) adjuster;1240return create(instant.getEpochSecond(), instant.getNano(), zone);1241} else if (adjuster instanceof ZoneOffset) {1242return resolveOffset((ZoneOffset) adjuster);1243}1244return (ZonedDateTime) adjuster.adjustInto(this);1245}12461247/**1248* Returns a copy of this date-time with the specified field set to a new value.1249* <p>1250* This returns a {@code ZonedDateTime}, based on this one, with the value1251* for the specified field changed.1252* This can be used to change any supported field, such as the year, month or day-of-month.1253* If it is not possible to set the value, because the field is not supported or for1254* some other reason, an exception is thrown.1255* <p>1256* In some cases, changing the specified field can cause the resulting date-time to become invalid,1257* such as changing the month from 31st January to February would make the day-of-month invalid.1258* In cases like this, the field is responsible for resolving the date. Typically it will choose1259* the previous valid date, which would be the last valid day of February in this example.1260* <p>1261* If the field is a {@link ChronoField} then the adjustment is implemented here.1262* <p>1263* The {@code INSTANT_SECONDS} field will return a date-time with the specified instant.1264* The zone and nano-of-second are unchanged.1265* The result will have an offset derived from the new instant and original zone.1266* If the new instant value is outside the valid range then a {@code DateTimeException} will be thrown.1267* <p>1268* The {@code OFFSET_SECONDS} field will typically be ignored.1269* The offset of a {@code ZonedDateTime} is controlled primarily by the time-zone.1270* As such, changing the offset does not generally make sense, because there is only1271* one valid offset for the local date-time and zone.1272* If the zoned date-time is in a daylight savings overlap, then the offset is used1273* to switch between the two valid offsets. In all other cases, the offset is ignored.1274* If the new offset value is outside the valid range then a {@code DateTimeException} will be thrown.1275* <p>1276* The other {@link #isSupported(TemporalField) supported fields} will behave as per1277* the matching method on {@link LocalDateTime#with(TemporalField, long) LocalDateTime}.1278* The zone is not part of the calculation and will be unchanged.1279* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1280* then the offset will be retained if possible, otherwise the earlier offset will be used.1281* If in a gap, the local date-time will be adjusted forward by the length of the gap.1282* <p>1283* All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.1284* <p>1285* If the field is not a {@code ChronoField}, then the result of this method1286* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}1287* passing {@code this} as the argument. In this case, the field determines1288* whether and how to adjust the instant.1289* <p>1290* This instance is immutable and unaffected by this method call.1291*1292* @param field the field to set in the result, not null1293* @param newValue the new value of the field in the result1294* @return a {@code ZonedDateTime} based on {@code this} with the specified field set, not null1295* @throws DateTimeException if the field cannot be set1296* @throws UnsupportedTemporalTypeException if the field is not supported1297* @throws ArithmeticException if numeric overflow occurs1298*/1299@Override1300public ZonedDateTime with(TemporalField field, long newValue) {1301if (field instanceof ChronoField) {1302ChronoField f = (ChronoField) field;1303switch (f) {1304case INSTANT_SECONDS:1305return create(newValue, getNano(), zone);1306case OFFSET_SECONDS:1307ZoneOffset offset = ZoneOffset.ofTotalSeconds(f.checkValidIntValue(newValue));1308return resolveOffset(offset);1309}1310return resolveLocal(dateTime.with(field, newValue));1311}1312return field.adjustInto(this, newValue);1313}13141315//-----------------------------------------------------------------------1316/**1317* Returns a copy of this {@code ZonedDateTime} with the year altered.1318* <p>1319* This operates on the local time-line,1320* {@link LocalDateTime#withYear(int) changing the year} of the local date-time.1321* This is then converted back to a {@code ZonedDateTime}, using the zone ID1322* to obtain the offset.1323* <p>1324* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1325* then the offset will be retained if possible, otherwise the earlier offset will be used.1326* If in a gap, the local date-time will be adjusted forward by the length of the gap.1327* <p>1328* This instance is immutable and unaffected by this method call.1329*1330* @param year the year to set in the result, from MIN_YEAR to MAX_YEAR1331* @return a {@code ZonedDateTime} based on this date-time with the requested year, not null1332* @throws DateTimeException if the year value is invalid1333*/1334public ZonedDateTime withYear(int year) {1335return resolveLocal(dateTime.withYear(year));1336}13371338/**1339* Returns a copy of this {@code ZonedDateTime} with the month-of-year altered.1340* <p>1341* This operates on the local time-line,1342* {@link LocalDateTime#withMonth(int) changing the month} of the local date-time.1343* This is then converted back to a {@code ZonedDateTime}, using the zone ID1344* to obtain the offset.1345* <p>1346* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1347* then the offset will be retained if possible, otherwise the earlier offset will be used.1348* If in a gap, the local date-time will be adjusted forward by the length of the gap.1349* <p>1350* This instance is immutable and unaffected by this method call.1351*1352* @param month the month-of-year to set in the result, from 1 (January) to 12 (December)1353* @return a {@code ZonedDateTime} based on this date-time with the requested month, not null1354* @throws DateTimeException if the month-of-year value is invalid1355*/1356public ZonedDateTime withMonth(int month) {1357return resolveLocal(dateTime.withMonth(month));1358}13591360/**1361* Returns a copy of this {@code ZonedDateTime} with the day-of-month altered.1362* <p>1363* This operates on the local time-line,1364* {@link LocalDateTime#withDayOfMonth(int) changing the day-of-month} of the local date-time.1365* This is then converted back to a {@code ZonedDateTime}, using the zone ID1366* to obtain the offset.1367* <p>1368* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1369* then the offset will be retained if possible, otherwise the earlier offset will be used.1370* If in a gap, the local date-time will be adjusted forward by the length of the gap.1371* <p>1372* This instance is immutable and unaffected by this method call.1373*1374* @param dayOfMonth the day-of-month to set in the result, from 1 to 28-311375* @return a {@code ZonedDateTime} based on this date-time with the requested day, not null1376* @throws DateTimeException if the day-of-month value is invalid,1377* or if the day-of-month is invalid for the month-year1378*/1379public ZonedDateTime withDayOfMonth(int dayOfMonth) {1380return resolveLocal(dateTime.withDayOfMonth(dayOfMonth));1381}13821383/**1384* Returns a copy of this {@code ZonedDateTime} with the day-of-year altered.1385* <p>1386* This operates on the local time-line,1387* {@link LocalDateTime#withDayOfYear(int) changing the day-of-year} of the local date-time.1388* This is then converted back to a {@code ZonedDateTime}, using the zone ID1389* to obtain the offset.1390* <p>1391* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1392* then the offset will be retained if possible, otherwise the earlier offset will be used.1393* If in a gap, the local date-time will be adjusted forward by the length of the gap.1394* <p>1395* This instance is immutable and unaffected by this method call.1396*1397* @param dayOfYear the day-of-year to set in the result, from 1 to 365-3661398* @return a {@code ZonedDateTime} based on this date with the requested day, not null1399* @throws DateTimeException if the day-of-year value is invalid,1400* or if the day-of-year is invalid for the year1401*/1402public ZonedDateTime withDayOfYear(int dayOfYear) {1403return resolveLocal(dateTime.withDayOfYear(dayOfYear));1404}14051406//-----------------------------------------------------------------------1407/**1408* Returns a copy of this {@code ZonedDateTime} with the hour-of-day altered.1409* <p>1410* This operates on the local time-line,1411* {@linkplain LocalDateTime#withHour(int) changing the time} of the local date-time.1412* This is then converted back to a {@code ZonedDateTime}, using the zone ID1413* to obtain the offset.1414* <p>1415* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1416* then the offset will be retained if possible, otherwise the earlier offset will be used.1417* If in a gap, the local date-time will be adjusted forward by the length of the gap.1418* <p>1419* This instance is immutable and unaffected by this method call.1420*1421* @param hour the hour-of-day to set in the result, from 0 to 231422* @return a {@code ZonedDateTime} based on this date-time with the requested hour, not null1423* @throws DateTimeException if the hour value is invalid1424*/1425public ZonedDateTime withHour(int hour) {1426return resolveLocal(dateTime.withHour(hour));1427}14281429/**1430* Returns a copy of this {@code ZonedDateTime} with the minute-of-hour altered.1431* <p>1432* This operates on the local time-line,1433* {@linkplain LocalDateTime#withMinute(int) changing the time} of the local date-time.1434* This is then converted back to a {@code ZonedDateTime}, using the zone ID1435* to obtain the offset.1436* <p>1437* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1438* then the offset will be retained if possible, otherwise the earlier offset will be used.1439* If in a gap, the local date-time will be adjusted forward by the length of the gap.1440* <p>1441* This instance is immutable and unaffected by this method call.1442*1443* @param minute the minute-of-hour to set in the result, from 0 to 591444* @return a {@code ZonedDateTime} based on this date-time with the requested minute, not null1445* @throws DateTimeException if the minute value is invalid1446*/1447public ZonedDateTime withMinute(int minute) {1448return resolveLocal(dateTime.withMinute(minute));1449}14501451/**1452* Returns a copy of this {@code ZonedDateTime} with the second-of-minute altered.1453* <p>1454* This operates on the local time-line,1455* {@linkplain LocalDateTime#withSecond(int) changing the time} of the local date-time.1456* This is then converted back to a {@code ZonedDateTime}, using the zone ID1457* to obtain the offset.1458* <p>1459* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1460* then the offset will be retained if possible, otherwise the earlier offset will be used.1461* If in a gap, the local date-time will be adjusted forward by the length of the gap.1462* <p>1463* This instance is immutable and unaffected by this method call.1464*1465* @param second the second-of-minute to set in the result, from 0 to 591466* @return a {@code ZonedDateTime} based on this date-time with the requested second, not null1467* @throws DateTimeException if the second value is invalid1468*/1469public ZonedDateTime withSecond(int second) {1470return resolveLocal(dateTime.withSecond(second));1471}14721473/**1474* Returns a copy of this {@code ZonedDateTime} with the nano-of-second altered.1475* <p>1476* This operates on the local time-line,1477* {@linkplain LocalDateTime#withNano(int) changing the time} of the local date-time.1478* This is then converted back to a {@code ZonedDateTime}, using the zone ID1479* to obtain the offset.1480* <p>1481* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1482* then the offset will be retained if possible, otherwise the earlier offset will be used.1483* If in a gap, the local date-time will be adjusted forward by the length of the gap.1484* <p>1485* This instance is immutable and unaffected by this method call.1486*1487* @param nanoOfSecond the nano-of-second to set in the result, from 0 to 999,999,9991488* @return a {@code ZonedDateTime} based on this date-time with the requested nanosecond, not null1489* @throws DateTimeException if the nano value is invalid1490*/1491public ZonedDateTime withNano(int nanoOfSecond) {1492return resolveLocal(dateTime.withNano(nanoOfSecond));1493}14941495//-----------------------------------------------------------------------1496/**1497* Returns a copy of this {@code ZonedDateTime} with the time truncated.1498* <p>1499* Truncation returns a copy of the original date-time with fields1500* smaller than the specified unit set to zero.1501* For example, truncating with the {@link ChronoUnit#MINUTES minutes} unit1502* will set the second-of-minute and nano-of-second field to zero.1503* <p>1504* The unit must have a {@linkplain TemporalUnit#getDuration() duration}1505* that divides into the length of a standard day without remainder.1506* This includes all supplied time units on {@link ChronoUnit} and1507* {@link ChronoUnit#DAYS DAYS}. Other units throw an exception.1508* <p>1509* This operates on the local time-line,1510* {@link LocalDateTime#truncatedTo(TemporalUnit) truncating}1511* the underlying local date-time. This is then converted back to a1512* {@code ZonedDateTime}, using the zone ID to obtain the offset.1513* <p>1514* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1515* then the offset will be retained if possible, otherwise the earlier offset will be used.1516* If in a gap, the local date-time will be adjusted forward by the length of the gap.1517* <p>1518* This instance is immutable and unaffected by this method call.1519*1520* @param unit the unit to truncate to, not null1521* @return a {@code ZonedDateTime} based on this date-time with the time truncated, not null1522* @throws DateTimeException if unable to truncate1523* @throws UnsupportedTemporalTypeException if the unit is not supported1524*/1525public ZonedDateTime truncatedTo(TemporalUnit unit) {1526return resolveLocal(dateTime.truncatedTo(unit));1527}15281529//-----------------------------------------------------------------------1530/**1531* Returns a copy of this date-time with the specified amount added.1532* <p>1533* This returns a {@code ZonedDateTime}, based on this one, with the specified amount added.1534* The amount is typically {@link Period} or {@link Duration} but may be1535* any other type implementing the {@link TemporalAmount} interface.1536* <p>1537* The calculation is delegated to the amount object by calling1538* {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free1539* to implement the addition in any way it wishes, however it typically1540* calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation1541* of the amount implementation to determine if it can be successfully added.1542* <p>1543* This instance is immutable and unaffected by this method call.1544*1545* @param amountToAdd the amount to add, not null1546* @return a {@code ZonedDateTime} based on this date-time with the addition made, not null1547* @throws DateTimeException if the addition cannot be made1548* @throws ArithmeticException if numeric overflow occurs1549*/1550@Override1551public ZonedDateTime plus(TemporalAmount amountToAdd) {1552if (amountToAdd instanceof Period) {1553Period periodToAdd = (Period) amountToAdd;1554return resolveLocal(dateTime.plus(periodToAdd));1555}1556Objects.requireNonNull(amountToAdd, "amountToAdd");1557return (ZonedDateTime) amountToAdd.addTo(this);1558}15591560/**1561* Returns a copy of this date-time with the specified amount added.1562* <p>1563* This returns a {@code ZonedDateTime}, based on this one, with the amount1564* in terms of the unit added. If it is not possible to add the amount, because the1565* unit is not supported or for some other reason, an exception is thrown.1566* <p>1567* If the field is a {@link ChronoUnit} then the addition is implemented here.1568* The zone is not part of the calculation and will be unchanged in the result.1569* The calculation for date and time units differ.1570* <p>1571* Date units operate on the local time-line.1572* The period is first added to the local date-time, then converted back1573* to a zoned date-time using the zone ID.1574* The conversion uses {@link #ofLocal(LocalDateTime, ZoneId, ZoneOffset)}1575* with the offset before the addition.1576* <p>1577* Time units operate on the instant time-line.1578* The period is first added to the local date-time, then converted back to1579* a zoned date-time using the zone ID.1580* The conversion uses {@link #ofInstant(LocalDateTime, ZoneOffset, ZoneId)}1581* with the offset before the addition.1582* <p>1583* If the field is not a {@code ChronoUnit}, then the result of this method1584* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}1585* passing {@code this} as the argument. In this case, the unit determines1586* whether and how to perform the addition.1587* <p>1588* This instance is immutable and unaffected by this method call.1589*1590* @param amountToAdd the amount of the unit to add to the result, may be negative1591* @param unit the unit of the amount to add, not null1592* @return a {@code ZonedDateTime} based on this date-time with the specified amount added, not null1593* @throws DateTimeException if the addition cannot be made1594* @throws UnsupportedTemporalTypeException if the unit is not supported1595* @throws ArithmeticException if numeric overflow occurs1596*/1597@Override1598public ZonedDateTime plus(long amountToAdd, TemporalUnit unit) {1599if (unit instanceof ChronoUnit) {1600if (unit.isDateBased()) {1601return resolveLocal(dateTime.plus(amountToAdd, unit));1602} else {1603return resolveInstant(dateTime.plus(amountToAdd, unit));1604}1605}1606return unit.addTo(this, amountToAdd);1607}16081609//-----------------------------------------------------------------------1610/**1611* Returns a copy of this {@code ZonedDateTime} with the specified number of years added.1612* <p>1613* This operates on the local time-line,1614* {@link LocalDateTime#plusYears(long) adding years} to the local date-time.1615* This is then converted back to a {@code ZonedDateTime}, using the zone ID1616* to obtain the offset.1617* <p>1618* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1619* then the offset will be retained if possible, otherwise the earlier offset will be used.1620* If in a gap, the local date-time will be adjusted forward by the length of the gap.1621* <p>1622* This instance is immutable and unaffected by this method call.1623*1624* @param years the years to add, may be negative1625* @return a {@code ZonedDateTime} based on this date-time with the years added, not null1626* @throws DateTimeException if the result exceeds the supported date range1627*/1628public ZonedDateTime plusYears(long years) {1629return resolveLocal(dateTime.plusYears(years));1630}16311632/**1633* Returns a copy of this {@code ZonedDateTime} with the specified number of months added.1634* <p>1635* This operates on the local time-line,1636* {@link LocalDateTime#plusMonths(long) adding months} to the local date-time.1637* This is then converted back to a {@code ZonedDateTime}, using the zone ID1638* to obtain the offset.1639* <p>1640* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1641* then the offset will be retained if possible, otherwise the earlier offset will be used.1642* If in a gap, the local date-time will be adjusted forward by the length of the gap.1643* <p>1644* This instance is immutable and unaffected by this method call.1645*1646* @param months the months to add, may be negative1647* @return a {@code ZonedDateTime} based on this date-time with the months added, not null1648* @throws DateTimeException if the result exceeds the supported date range1649*/1650public ZonedDateTime plusMonths(long months) {1651return resolveLocal(dateTime.plusMonths(months));1652}16531654/**1655* Returns a copy of this {@code ZonedDateTime} with the specified number of weeks added.1656* <p>1657* This operates on the local time-line,1658* {@link LocalDateTime#plusWeeks(long) adding weeks} to the local date-time.1659* This is then converted back to a {@code ZonedDateTime}, using the zone ID1660* to obtain the offset.1661* <p>1662* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1663* then the offset will be retained if possible, otherwise the earlier offset will be used.1664* If in a gap, the local date-time will be adjusted forward by the length of the gap.1665* <p>1666* This instance is immutable and unaffected by this method call.1667*1668* @param weeks the weeks to add, may be negative1669* @return a {@code ZonedDateTime} based on this date-time with the weeks added, not null1670* @throws DateTimeException if the result exceeds the supported date range1671*/1672public ZonedDateTime plusWeeks(long weeks) {1673return resolveLocal(dateTime.plusWeeks(weeks));1674}16751676/**1677* Returns a copy of this {@code ZonedDateTime} with the specified number of days added.1678* <p>1679* This operates on the local time-line,1680* {@link LocalDateTime#plusDays(long) adding days} to the local date-time.1681* This is then converted back to a {@code ZonedDateTime}, using the zone ID1682* to obtain the offset.1683* <p>1684* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1685* then the offset will be retained if possible, otherwise the earlier offset will be used.1686* If in a gap, the local date-time will be adjusted forward by the length of the gap.1687* <p>1688* This instance is immutable and unaffected by this method call.1689*1690* @param days the days to add, may be negative1691* @return a {@code ZonedDateTime} based on this date-time with the days added, not null1692* @throws DateTimeException if the result exceeds the supported date range1693*/1694public ZonedDateTime plusDays(long days) {1695return resolveLocal(dateTime.plusDays(days));1696}16971698//-----------------------------------------------------------------------1699/**1700* Returns a copy of this {@code ZonedDateTime} with the specified number of hours added.1701* <p>1702* This operates on the instant time-line, such that adding one hour will1703* always be a duration of one hour later.1704* This may cause the local date-time to change by an amount other than one hour.1705* Note that this is a different approach to that used by days, months and years,1706* thus adding one day is not the same as adding 24 hours.1707* <p>1708* For example, consider a time-zone where the spring DST cutover means that the1709* local times 01:00 to 01:59 occur twice changing from offset +02:00 to +01:00.1710* <ul>1711* <li>Adding one hour to 00:30+02:00 will result in 01:30+02:001712* <li>Adding one hour to 01:30+02:00 will result in 01:30+01:001713* <li>Adding one hour to 01:30+01:00 will result in 02:30+01:001714* <li>Adding three hours to 00:30+02:00 will result in 02:30+01:001715* </ul>1716* <p>1717* This instance is immutable and unaffected by this method call.1718*1719* @param hours the hours to add, may be negative1720* @return a {@code ZonedDateTime} based on this date-time with the hours added, not null1721* @throws DateTimeException if the result exceeds the supported date range1722*/1723public ZonedDateTime plusHours(long hours) {1724return resolveInstant(dateTime.plusHours(hours));1725}17261727/**1728* Returns a copy of this {@code ZonedDateTime} with the specified number of minutes added.1729* <p>1730* This operates on the instant time-line, such that adding one minute will1731* always be a duration of one minute later.1732* This may cause the local date-time to change by an amount other than one minute.1733* Note that this is a different approach to that used by days, months and years.1734* <p>1735* This instance is immutable and unaffected by this method call.1736*1737* @param minutes the minutes to add, may be negative1738* @return a {@code ZonedDateTime} based on this date-time with the minutes added, not null1739* @throws DateTimeException if the result exceeds the supported date range1740*/1741public ZonedDateTime plusMinutes(long minutes) {1742return resolveInstant(dateTime.plusMinutes(minutes));1743}17441745/**1746* Returns a copy of this {@code ZonedDateTime} with the specified number of seconds added.1747* <p>1748* This operates on the instant time-line, such that adding one second will1749* always be a duration of one second later.1750* This may cause the local date-time to change by an amount other than one second.1751* Note that this is a different approach to that used by days, months and years.1752* <p>1753* This instance is immutable and unaffected by this method call.1754*1755* @param seconds the seconds to add, may be negative1756* @return a {@code ZonedDateTime} based on this date-time with the seconds added, not null1757* @throws DateTimeException if the result exceeds the supported date range1758*/1759public ZonedDateTime plusSeconds(long seconds) {1760return resolveInstant(dateTime.plusSeconds(seconds));1761}17621763/**1764* Returns a copy of this {@code ZonedDateTime} with the specified number of nanoseconds added.1765* <p>1766* This operates on the instant time-line, such that adding one nano will1767* always be a duration of one nano later.1768* This may cause the local date-time to change by an amount other than one nano.1769* Note that this is a different approach to that used by days, months and years.1770* <p>1771* This instance is immutable and unaffected by this method call.1772*1773* @param nanos the nanos to add, may be negative1774* @return a {@code ZonedDateTime} based on this date-time with the nanoseconds added, not null1775* @throws DateTimeException if the result exceeds the supported date range1776*/1777public ZonedDateTime plusNanos(long nanos) {1778return resolveInstant(dateTime.plusNanos(nanos));1779}17801781//-----------------------------------------------------------------------1782/**1783* Returns a copy of this date-time with the specified amount subtracted.1784* <p>1785* This returns a {@code ZonedDateTime}, based on this one, with the specified amount subtracted.1786* The amount is typically {@link Period} or {@link Duration} but may be1787* any other type implementing the {@link TemporalAmount} interface.1788* <p>1789* The calculation is delegated to the amount object by calling1790* {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free1791* to implement the subtraction in any way it wishes, however it typically1792* calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation1793* of the amount implementation to determine if it can be successfully subtracted.1794* <p>1795* This instance is immutable and unaffected by this method call.1796*1797* @param amountToSubtract the amount to subtract, not null1798* @return a {@code ZonedDateTime} based on this date-time with the subtraction made, not null1799* @throws DateTimeException if the subtraction cannot be made1800* @throws ArithmeticException if numeric overflow occurs1801*/1802@Override1803public ZonedDateTime minus(TemporalAmount amountToSubtract) {1804if (amountToSubtract instanceof Period) {1805Period periodToSubtract = (Period) amountToSubtract;1806return resolveLocal(dateTime.minus(periodToSubtract));1807}1808Objects.requireNonNull(amountToSubtract, "amountToSubtract");1809return (ZonedDateTime) amountToSubtract.subtractFrom(this);1810}18111812/**1813* Returns a copy of this date-time with the specified amount subtracted.1814* <p>1815* This returns a {@code ZonedDateTime}, based on this one, with the amount1816* in terms of the unit subtracted. If it is not possible to subtract the amount,1817* because the unit is not supported or for some other reason, an exception is thrown.1818* <p>1819* The calculation for date and time units differ.1820* <p>1821* Date units operate on the local time-line.1822* The period is first subtracted from the local date-time, then converted back1823* to a zoned date-time using the zone ID.1824* The conversion uses {@link #ofLocal(LocalDateTime, ZoneId, ZoneOffset)}1825* with the offset before the subtraction.1826* <p>1827* Time units operate on the instant time-line.1828* The period is first subtracted from the local date-time, then converted back to1829* a zoned date-time using the zone ID.1830* The conversion uses {@link #ofInstant(LocalDateTime, ZoneOffset, ZoneId)}1831* with the offset before the subtraction.1832* <p>1833* This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.1834* See that method for a full description of how addition, and thus subtraction, works.1835* <p>1836* This instance is immutable and unaffected by this method call.1837*1838* @param amountToSubtract the amount of the unit to subtract from the result, may be negative1839* @param unit the unit of the amount to subtract, not null1840* @return a {@code ZonedDateTime} based on this date-time with the specified amount subtracted, not null1841* @throws DateTimeException if the subtraction cannot be made1842* @throws UnsupportedTemporalTypeException if the unit is not supported1843* @throws ArithmeticException if numeric overflow occurs1844*/1845@Override1846public ZonedDateTime minus(long amountToSubtract, TemporalUnit unit) {1847return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));1848}18491850//-----------------------------------------------------------------------1851/**1852* Returns a copy of this {@code ZonedDateTime} with the specified number of years subtracted.1853* <p>1854* This operates on the local time-line,1855* {@link LocalDateTime#minusYears(long) subtracting years} to the local date-time.1856* This is then converted back to a {@code ZonedDateTime}, using the zone ID1857* to obtain the offset.1858* <p>1859* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1860* then the offset will be retained if possible, otherwise the earlier offset will be used.1861* If in a gap, the local date-time will be adjusted forward by the length of the gap.1862* <p>1863* This instance is immutable and unaffected by this method call.1864*1865* @param years the years to subtract, may be negative1866* @return a {@code ZonedDateTime} based on this date-time with the years subtracted, not null1867* @throws DateTimeException if the result exceeds the supported date range1868*/1869public ZonedDateTime minusYears(long years) {1870return (years == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-years));1871}18721873/**1874* Returns a copy of this {@code ZonedDateTime} with the specified number of months subtracted.1875* <p>1876* This operates on the local time-line,1877* {@link LocalDateTime#minusMonths(long) subtracting months} to the local date-time.1878* This is then converted back to a {@code ZonedDateTime}, using the zone ID1879* to obtain the offset.1880* <p>1881* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1882* then the offset will be retained if possible, otherwise the earlier offset will be used.1883* If in a gap, the local date-time will be adjusted forward by the length of the gap.1884* <p>1885* This instance is immutable and unaffected by this method call.1886*1887* @param months the months to subtract, may be negative1888* @return a {@code ZonedDateTime} based on this date-time with the months subtracted, not null1889* @throws DateTimeException if the result exceeds the supported date range1890*/1891public ZonedDateTime minusMonths(long months) {1892return (months == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-months));1893}18941895/**1896* Returns a copy of this {@code ZonedDateTime} with the specified number of weeks subtracted.1897* <p>1898* This operates on the local time-line,1899* {@link LocalDateTime#minusWeeks(long) subtracting weeks} to the local date-time.1900* This is then converted back to a {@code ZonedDateTime}, using the zone ID1901* to obtain the offset.1902* <p>1903* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1904* then the offset will be retained if possible, otherwise the earlier offset will be used.1905* If in a gap, the local date-time will be adjusted forward by the length of the gap.1906* <p>1907* This instance is immutable and unaffected by this method call.1908*1909* @param weeks the weeks to subtract, may be negative1910* @return a {@code ZonedDateTime} based on this date-time with the weeks subtracted, not null1911* @throws DateTimeException if the result exceeds the supported date range1912*/1913public ZonedDateTime minusWeeks(long weeks) {1914return (weeks == Long.MIN_VALUE ? plusWeeks(Long.MAX_VALUE).plusWeeks(1) : plusWeeks(-weeks));1915}19161917/**1918* Returns a copy of this {@code ZonedDateTime} with the specified number of days subtracted.1919* <p>1920* This operates on the local time-line,1921* {@link LocalDateTime#minusDays(long) subtracting days} to the local date-time.1922* This is then converted back to a {@code ZonedDateTime}, using the zone ID1923* to obtain the offset.1924* <p>1925* When converting back to {@code ZonedDateTime}, if the local date-time is in an overlap,1926* then the offset will be retained if possible, otherwise the earlier offset will be used.1927* If in a gap, the local date-time will be adjusted forward by the length of the gap.1928* <p>1929* This instance is immutable and unaffected by this method call.1930*1931* @param days the days to subtract, may be negative1932* @return a {@code ZonedDateTime} based on this date-time with the days subtracted, not null1933* @throws DateTimeException if the result exceeds the supported date range1934*/1935public ZonedDateTime minusDays(long days) {1936return (days == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-days));1937}19381939//-----------------------------------------------------------------------1940/**1941* Returns a copy of this {@code ZonedDateTime} with the specified number of hours subtracted.1942* <p>1943* This operates on the instant time-line, such that subtracting one hour will1944* always be a duration of one hour earlier.1945* This may cause the local date-time to change by an amount other than one hour.1946* Note that this is a different approach to that used by days, months and years,1947* thus subtracting one day is not the same as adding 24 hours.1948* <p>1949* For example, consider a time-zone where the spring DST cutover means that the1950* local times 01:00 to 01:59 occur twice changing from offset +02:00 to +01:00.1951* <ul>1952* <li>Subtracting one hour from 02:30+01:00 will result in 01:30+02:001953* <li>Subtracting one hour from 01:30+01:00 will result in 01:30+02:001954* <li>Subtracting one hour from 01:30+02:00 will result in 00:30+01:001955* <li>Subtracting three hours from 02:30+01:00 will result in 00:30+02:001956* </ul>1957* <p>1958* This instance is immutable and unaffected by this method call.1959*1960* @param hours the hours to subtract, may be negative1961* @return a {@code ZonedDateTime} based on this date-time with the hours subtracted, not null1962* @throws DateTimeException if the result exceeds the supported date range1963*/1964public ZonedDateTime minusHours(long hours) {1965return (hours == Long.MIN_VALUE ? plusHours(Long.MAX_VALUE).plusHours(1) : plusHours(-hours));1966}19671968/**1969* Returns a copy of this {@code ZonedDateTime} with the specified number of minutes subtracted.1970* <p>1971* This operates on the instant time-line, such that subtracting one minute will1972* always be a duration of one minute earlier.1973* This may cause the local date-time to change by an amount other than one minute.1974* Note that this is a different approach to that used by days, months and years.1975* <p>1976* This instance is immutable and unaffected by this method call.1977*1978* @param minutes the minutes to subtract, may be negative1979* @return a {@code ZonedDateTime} based on this date-time with the minutes subtracted, not null1980* @throws DateTimeException if the result exceeds the supported date range1981*/1982public ZonedDateTime minusMinutes(long minutes) {1983return (minutes == Long.MIN_VALUE ? plusMinutes(Long.MAX_VALUE).plusMinutes(1) : plusMinutes(-minutes));1984}19851986/**1987* Returns a copy of this {@code ZonedDateTime} with the specified number of seconds subtracted.1988* <p>1989* This operates on the instant time-line, such that subtracting one second will1990* always be a duration of one second earlier.1991* This may cause the local date-time to change by an amount other than one second.1992* Note that this is a different approach to that used by days, months and years.1993* <p>1994* This instance is immutable and unaffected by this method call.1995*1996* @param seconds the seconds to subtract, may be negative1997* @return a {@code ZonedDateTime} based on this date-time with the seconds subtracted, not null1998* @throws DateTimeException if the result exceeds the supported date range1999*/2000public ZonedDateTime minusSeconds(long seconds) {2001return (seconds == Long.MIN_VALUE ? plusSeconds(Long.MAX_VALUE).plusSeconds(1) : plusSeconds(-seconds));2002}20032004/**2005* Returns a copy of this {@code ZonedDateTime} with the specified number of nanoseconds subtracted.2006* <p>2007* This operates on the instant time-line, such that subtracting one nano will2008* always be a duration of one nano earlier.2009* This may cause the local date-time to change by an amount other than one nano.2010* Note that this is a different approach to that used by days, months and years.2011* <p>2012* This instance is immutable and unaffected by this method call.2013*2014* @param nanos the nanos to subtract, may be negative2015* @return a {@code ZonedDateTime} based on this date-time with the nanoseconds subtracted, not null2016* @throws DateTimeException if the result exceeds the supported date range2017*/2018public ZonedDateTime minusNanos(long nanos) {2019return (nanos == Long.MIN_VALUE ? plusNanos(Long.MAX_VALUE).plusNanos(1) : plusNanos(-nanos));2020}20212022//-----------------------------------------------------------------------2023/**2024* Queries this date-time using the specified query.2025* <p>2026* This queries this date-time using the specified query strategy object.2027* The {@code TemporalQuery} object defines the logic to be used to2028* obtain the result. Read the documentation of the query to understand2029* what the result of this method will be.2030* <p>2031* The result of this method is obtained by invoking the2032* {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the2033* specified query passing {@code this} as the argument.2034*2035* @param <R> the type of the result2036* @param query the query to invoke, not null2037* @return the query result, null may be returned (defined by the query)2038* @throws DateTimeException if unable to query (defined by the query)2039* @throws ArithmeticException if numeric overflow occurs (defined by the query)2040*/2041@SuppressWarnings("unchecked")2042@Override // override for Javadoc2043public <R> R query(TemporalQuery<R> query) {2044if (query == TemporalQueries.localDate()) {2045return (R) toLocalDate();2046}2047return ChronoZonedDateTime.super.query(query);2048}20492050/**2051* Calculates the amount of time until another date-time in terms of the specified unit.2052* <p>2053* This calculates the amount of time between two {@code ZonedDateTime}2054* objects in terms of a single {@code TemporalUnit}.2055* The start and end points are {@code this} and the specified date-time.2056* The result will be negative if the end is before the start.2057* For example, the amount in days between two date-times can be calculated2058* using {@code startDateTime.until(endDateTime, DAYS)}.2059* <p>2060* The {@code Temporal} passed to this method is converted to a2061* {@code ZonedDateTime} using {@link #from(TemporalAccessor)}.2062* If the time-zone differs between the two zoned date-times, the specified2063* end date-time is normalized to have the same zone as this date-time.2064* <p>2065* The calculation returns a whole number, representing the number of2066* complete units between the two date-times.2067* For example, the amount in months between 2012-06-15T00:00Z and 2012-08-14T23:59Z2068* will only be one month as it is one minute short of two months.2069* <p>2070* There are two equivalent ways of using this method.2071* The first is to invoke this method.2072* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:2073* <pre>2074* // these two lines are equivalent2075* amount = start.until(end, MONTHS);2076* amount = MONTHS.between(start, end);2077* </pre>2078* The choice should be made based on which makes the code more readable.2079* <p>2080* The calculation is implemented in this method for {@link ChronoUnit}.2081* The units {@code NANOS}, {@code MICROS}, {@code MILLIS}, {@code SECONDS},2082* {@code MINUTES}, {@code HOURS} and {@code HALF_DAYS}, {@code DAYS},2083* {@code WEEKS}, {@code MONTHS}, {@code YEARS}, {@code DECADES},2084* {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS} are supported.2085* Other {@code ChronoUnit} values will throw an exception.2086* <p>2087* The calculation for date and time units differ.2088* <p>2089* Date units operate on the local time-line, using the local date-time.2090* For example, the period from noon on day 1 to noon the following day2091* in days will always be counted as exactly one day, irrespective of whether2092* there was a daylight savings change or not.2093* <p>2094* Time units operate on the instant time-line.2095* The calculation effectively converts both zoned date-times to instants2096* and then calculates the period between the instants.2097* For example, the period from noon on day 1 to noon the following day2098* in hours may be 23, 24 or 25 hours (or some other amount) depending on2099* whether there was a daylight savings change or not.2100* <p>2101* If the unit is not a {@code ChronoUnit}, then the result of this method2102* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}2103* passing {@code this} as the first argument and the converted input temporal2104* as the second argument.2105* <p>2106* This instance is immutable and unaffected by this method call.2107*2108* @param endExclusive the end date, exclusive, which is converted to a {@code ZonedDateTime}, not null2109* @param unit the unit to measure the amount in, not null2110* @return the amount of time between this date-time and the end date-time2111* @throws DateTimeException if the amount cannot be calculated, or the end2112* temporal cannot be converted to a {@code ZonedDateTime}2113* @throws UnsupportedTemporalTypeException if the unit is not supported2114* @throws ArithmeticException if numeric overflow occurs2115*/2116@Override2117public long until(Temporal endExclusive, TemporalUnit unit) {2118ZonedDateTime end = ZonedDateTime.from(endExclusive);2119if (unit instanceof ChronoUnit) {2120end = end.withZoneSameInstant(zone);2121if (unit.isDateBased()) {2122return dateTime.until(end.dateTime, unit);2123} else {2124return toOffsetDateTime().until(end.toOffsetDateTime(), unit);2125}2126}2127return unit.between(this, end);2128}21292130/**2131* Formats this date-time using the specified formatter.2132* <p>2133* This date-time will be passed to the formatter to produce a string.2134*2135* @param formatter the formatter to use, not null2136* @return the formatted date-time string, not null2137* @throws DateTimeException if an error occurs during printing2138*/2139@Override // override for Javadoc and performance2140public String format(DateTimeFormatter formatter) {2141Objects.requireNonNull(formatter, "formatter");2142return formatter.format(this);2143}21442145//-----------------------------------------------------------------------2146/**2147* Converts this date-time to an {@code OffsetDateTime}.2148* <p>2149* This creates an offset date-time using the local date-time and offset.2150* The zone ID is ignored.2151*2152* @return an offset date-time representing the same local date-time and offset, not null2153*/2154public OffsetDateTime toOffsetDateTime() {2155return OffsetDateTime.of(dateTime, offset);2156}21572158//-----------------------------------------------------------------------2159/**2160* Checks if this date-time is equal to another date-time.2161* <p>2162* The comparison is based on the offset date-time and the zone.2163* Only objects of type {@code ZonedDateTime} are compared, other types return false.2164*2165* @param obj the object to check, null returns false2166* @return true if this is equal to the other date-time2167*/2168@Override2169public boolean equals(Object obj) {2170if (this == obj) {2171return true;2172}2173if (obj instanceof ZonedDateTime) {2174ZonedDateTime other = (ZonedDateTime) obj;2175return dateTime.equals(other.dateTime) &&2176offset.equals(other.offset) &&2177zone.equals(other.zone);2178}2179return false;2180}21812182/**2183* A hash code for this date-time.2184*2185* @return a suitable hash code2186*/2187@Override2188public int hashCode() {2189return dateTime.hashCode() ^ offset.hashCode() ^ Integer.rotateLeft(zone.hashCode(), 3);2190}21912192//-----------------------------------------------------------------------2193/**2194* Outputs this date-time as a {@code String}, such as2195* {@code 2007-12-03T10:15:30+01:00[Europe/Paris]}.2196* <p>2197* The format consists of the {@code LocalDateTime} followed by the {@code ZoneOffset}.2198* If the {@code ZoneId} is not the same as the offset, then the ID is output.2199* The output is compatible with ISO-8601 if the offset and ID are the same.2200*2201* @return a string representation of this date-time, not null2202*/2203@Override // override for Javadoc2204public String toString() {2205String str = dateTime.toString() + offset.toString();2206if (offset != zone) {2207str += '[' + zone.toString() + ']';2208}2209return str;2210}22112212//-----------------------------------------------------------------------2213/**2214* Writes the object using a2215* <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.2216* @serialData2217* <pre>2218* out.writeByte(6); // identifies a ZonedDateTime2219* // the <a href="../../serialized-form.html#java.time.LocalDateTime">dateTime</a> excluding the one byte header2220* // the <a href="../../serialized-form.html#java.time.ZoneOffset">offset</a> excluding the one byte header2221* // the <a href="../../serialized-form.html#java.time.ZoneId">zone ID</a> excluding the one byte header2222* </pre>2223*2224* @return the instance of {@code Ser}, not null2225*/2226private Object writeReplace() {2227return new Ser(Ser.ZONE_DATE_TIME_TYPE, this);2228}22292230/**2231* Defend against malicious streams.2232*2233* @param s the stream to read2234* @throws InvalidObjectException always2235*/2236private void readObject(ObjectInputStream s) throws InvalidObjectException {2237throw new InvalidObjectException("Deserialization via serialization delegate");2238}22392240void writeExternal(DataOutput out) throws IOException {2241dateTime.writeExternal(out);2242offset.writeExternal(out);2243zone.write(out);2244}22452246static ZonedDateTime readExternal(ObjectInput in) throws IOException, ClassNotFoundException {2247LocalDateTime dateTime = LocalDateTime.readExternal(in);2248ZoneOffset offset = ZoneOffset.readExternal(in);2249ZoneId zone = (ZoneId) Ser.read(in);2250return ZonedDateTime.ofLenient(dateTime, offset, zone);2251}22522253}225422552256