Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/time/Duration.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.LocalTime.NANOS_PER_SECOND;64import static java.time.LocalTime.SECONDS_PER_DAY;65import static java.time.LocalTime.SECONDS_PER_HOUR;66import static java.time.LocalTime.SECONDS_PER_MINUTE;67import static java.time.temporal.ChronoField.NANO_OF_SECOND;68import static java.time.temporal.ChronoUnit.DAYS;69import static java.time.temporal.ChronoUnit.NANOS;70import static java.time.temporal.ChronoUnit.SECONDS;7172import java.io.DataInput;73import java.io.DataOutput;74import java.io.IOException;75import java.io.InvalidObjectException;76import java.io.ObjectInputStream;77import java.io.Serializable;78import java.math.BigDecimal;79import java.math.BigInteger;80import java.math.RoundingMode;81import java.time.format.DateTimeParseException;82import java.time.temporal.ChronoField;83import java.time.temporal.ChronoUnit;84import java.time.temporal.Temporal;85import java.time.temporal.TemporalAmount;86import java.time.temporal.TemporalUnit;87import java.time.temporal.UnsupportedTemporalTypeException;88import java.util.Arrays;89import java.util.Collections;90import java.util.List;91import java.util.Objects;92import java.util.regex.Matcher;93import java.util.regex.Pattern;9495/**96* A time-based amount of time, such as '34.5 seconds'.97* <p>98* This class models a quantity or amount of time in terms of seconds and nanoseconds.99* It can be accessed using other duration-based units, such as minutes and hours.100* In addition, the {@link ChronoUnit#DAYS DAYS} unit can be used and is treated as101* exactly equal to 24 hours, thus ignoring daylight savings effects.102* See {@link Period} for the date-based equivalent to this class.103* <p>104* A physical duration could be of infinite length.105* For practicality, the duration is stored with constraints similar to {@link Instant}.106* The duration uses nanosecond resolution with a maximum value of the seconds that can107* be held in a {@code long}. This is greater than the current estimated age of the universe.108* <p>109* The range of a duration requires the storage of a number larger than a {@code long}.110* To achieve this, the class stores a {@code long} representing seconds and an {@code int}111* representing nanosecond-of-second, which will always be between 0 and 999,999,999.112* The model is of a directed duration, meaning that the duration may be negative.113* <p>114* The duration is measured in "seconds", but these are not necessarily identical to115* the scientific "SI second" definition based on atomic clocks.116* This difference only impacts durations measured near a leap-second and should not affect117* most applications.118* See {@link Instant} for a discussion as to the meaning of the second and time-scales.119*120* <p>121* This is a <a href="{@docRoot}/java/lang/doc-files/ValueBased.html">value-based</a>122* class; use of identity-sensitive operations (including reference equality123* ({@code ==}), identity hash code, or synchronization) on instances of124* {@code Duration} may have unpredictable results and should be avoided.125* The {@code equals} method should be used for comparisons.126*127* @implSpec128* This class is immutable and thread-safe.129*130* @since 1.8131*/132public final class Duration133implements TemporalAmount, Comparable<Duration>, Serializable {134135/**136* Constant for a duration of zero.137*/138public static final Duration ZERO = new Duration(0, 0);139/**140* Serialization version.141*/142private static final long serialVersionUID = 3078945930695997490L;143/**144* Constant for nanos per second.145*/146private static final BigInteger BI_NANOS_PER_SECOND = BigInteger.valueOf(NANOS_PER_SECOND);147/**148* The pattern for parsing.149*/150private static final Pattern PATTERN =151Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)D)?" +152"(T(?:([-+]?[0-9]+)H)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)(?:[.,]([0-9]{0,9}))?S)?)?",153Pattern.CASE_INSENSITIVE);154155/**156* The number of seconds in the duration.157*/158private final long seconds;159/**160* The number of nanoseconds in the duration, expressed as a fraction of the161* number of seconds. This is always positive, and never exceeds 999,999,999.162*/163private final int nanos;164165//-----------------------------------------------------------------------166/**167* Obtains a {@code Duration} representing a number of standard 24 hour days.168* <p>169* The seconds are calculated based on the standard definition of a day,170* where each day is 86400 seconds which implies a 24 hour day.171* The nanosecond in second field is set to zero.172*173* @param days the number of days, positive or negative174* @return a {@code Duration}, not null175* @throws ArithmeticException if the input days exceeds the capacity of {@code Duration}176*/177public static Duration ofDays(long days) {178return create(Math.multiplyExact(days, SECONDS_PER_DAY), 0);179}180181/**182* Obtains a {@code Duration} representing a number of standard hours.183* <p>184* The seconds are calculated based on the standard definition of an hour,185* where each hour is 3600 seconds.186* The nanosecond in second field is set to zero.187*188* @param hours the number of hours, positive or negative189* @return a {@code Duration}, not null190* @throws ArithmeticException if the input hours exceeds the capacity of {@code Duration}191*/192public static Duration ofHours(long hours) {193return create(Math.multiplyExact(hours, SECONDS_PER_HOUR), 0);194}195196/**197* Obtains a {@code Duration} representing a number of standard minutes.198* <p>199* The seconds are calculated based on the standard definition of a minute,200* where each minute is 60 seconds.201* The nanosecond in second field is set to zero.202*203* @param minutes the number of minutes, positive or negative204* @return a {@code Duration}, not null205* @throws ArithmeticException if the input minutes exceeds the capacity of {@code Duration}206*/207public static Duration ofMinutes(long minutes) {208return create(Math.multiplyExact(minutes, SECONDS_PER_MINUTE), 0);209}210211//-----------------------------------------------------------------------212/**213* Obtains a {@code Duration} representing a number of seconds.214* <p>215* The nanosecond in second field is set to zero.216*217* @param seconds the number of seconds, positive or negative218* @return a {@code Duration}, not null219*/220public static Duration ofSeconds(long seconds) {221return create(seconds, 0);222}223224/**225* Obtains a {@code Duration} representing a number of seconds and an226* adjustment in nanoseconds.227* <p>228* This method allows an arbitrary number of nanoseconds to be passed in.229* The factory will alter the values of the second and nanosecond in order230* to ensure that the stored nanosecond is in the range 0 to 999,999,999.231* For example, the following will result in the exactly the same duration:232* <pre>233* Duration.ofSeconds(3, 1);234* Duration.ofSeconds(4, -999_999_999);235* Duration.ofSeconds(2, 1000_000_001);236* </pre>237*238* @param seconds the number of seconds, positive or negative239* @param nanoAdjustment the nanosecond adjustment to the number of seconds, positive or negative240* @return a {@code Duration}, not null241* @throws ArithmeticException if the adjustment causes the seconds to exceed the capacity of {@code Duration}242*/243public static Duration ofSeconds(long seconds, long nanoAdjustment) {244long secs = Math.addExact(seconds, Math.floorDiv(nanoAdjustment, NANOS_PER_SECOND));245int nos = (int) Math.floorMod(nanoAdjustment, NANOS_PER_SECOND);246return create(secs, nos);247}248249//-----------------------------------------------------------------------250/**251* Obtains a {@code Duration} representing a number of milliseconds.252* <p>253* The seconds and nanoseconds are extracted from the specified milliseconds.254*255* @param millis the number of milliseconds, positive or negative256* @return a {@code Duration}, not null257*/258public static Duration ofMillis(long millis) {259long secs = millis / 1000;260int mos = (int) (millis % 1000);261if (mos < 0) {262mos += 1000;263secs--;264}265return create(secs, mos * 1000_000);266}267268//-----------------------------------------------------------------------269/**270* Obtains a {@code Duration} representing a number of nanoseconds.271* <p>272* The seconds and nanoseconds are extracted from the specified nanoseconds.273*274* @param nanos the number of nanoseconds, positive or negative275* @return a {@code Duration}, not null276*/277public static Duration ofNanos(long nanos) {278long secs = nanos / NANOS_PER_SECOND;279int nos = (int) (nanos % NANOS_PER_SECOND);280if (nos < 0) {281nos += NANOS_PER_SECOND;282secs--;283}284return create(secs, nos);285}286287//-----------------------------------------------------------------------288/**289* Obtains a {@code Duration} representing an amount in the specified unit.290* <p>291* The parameters represent the two parts of a phrase like '6 Hours'. For example:292* <pre>293* Duration.of(3, SECONDS);294* Duration.of(465, HOURS);295* </pre>296* Only a subset of units are accepted by this method.297* The unit must either have an {@linkplain TemporalUnit#isDurationEstimated() exact duration} or298* be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception.299*300* @param amount the amount of the duration, measured in terms of the unit, positive or negative301* @param unit the unit that the duration is measured in, must have an exact duration, not null302* @return a {@code Duration}, not null303* @throws DateTimeException if the period unit has an estimated duration304* @throws ArithmeticException if a numeric overflow occurs305*/306public static Duration of(long amount, TemporalUnit unit) {307return ZERO.plus(amount, unit);308}309310//-----------------------------------------------------------------------311/**312* Obtains an instance of {@code Duration} from a temporal amount.313* <p>314* This obtains a duration based on the specified amount.315* A {@code TemporalAmount} represents an amount of time, which may be316* date-based or time-based, which this factory extracts to a duration.317* <p>318* The conversion loops around the set of units from the amount and uses319* the {@linkplain TemporalUnit#getDuration() duration} of the unit to320* calculate the total {@code Duration}.321* Only a subset of units are accepted by this method. The unit must either322* have an {@linkplain TemporalUnit#isDurationEstimated() exact duration}323* or be {@link ChronoUnit#DAYS} which is treated as 24 hours.324* If any other units are found then an exception is thrown.325*326* @param amount the temporal amount to convert, not null327* @return the equivalent duration, not null328* @throws DateTimeException if unable to convert to a {@code Duration}329* @throws ArithmeticException if numeric overflow occurs330*/331public static Duration from(TemporalAmount amount) {332Objects.requireNonNull(amount, "amount");333Duration duration = ZERO;334for (TemporalUnit unit : amount.getUnits()) {335duration = duration.plus(amount.get(unit), unit);336}337return duration;338}339340//-----------------------------------------------------------------------341/**342* Obtains a {@code Duration} from a text string such as {@code PnDTnHnMn.nS}.343* <p>344* This will parse a textual representation of a duration, including the345* string produced by {@code toString()}. The formats accepted are based346* on the ISO-8601 duration format {@code PnDTnHnMn.nS} with days347* considered to be exactly 24 hours.348* <p>349* The string starts with an optional sign, denoted by the ASCII negative350* or positive symbol. If negative, the whole period is negated.351* The ASCII letter "P" is next in upper or lower case.352* There are then four sections, each consisting of a number and a suffix.353* The sections have suffixes in ASCII of "D", "H", "M" and "S" for354* days, hours, minutes and seconds, accepted in upper or lower case.355* The suffixes must occur in order. The ASCII letter "T" must occur before356* the first occurrence, if any, of an hour, minute or second section.357* At least one of the four sections must be present, and if "T" is present358* there must be at least one section after the "T".359* The number part of each section must consist of one or more ASCII digits.360* The number may be prefixed by the ASCII negative or positive symbol.361* The number of days, hours and minutes must parse to an {@code long}.362* The number of seconds must parse to an {@code long} with optional fraction.363* The decimal point may be either a dot or a comma.364* The fractional part may have from zero to 9 digits.365* <p>366* The leading plus/minus sign, and negative values for other units are367* not part of the ISO-8601 standard.368* <p>369* Examples:370* <pre>371* "PT20.345S" -- parses as "20.345 seconds"372* "PT15M" -- parses as "15 minutes" (where a minute is 60 seconds)373* "PT10H" -- parses as "10 hours" (where an hour is 3600 seconds)374* "P2D" -- parses as "2 days" (where a day is 24 hours or 86400 seconds)375* "P2DT3H4M" -- parses as "2 days, 3 hours and 4 minutes"376* "P-6H3M" -- parses as "-6 hours and +3 minutes"377* "-P6H3M" -- parses as "-6 hours and -3 minutes"378* "-P-6H+3M" -- parses as "+6 hours and -3 minutes"379* </pre>380*381* @param text the text to parse, not null382* @return the parsed duration, not null383* @throws DateTimeParseException if the text cannot be parsed to a duration384*/385public static Duration parse(CharSequence text) {386Objects.requireNonNull(text, "text");387Matcher matcher = PATTERN.matcher(text);388if (matcher.matches()) {389// check for letter T but no time sections390if ("T".equals(matcher.group(3)) == false) {391boolean negate = "-".equals(matcher.group(1));392String dayMatch = matcher.group(2);393String hourMatch = matcher.group(4);394String minuteMatch = matcher.group(5);395String secondMatch = matcher.group(6);396String fractionMatch = matcher.group(7);397if (dayMatch != null || hourMatch != null || minuteMatch != null || secondMatch != null) {398long daysAsSecs = parseNumber(text, dayMatch, SECONDS_PER_DAY, "days");399long hoursAsSecs = parseNumber(text, hourMatch, SECONDS_PER_HOUR, "hours");400long minsAsSecs = parseNumber(text, minuteMatch, SECONDS_PER_MINUTE, "minutes");401long seconds = parseNumber(text, secondMatch, 1, "seconds");402int nanos = parseFraction(text, fractionMatch, seconds < 0 ? -1 : 1);403try {404return create(negate, daysAsSecs, hoursAsSecs, minsAsSecs, seconds, nanos);405} catch (ArithmeticException ex) {406throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: overflow", text, 0).initCause(ex);407}408}409}410}411throw new DateTimeParseException("Text cannot be parsed to a Duration", text, 0);412}413414private static long parseNumber(CharSequence text, String parsed, int multiplier, String errorText) {415// regex limits to [-+]?[0-9]+416if (parsed == null) {417return 0;418}419try {420long val = Long.parseLong(parsed);421return Math.multiplyExact(val, multiplier);422} catch (NumberFormatException | ArithmeticException ex) {423throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: " + errorText, text, 0).initCause(ex);424}425}426427private static int parseFraction(CharSequence text, String parsed, int negate) {428// regex limits to [0-9]{0,9}429if (parsed == null || parsed.length() == 0) {430return 0;431}432try {433parsed = (parsed + "000000000").substring(0, 9);434return Integer.parseInt(parsed) * negate;435} catch (NumberFormatException | ArithmeticException ex) {436throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: fraction", text, 0).initCause(ex);437}438}439440private static Duration create(boolean negate, long daysAsSecs, long hoursAsSecs, long minsAsSecs, long secs, int nanos) {441long seconds = Math.addExact(daysAsSecs, Math.addExact(hoursAsSecs, Math.addExact(minsAsSecs, secs)));442if (negate) {443return ofSeconds(seconds, nanos).negated();444}445return ofSeconds(seconds, nanos);446}447448//-----------------------------------------------------------------------449/**450* Obtains a {@code Duration} representing the duration between two temporal objects.451* <p>452* This calculates the duration between two temporal objects. If the objects453* are of different types, then the duration is calculated based on the type454* of the first object. For example, if the first argument is a {@code LocalTime}455* then the second argument is converted to a {@code LocalTime}.456* <p>457* The specified temporal objects must support the {@link ChronoUnit#SECONDS SECONDS} unit.458* For full accuracy, either the {@link ChronoUnit#NANOS NANOS} unit or the459* {@link ChronoField#NANO_OF_SECOND NANO_OF_SECOND} field should be supported.460* <p>461* The result of this method can be a negative period if the end is before the start.462* To guarantee to obtain a positive duration call {@link #abs()} on the result.463*464* @param startInclusive the start instant, inclusive, not null465* @param endExclusive the end instant, exclusive, not null466* @return a {@code Duration}, not null467* @throws DateTimeException if the seconds between the temporals cannot be obtained468* @throws ArithmeticException if the calculation exceeds the capacity of {@code Duration}469*/470public static Duration between(Temporal startInclusive, Temporal endExclusive) {471try {472return ofNanos(startInclusive.until(endExclusive, NANOS));473} catch (DateTimeException | ArithmeticException ex) {474long secs = startInclusive.until(endExclusive, SECONDS);475long nanos;476try {477nanos = endExclusive.getLong(NANO_OF_SECOND) - startInclusive.getLong(NANO_OF_SECOND);478if (secs > 0 && nanos < 0) {479secs++;480} else if (secs < 0 && nanos > 0) {481secs--;482}483} catch (DateTimeException ex2) {484nanos = 0;485}486return ofSeconds(secs, nanos);487}488}489490//-----------------------------------------------------------------------491/**492* Obtains an instance of {@code Duration} using seconds and nanoseconds.493*494* @param seconds the length of the duration in seconds, positive or negative495* @param nanoAdjustment the nanosecond adjustment within the second, from 0 to 999,999,999496*/497private static Duration create(long seconds, int nanoAdjustment) {498if ((seconds | nanoAdjustment) == 0) {499return ZERO;500}501return new Duration(seconds, nanoAdjustment);502}503504/**505* Constructs an instance of {@code Duration} using seconds and nanoseconds.506*507* @param seconds the length of the duration in seconds, positive or negative508* @param nanos the nanoseconds within the second, from 0 to 999,999,999509*/510private Duration(long seconds, int nanos) {511super();512this.seconds = seconds;513this.nanos = nanos;514}515516//-----------------------------------------------------------------------517/**518* Gets the value of the requested unit.519* <p>520* This returns a value for each of the two supported units,521* {@link ChronoUnit#SECONDS SECONDS} and {@link ChronoUnit#NANOS NANOS}.522* All other units throw an exception.523*524* @param unit the {@code TemporalUnit} for which to return the value525* @return the long value of the unit526* @throws DateTimeException if the unit is not supported527* @throws UnsupportedTemporalTypeException if the unit is not supported528*/529@Override530public long get(TemporalUnit unit) {531if (unit == SECONDS) {532return seconds;533} else if (unit == NANOS) {534return nanos;535} else {536throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);537}538}539540/**541* Gets the set of units supported by this duration.542* <p>543* The supported units are {@link ChronoUnit#SECONDS SECONDS},544* and {@link ChronoUnit#NANOS NANOS}.545* They are returned in the order seconds, nanos.546* <p>547* This set can be used in conjunction with {@link #get(TemporalUnit)}548* to access the entire state of the duration.549*550* @return a list containing the seconds and nanos units, not null551*/552@Override553public List<TemporalUnit> getUnits() {554return DurationUnits.UNITS;555}556557/**558* Private class to delay initialization of this list until needed.559* The circular dependency between Duration and ChronoUnit prevents560* the simple initialization in Duration.561*/562private static class DurationUnits {563static final List<TemporalUnit> UNITS =564Collections.unmodifiableList(Arrays.<TemporalUnit>asList(SECONDS, NANOS));565}566567//-----------------------------------------------------------------------568/**569* Checks if this duration is zero length.570* <p>571* A {@code Duration} represents a directed distance between two points on572* the time-line and can therefore be positive, zero or negative.573* This method checks whether the length is zero.574*575* @return true if this duration has a total length equal to zero576*/577public boolean isZero() {578return (seconds | nanos) == 0;579}580581/**582* Checks if this duration is negative, excluding zero.583* <p>584* A {@code Duration} represents a directed distance between two points on585* the time-line and can therefore be positive, zero or negative.586* This method checks whether the length is less than zero.587*588* @return true if this duration has a total length less than zero589*/590public boolean isNegative() {591return seconds < 0;592}593594//-----------------------------------------------------------------------595/**596* Gets the number of seconds in this duration.597* <p>598* The length of the duration is stored using two fields - seconds and nanoseconds.599* The nanoseconds part is a value from 0 to 999,999,999 that is an adjustment to600* the length in seconds.601* The total duration is defined by calling this method and {@link #getNano()}.602* <p>603* A {@code Duration} represents a directed distance between two points on the time-line.604* A negative duration is expressed by the negative sign of the seconds part.605* A duration of -1 nanosecond is stored as -1 seconds plus 999,999,999 nanoseconds.606*607* @return the whole seconds part of the length of the duration, positive or negative608*/609public long getSeconds() {610return seconds;611}612613/**614* Gets the number of nanoseconds within the second in this duration.615* <p>616* The length of the duration is stored using two fields - seconds and nanoseconds.617* The nanoseconds part is a value from 0 to 999,999,999 that is an adjustment to618* the length in seconds.619* The total duration is defined by calling this method and {@link #getSeconds()}.620* <p>621* A {@code Duration} represents a directed distance between two points on the time-line.622* A negative duration is expressed by the negative sign of the seconds part.623* A duration of -1 nanosecond is stored as -1 seconds plus 999,999,999 nanoseconds.624*625* @return the nanoseconds within the second part of the length of the duration, from 0 to 999,999,999626*/627public int getNano() {628return nanos;629}630631//-----------------------------------------------------------------------632/**633* Returns a copy of this duration with the specified amount of seconds.634* <p>635* This returns a duration with the specified seconds, retaining the636* nano-of-second part of this duration.637* <p>638* This instance is immutable and unaffected by this method call.639*640* @param seconds the seconds to represent, may be negative641* @return a {@code Duration} based on this period with the requested seconds, not null642*/643public Duration withSeconds(long seconds) {644return create(seconds, nanos);645}646647/**648* Returns a copy of this duration with the specified nano-of-second.649* <p>650* This returns a duration with the specified nano-of-second, retaining the651* seconds part of this duration.652* <p>653* This instance is immutable and unaffected by this method call.654*655* @param nanoOfSecond the nano-of-second to represent, from 0 to 999,999,999656* @return a {@code Duration} based on this period with the requested nano-of-second, not null657* @throws DateTimeException if the nano-of-second is invalid658*/659public Duration withNanos(int nanoOfSecond) {660NANO_OF_SECOND.checkValidIntValue(nanoOfSecond);661return create(seconds, nanoOfSecond);662}663664//-----------------------------------------------------------------------665/**666* Returns a copy of this duration with the specified duration added.667* <p>668* This instance is immutable and unaffected by this method call.669*670* @param duration the duration to add, positive or negative, not null671* @return a {@code Duration} based on this duration with the specified duration added, not null672* @throws ArithmeticException if numeric overflow occurs673*/674public Duration plus(Duration duration) {675return plus(duration.getSeconds(), duration.getNano());676}677678/**679* Returns a copy of this duration with the specified duration added.680* <p>681* The duration amount is measured in terms of the specified unit.682* Only a subset of units are accepted by this method.683* The unit must either have an {@linkplain TemporalUnit#isDurationEstimated() exact duration} or684* be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception.685* <p>686* This instance is immutable and unaffected by this method call.687*688* @param amountToAdd the amount to add, measured in terms of the unit, positive or negative689* @param unit the unit that the amount is measured in, must have an exact duration, not null690* @return a {@code Duration} based on this duration with the specified duration added, not null691* @throws UnsupportedTemporalTypeException if the unit is not supported692* @throws ArithmeticException if numeric overflow occurs693*/694public Duration plus(long amountToAdd, TemporalUnit unit) {695Objects.requireNonNull(unit, "unit");696if (unit == DAYS) {697return plus(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY), 0);698}699if (unit.isDurationEstimated()) {700throw new UnsupportedTemporalTypeException("Unit must not have an estimated duration");701}702if (amountToAdd == 0) {703return this;704}705if (unit instanceof ChronoUnit) {706switch ((ChronoUnit) unit) {707case NANOS: return plusNanos(amountToAdd);708case MICROS: return plusSeconds((amountToAdd / (1000_000L * 1000)) * 1000).plusNanos((amountToAdd % (1000_000L * 1000)) * 1000);709case MILLIS: return plusMillis(amountToAdd);710case SECONDS: return plusSeconds(amountToAdd);711}712return plusSeconds(Math.multiplyExact(unit.getDuration().seconds, amountToAdd));713}714Duration duration = unit.getDuration().multipliedBy(amountToAdd);715return plusSeconds(duration.getSeconds()).plusNanos(duration.getNano());716}717718//-----------------------------------------------------------------------719/**720* Returns a copy of this duration with the specified duration in standard 24 hour days added.721* <p>722* The number of days is multiplied by 86400 to obtain the number of seconds to add.723* This is based on the standard definition of a day as 24 hours.724* <p>725* This instance is immutable and unaffected by this method call.726*727* @param daysToAdd the days to add, positive or negative728* @return a {@code Duration} based on this duration with the specified days added, not null729* @throws ArithmeticException if numeric overflow occurs730*/731public Duration plusDays(long daysToAdd) {732return plus(Math.multiplyExact(daysToAdd, SECONDS_PER_DAY), 0);733}734735/**736* Returns a copy of this duration with the specified duration in hours added.737* <p>738* This instance is immutable and unaffected by this method call.739*740* @param hoursToAdd the hours to add, positive or negative741* @return a {@code Duration} based on this duration with the specified hours added, not null742* @throws ArithmeticException if numeric overflow occurs743*/744public Duration plusHours(long hoursToAdd) {745return plus(Math.multiplyExact(hoursToAdd, SECONDS_PER_HOUR), 0);746}747748/**749* Returns a copy of this duration with the specified duration in minutes added.750* <p>751* This instance is immutable and unaffected by this method call.752*753* @param minutesToAdd the minutes to add, positive or negative754* @return a {@code Duration} based on this duration with the specified minutes added, not null755* @throws ArithmeticException if numeric overflow occurs756*/757public Duration plusMinutes(long minutesToAdd) {758return plus(Math.multiplyExact(minutesToAdd, SECONDS_PER_MINUTE), 0);759}760761/**762* Returns a copy of this duration with the specified duration in seconds added.763* <p>764* This instance is immutable and unaffected by this method call.765*766* @param secondsToAdd the seconds to add, positive or negative767* @return a {@code Duration} based on this duration with the specified seconds added, not null768* @throws ArithmeticException if numeric overflow occurs769*/770public Duration plusSeconds(long secondsToAdd) {771return plus(secondsToAdd, 0);772}773774/**775* Returns a copy of this duration with the specified duration in milliseconds added.776* <p>777* This instance is immutable and unaffected by this method call.778*779* @param millisToAdd the milliseconds to add, positive or negative780* @return a {@code Duration} based on this duration with the specified milliseconds added, not null781* @throws ArithmeticException if numeric overflow occurs782*/783public Duration plusMillis(long millisToAdd) {784return plus(millisToAdd / 1000, (millisToAdd % 1000) * 1000_000);785}786787/**788* Returns a copy of this duration with the specified duration in nanoseconds added.789* <p>790* This instance is immutable and unaffected by this method call.791*792* @param nanosToAdd the nanoseconds to add, positive or negative793* @return a {@code Duration} based on this duration with the specified nanoseconds added, not null794* @throws ArithmeticException if numeric overflow occurs795*/796public Duration plusNanos(long nanosToAdd) {797return plus(0, nanosToAdd);798}799800/**801* Returns a copy of this duration with the specified duration added.802* <p>803* This instance is immutable and unaffected by this method call.804*805* @param secondsToAdd the seconds to add, positive or negative806* @param nanosToAdd the nanos to add, positive or negative807* @return a {@code Duration} based on this duration with the specified seconds added, not null808* @throws ArithmeticException if numeric overflow occurs809*/810private Duration plus(long secondsToAdd, long nanosToAdd) {811if ((secondsToAdd | nanosToAdd) == 0) {812return this;813}814long epochSec = Math.addExact(seconds, secondsToAdd);815epochSec = Math.addExact(epochSec, nanosToAdd / NANOS_PER_SECOND);816nanosToAdd = nanosToAdd % NANOS_PER_SECOND;817long nanoAdjustment = nanos + nanosToAdd; // safe int+NANOS_PER_SECOND818return ofSeconds(epochSec, nanoAdjustment);819}820821//-----------------------------------------------------------------------822/**823* Returns a copy of this duration with the specified duration subtracted.824* <p>825* This instance is immutable and unaffected by this method call.826*827* @param duration the duration to subtract, positive or negative, not null828* @return a {@code Duration} based on this duration with the specified duration subtracted, not null829* @throws ArithmeticException if numeric overflow occurs830*/831public Duration minus(Duration duration) {832long secsToSubtract = duration.getSeconds();833int nanosToSubtract = duration.getNano();834if (secsToSubtract == Long.MIN_VALUE) {835return plus(Long.MAX_VALUE, -nanosToSubtract).plus(1, 0);836}837return plus(-secsToSubtract, -nanosToSubtract);838}839840/**841* Returns a copy of this duration with the specified duration subtracted.842* <p>843* The duration amount is measured in terms of the specified unit.844* Only a subset of units are accepted by this method.845* The unit must either have an {@linkplain TemporalUnit#isDurationEstimated() exact duration} or846* be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception.847* <p>848* This instance is immutable and unaffected by this method call.849*850* @param amountToSubtract the amount to subtract, measured in terms of the unit, positive or negative851* @param unit the unit that the amount is measured in, must have an exact duration, not null852* @return a {@code Duration} based on this duration with the specified duration subtracted, not null853* @throws ArithmeticException if numeric overflow occurs854*/855public Duration minus(long amountToSubtract, TemporalUnit unit) {856return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));857}858859//-----------------------------------------------------------------------860/**861* Returns a copy of this duration with the specified duration in standard 24 hour days subtracted.862* <p>863* The number of days is multiplied by 86400 to obtain the number of seconds to subtract.864* This is based on the standard definition of a day as 24 hours.865* <p>866* This instance is immutable and unaffected by this method call.867*868* @param daysToSubtract the days to subtract, positive or negative869* @return a {@code Duration} based on this duration with the specified days subtracted, not null870* @throws ArithmeticException if numeric overflow occurs871*/872public Duration minusDays(long daysToSubtract) {873return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));874}875876/**877* Returns a copy of this duration with the specified duration in hours subtracted.878* <p>879* The number of hours is multiplied by 3600 to obtain the number of seconds to subtract.880* <p>881* This instance is immutable and unaffected by this method call.882*883* @param hoursToSubtract the hours to subtract, positive or negative884* @return a {@code Duration} based on this duration with the specified hours subtracted, not null885* @throws ArithmeticException if numeric overflow occurs886*/887public Duration minusHours(long hoursToSubtract) {888return (hoursToSubtract == Long.MIN_VALUE ? plusHours(Long.MAX_VALUE).plusHours(1) : plusHours(-hoursToSubtract));889}890891/**892* Returns a copy of this duration with the specified duration in minutes subtracted.893* <p>894* The number of hours is multiplied by 60 to obtain the number of seconds to subtract.895* <p>896* This instance is immutable and unaffected by this method call.897*898* @param minutesToSubtract the minutes to subtract, positive or negative899* @return a {@code Duration} based on this duration with the specified minutes subtracted, not null900* @throws ArithmeticException if numeric overflow occurs901*/902public Duration minusMinutes(long minutesToSubtract) {903return (minutesToSubtract == Long.MIN_VALUE ? plusMinutes(Long.MAX_VALUE).plusMinutes(1) : plusMinutes(-minutesToSubtract));904}905906/**907* Returns a copy of this duration with the specified duration in seconds subtracted.908* <p>909* This instance is immutable and unaffected by this method call.910*911* @param secondsToSubtract the seconds to subtract, positive or negative912* @return a {@code Duration} based on this duration with the specified seconds subtracted, not null913* @throws ArithmeticException if numeric overflow occurs914*/915public Duration minusSeconds(long secondsToSubtract) {916return (secondsToSubtract == Long.MIN_VALUE ? plusSeconds(Long.MAX_VALUE).plusSeconds(1) : plusSeconds(-secondsToSubtract));917}918919/**920* Returns a copy of this duration with the specified duration in milliseconds subtracted.921* <p>922* This instance is immutable and unaffected by this method call.923*924* @param millisToSubtract the milliseconds to subtract, positive or negative925* @return a {@code Duration} based on this duration with the specified milliseconds subtracted, not null926* @throws ArithmeticException if numeric overflow occurs927*/928public Duration minusMillis(long millisToSubtract) {929return (millisToSubtract == Long.MIN_VALUE ? plusMillis(Long.MAX_VALUE).plusMillis(1) : plusMillis(-millisToSubtract));930}931932/**933* Returns a copy of this duration with the specified duration in nanoseconds subtracted.934* <p>935* This instance is immutable and unaffected by this method call.936*937* @param nanosToSubtract the nanoseconds to subtract, positive or negative938* @return a {@code Duration} based on this duration with the specified nanoseconds subtracted, not null939* @throws ArithmeticException if numeric overflow occurs940*/941public Duration minusNanos(long nanosToSubtract) {942return (nanosToSubtract == Long.MIN_VALUE ? plusNanos(Long.MAX_VALUE).plusNanos(1) : plusNanos(-nanosToSubtract));943}944945//-----------------------------------------------------------------------946/**947* Returns a copy of this duration multiplied by the scalar.948* <p>949* This instance is immutable and unaffected by this method call.950*951* @param multiplicand the value to multiply the duration by, positive or negative952* @return a {@code Duration} based on this duration multiplied by the specified scalar, not null953* @throws ArithmeticException if numeric overflow occurs954*/955public Duration multipliedBy(long multiplicand) {956if (multiplicand == 0) {957return ZERO;958}959if (multiplicand == 1) {960return this;961}962return create(toSeconds().multiply(BigDecimal.valueOf(multiplicand)));963}964965/**966* Returns a copy of this duration divided by the specified value.967* <p>968* This instance is immutable and unaffected by this method call.969*970* @param divisor the value to divide the duration by, positive or negative, not zero971* @return a {@code Duration} based on this duration divided by the specified divisor, not null972* @throws ArithmeticException if the divisor is zero or if numeric overflow occurs973*/974public Duration dividedBy(long divisor) {975if (divisor == 0) {976throw new ArithmeticException("Cannot divide by zero");977}978if (divisor == 1) {979return this;980}981return create(toSeconds().divide(BigDecimal.valueOf(divisor), RoundingMode.DOWN));982}983984/**985* Converts this duration to the total length in seconds and986* fractional nanoseconds expressed as a {@code BigDecimal}.987*988* @return the total length of the duration in seconds, with a scale of 9, not null989*/990private BigDecimal toSeconds() {991return BigDecimal.valueOf(seconds).add(BigDecimal.valueOf(nanos, 9));992}993994/**995* Creates an instance of {@code Duration} from a number of seconds.996*997* @param seconds the number of seconds, up to scale 9, positive or negative998* @return a {@code Duration}, not null999* @throws ArithmeticException if numeric overflow occurs1000*/1001private static Duration create(BigDecimal seconds) {1002BigInteger nanos = seconds.movePointRight(9).toBigIntegerExact();1003BigInteger[] divRem = nanos.divideAndRemainder(BI_NANOS_PER_SECOND);1004if (divRem[0].bitLength() > 63) {1005throw new ArithmeticException("Exceeds capacity of Duration: " + nanos);1006}1007return ofSeconds(divRem[0].longValue(), divRem[1].intValue());1008}10091010//-----------------------------------------------------------------------1011/**1012* Returns a copy of this duration with the length negated.1013* <p>1014* This method swaps the sign of the total length of this duration.1015* For example, {@code PT1.3S} will be returned as {@code PT-1.3S}.1016* <p>1017* This instance is immutable and unaffected by this method call.1018*1019* @return a {@code Duration} based on this duration with the amount negated, not null1020* @throws ArithmeticException if numeric overflow occurs1021*/1022public Duration negated() {1023return multipliedBy(-1);1024}10251026/**1027* Returns a copy of this duration with a positive length.1028* <p>1029* This method returns a positive duration by effectively removing the sign from any negative total length.1030* For example, {@code PT-1.3S} will be returned as {@code PT1.3S}.1031* <p>1032* This instance is immutable and unaffected by this method call.1033*1034* @return a {@code Duration} based on this duration with an absolute length, not null1035* @throws ArithmeticException if numeric overflow occurs1036*/1037public Duration abs() {1038return isNegative() ? negated() : this;1039}10401041//-------------------------------------------------------------------------1042/**1043* Adds this duration to the specified temporal object.1044* <p>1045* This returns a temporal object of the same observable type as the input1046* with this duration added.1047* <p>1048* In most cases, it is clearer to reverse the calling pattern by using1049* {@link Temporal#plus(TemporalAmount)}.1050* <pre>1051* // these two lines are equivalent, but the second approach is recommended1052* dateTime = thisDuration.addTo(dateTime);1053* dateTime = dateTime.plus(thisDuration);1054* </pre>1055* <p>1056* The calculation will add the seconds, then nanos.1057* Only non-zero amounts will be added.1058* <p>1059* This instance is immutable and unaffected by this method call.1060*1061* @param temporal the temporal object to adjust, not null1062* @return an object of the same type with the adjustment made, not null1063* @throws DateTimeException if unable to add1064* @throws ArithmeticException if numeric overflow occurs1065*/1066@Override1067public Temporal addTo(Temporal temporal) {1068if (seconds != 0) {1069temporal = temporal.plus(seconds, SECONDS);1070}1071if (nanos != 0) {1072temporal = temporal.plus(nanos, NANOS);1073}1074return temporal;1075}10761077/**1078* Subtracts this duration from the specified temporal object.1079* <p>1080* This returns a temporal object of the same observable type as the input1081* with this duration subtracted.1082* <p>1083* In most cases, it is clearer to reverse the calling pattern by using1084* {@link Temporal#minus(TemporalAmount)}.1085* <pre>1086* // these two lines are equivalent, but the second approach is recommended1087* dateTime = thisDuration.subtractFrom(dateTime);1088* dateTime = dateTime.minus(thisDuration);1089* </pre>1090* <p>1091* The calculation will subtract the seconds, then nanos.1092* Only non-zero amounts will be added.1093* <p>1094* This instance is immutable and unaffected by this method call.1095*1096* @param temporal the temporal object to adjust, not null1097* @return an object of the same type with the adjustment made, not null1098* @throws DateTimeException if unable to subtract1099* @throws ArithmeticException if numeric overflow occurs1100*/1101@Override1102public Temporal subtractFrom(Temporal temporal) {1103if (seconds != 0) {1104temporal = temporal.minus(seconds, SECONDS);1105}1106if (nanos != 0) {1107temporal = temporal.minus(nanos, NANOS);1108}1109return temporal;1110}11111112//-----------------------------------------------------------------------1113/**1114* Gets the number of days in this duration.1115* <p>1116* This returns the total number of days in the duration by dividing the1117* number of seconds by 86400.1118* This is based on the standard definition of a day as 24 hours.1119* <p>1120* This instance is immutable and unaffected by this method call.1121*1122* @return the number of days in the duration, may be negative1123*/1124public long toDays() {1125return seconds / SECONDS_PER_DAY;1126}11271128/**1129* Gets the number of hours in this duration.1130* <p>1131* This returns the total number of hours in the duration by dividing the1132* number of seconds by 3600.1133* <p>1134* This instance is immutable and unaffected by this method call.1135*1136* @return the number of hours in the duration, may be negative1137*/1138public long toHours() {1139return seconds / SECONDS_PER_HOUR;1140}11411142/**1143* Gets the number of minutes in this duration.1144* <p>1145* This returns the total number of minutes in the duration by dividing the1146* number of seconds by 60.1147* <p>1148* This instance is immutable and unaffected by this method call.1149*1150* @return the number of minutes in the duration, may be negative1151*/1152public long toMinutes() {1153return seconds / SECONDS_PER_MINUTE;1154}11551156/**1157* Converts this duration to the total length in milliseconds.1158* <p>1159* If this duration is too large to fit in a {@code long} milliseconds, then an1160* exception is thrown.1161* <p>1162* If this duration has greater than millisecond precision, then the conversion1163* will drop any excess precision information as though the amount in nanoseconds1164* was subject to integer division by one million.1165*1166* @return the total length of the duration in milliseconds1167* @throws ArithmeticException if numeric overflow occurs1168*/1169public long toMillis() {1170long millis = Math.multiplyExact(seconds, 1000);1171millis = Math.addExact(millis, nanos / 1000_000);1172return millis;1173}11741175/**1176* Converts this duration to the total length in nanoseconds expressed as a {@code long}.1177* <p>1178* If this duration is too large to fit in a {@code long} nanoseconds, then an1179* exception is thrown.1180*1181* @return the total length of the duration in nanoseconds1182* @throws ArithmeticException if numeric overflow occurs1183*/1184public long toNanos() {1185long totalNanos = Math.multiplyExact(seconds, NANOS_PER_SECOND);1186totalNanos = Math.addExact(totalNanos, nanos);1187return totalNanos;1188}11891190//-----------------------------------------------------------------------1191/**1192* Compares this duration to the specified {@code Duration}.1193* <p>1194* The comparison is based on the total length of the durations.1195* It is "consistent with equals", as defined by {@link Comparable}.1196*1197* @param otherDuration the other duration to compare to, not null1198* @return the comparator value, negative if less, positive if greater1199*/1200@Override1201public int compareTo(Duration otherDuration) {1202int cmp = Long.compare(seconds, otherDuration.seconds);1203if (cmp != 0) {1204return cmp;1205}1206return nanos - otherDuration.nanos;1207}12081209//-----------------------------------------------------------------------1210/**1211* Checks if this duration is equal to the specified {@code Duration}.1212* <p>1213* The comparison is based on the total length of the durations.1214*1215* @param otherDuration the other duration, null returns false1216* @return true if the other duration is equal to this one1217*/1218@Override1219public boolean equals(Object otherDuration) {1220if (this == otherDuration) {1221return true;1222}1223if (otherDuration instanceof Duration) {1224Duration other = (Duration) otherDuration;1225return this.seconds == other.seconds &&1226this.nanos == other.nanos;1227}1228return false;1229}12301231/**1232* A hash code for this duration.1233*1234* @return a suitable hash code1235*/1236@Override1237public int hashCode() {1238return ((int) (seconds ^ (seconds >>> 32))) + (51 * nanos);1239}12401241//-----------------------------------------------------------------------1242/**1243* A string representation of this duration using ISO-8601 seconds1244* based representation, such as {@code PT8H6M12.345S}.1245* <p>1246* The format of the returned string will be {@code PTnHnMnS}, where n is1247* the relevant hours, minutes or seconds part of the duration.1248* Any fractional seconds are placed after a decimal point i the seconds section.1249* If a section has a zero value, it is omitted.1250* The hours, minutes and seconds will all have the same sign.1251* <p>1252* Examples:1253* <pre>1254* "20.345 seconds" -- "PT20.345S1255* "15 minutes" (15 * 60 seconds) -- "PT15M"1256* "10 hours" (10 * 3600 seconds) -- "PT10H"1257* "2 days" (2 * 86400 seconds) -- "PT48H"1258* </pre>1259* Note that multiples of 24 hours are not output as days to avoid confusion1260* with {@code Period}.1261*1262* @return an ISO-8601 representation of this duration, not null1263*/1264@Override1265public String toString() {1266if (this == ZERO) {1267return "PT0S";1268}1269long hours = seconds / SECONDS_PER_HOUR;1270int minutes = (int) ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);1271int secs = (int) (seconds % SECONDS_PER_MINUTE);1272StringBuilder buf = new StringBuilder(24);1273buf.append("PT");1274if (hours != 0) {1275buf.append(hours).append('H');1276}1277if (minutes != 0) {1278buf.append(minutes).append('M');1279}1280if (secs == 0 && nanos == 0 && buf.length() > 2) {1281return buf.toString();1282}1283if (secs < 0 && nanos > 0) {1284if (secs == -1) {1285buf.append("-0");1286} else {1287buf.append(secs + 1);1288}1289} else {1290buf.append(secs);1291}1292if (nanos > 0) {1293int pos = buf.length();1294if (secs < 0) {1295buf.append(2 * NANOS_PER_SECOND - nanos);1296} else {1297buf.append(nanos + NANOS_PER_SECOND);1298}1299while (buf.charAt(buf.length() - 1) == '0') {1300buf.setLength(buf.length() - 1);1301}1302buf.setCharAt(pos, '.');1303}1304buf.append('S');1305return buf.toString();1306}13071308//-----------------------------------------------------------------------1309/**1310* Writes the object using a1311* <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.1312* @serialData1313* <pre>1314* out.writeByte(1); // identifies a Duration1315* out.writeLong(seconds);1316* out.writeInt(nanos);1317* </pre>1318*1319* @return the instance of {@code Ser}, not null1320*/1321private Object writeReplace() {1322return new Ser(Ser.DURATION_TYPE, this);1323}13241325/**1326* Defend against malicious streams.1327*1328* @param s the stream to read1329* @throws InvalidObjectException always1330*/1331private void readObject(ObjectInputStream s) throws InvalidObjectException {1332throw new InvalidObjectException("Deserialization via serialization delegate");1333}13341335void writeExternal(DataOutput out) throws IOException {1336out.writeLong(seconds);1337out.writeInt(nanos);1338}13391340static Duration readExternal(DataInput in) throws IOException {1341long seconds = in.readLong();1342int nanos = in.readInt();1343return Duration.ofSeconds(seconds, nanos);1344}13451346}134713481349