1 /*
2  * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 /*
27  * This file is available under and governed by the GNU General Public
28  * License version 2 only, as published by the Free Software Foundation.
29  * However, the following notice accompanied the original version of this
30  * file:
31  *
32  * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
33  *
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions are met:
38  *
39  *  * Redistributions of source code must retain the above copyright notice,
40  *    this list of conditions and the following disclaimer.
41  *
42  *  * Redistributions in binary form must reproduce the above copyright notice,
43  *    this list of conditions and the following disclaimer in the documentation
44  *    and/or other materials provided with the distribution.
45  *
46  *  * Neither the name of JSR-310 nor the names of its contributors
47  *    may be used to endorse or promote products derived from this software
48  *    without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
54  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
55  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
56  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
57  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
58  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
59  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  */
62 package java.time;
63 
64 import static java.time.LocalTime.NANOS_PER_SECOND;
65 import static java.time.LocalTime.SECONDS_PER_DAY;
66 import static java.time.LocalTime.SECONDS_PER_HOUR;
67 import static java.time.LocalTime.SECONDS_PER_MINUTE;
68 import static java.time.temporal.ChronoField.NANO_OF_SECOND;
69 import static java.time.temporal.ChronoUnit.DAYS;
70 import static java.time.temporal.ChronoUnit.NANOS;
71 import static java.time.temporal.ChronoUnit.SECONDS;
72 
73 import java.io.DataInput;
74 import java.io.DataOutput;
75 import java.io.IOException;
76 import java.io.InvalidObjectException;
77 import java.io.ObjectInputStream;
78 import java.io.Serializable;
79 import java.math.BigDecimal;
80 import java.math.BigInteger;
81 import java.math.RoundingMode;
82 import java.time.format.DateTimeParseException;
83 import java.time.temporal.ChronoField;
84 import java.time.temporal.ChronoUnit;
85 import java.time.temporal.Temporal;
86 import java.time.temporal.TemporalAmount;
87 import java.time.temporal.TemporalUnit;
88 import java.time.temporal.UnsupportedTemporalTypeException;
89 import java.util.Arrays;
90 import java.util.Collections;
91 import java.util.List;
92 import java.util.Objects;
93 import java.util.regex.Matcher;
94 import java.util.regex.Pattern;
95 
96 // Android-changed: removed ValueBased paragraph.
97 /**
98  * A time-based amount of time, such as '34.5 seconds'.
99  * <p>
100  * This class models a quantity or amount of time in terms of seconds and nanoseconds.
101  * It can be accessed using other duration-based units, such as minutes and hours.
102  * In addition, the {@link ChronoUnit#DAYS DAYS} unit can be used and is treated as
103  * exactly equal to 24 hours, thus ignoring daylight savings effects.
104  * See {@link Period} for the date-based equivalent to this class.
105  * <p>
106  * A physical duration could be of infinite length.
107  * For practicality, the duration is stored with constraints similar to {@link Instant}.
108  * The duration uses nanosecond resolution with a maximum value of the seconds that can
109  * be held in a {@code long}. This is greater than the current estimated age of the universe.
110  * <p>
111  * The range of a duration requires the storage of a number larger than a {@code long}.
112  * To achieve this, the class stores a {@code long} representing seconds and an {@code int}
113  * representing nanosecond-of-second, which will always be between 0 and 999,999,999.
114  * The model is of a directed duration, meaning that the duration may be negative.
115  * <p>
116  * The duration is measured in "seconds", but these are not necessarily identical to
117  * the scientific "SI second" definition based on atomic clocks.
118  * This difference only impacts durations measured near a leap-second and should not affect
119  * most applications.
120  * See {@link Instant} for a discussion as to the meaning of the second and time-scales.
121  *
122  * @implSpec
123  * This class is immutable and thread-safe.
124  *
125  * @since 1.8
126  */
127 public final class Duration
128         implements TemporalAmount, Comparable<Duration>, Serializable {
129 
130     /**
131      * Constant for a duration of zero.
132      */
133     public static final Duration ZERO = new Duration(0, 0);
134     /**
135      * Serialization version.
136      */
137     private static final long serialVersionUID = 3078945930695997490L;
138     /**
139      * Constant for nanos per second.
140      */
141     private static final BigInteger BI_NANOS_PER_SECOND = BigInteger.valueOf(NANOS_PER_SECOND);
142     /**
143      * The pattern for parsing.
144      */
145     private static final Pattern PATTERN =
146             Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)D)?" +
147                     "(T(?:([-+]?[0-9]+)H)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)(?:[.,]([0-9]{0,9}))?S)?)?",
148                     Pattern.CASE_INSENSITIVE);
149 
150     /**
151      * The number of seconds in the duration.
152      */
153     private final long seconds;
154     /**
155      * The number of nanoseconds in the duration, expressed as a fraction of the
156      * number of seconds. This is always positive, and never exceeds 999,999,999.
157      */
158     private final int nanos;
159 
160     //-----------------------------------------------------------------------
161     /**
162      * Obtains a {@code Duration} representing a number of standard 24 hour days.
163      * <p>
164      * The seconds are calculated based on the standard definition of a day,
165      * where each day is 86400 seconds which implies a 24 hour day.
166      * The nanosecond in second field is set to zero.
167      *
168      * @param days  the number of days, positive or negative
169      * @return a {@code Duration}, not null
170      * @throws ArithmeticException if the input days exceeds the capacity of {@code Duration}
171      */
ofDays(long days)172     public static Duration ofDays(long days) {
173         return create(Math.multiplyExact(days, SECONDS_PER_DAY), 0);
174     }
175 
176     /**
177      * Obtains a {@code Duration} representing a number of standard hours.
178      * <p>
179      * The seconds are calculated based on the standard definition of an hour,
180      * where each hour is 3600 seconds.
181      * The nanosecond in second field is set to zero.
182      *
183      * @param hours  the number of hours, positive or negative
184      * @return a {@code Duration}, not null
185      * @throws ArithmeticException if the input hours exceeds the capacity of {@code Duration}
186      */
ofHours(long hours)187     public static Duration ofHours(long hours) {
188         return create(Math.multiplyExact(hours, SECONDS_PER_HOUR), 0);
189     }
190 
191     /**
192      * Obtains a {@code Duration} representing a number of standard minutes.
193      * <p>
194      * The seconds are calculated based on the standard definition of a minute,
195      * where each minute is 60 seconds.
196      * The nanosecond in second field is set to zero.
197      *
198      * @param minutes  the number of minutes, positive or negative
199      * @return a {@code Duration}, not null
200      * @throws ArithmeticException if the input minutes exceeds the capacity of {@code Duration}
201      */
ofMinutes(long minutes)202     public static Duration ofMinutes(long minutes) {
203         return create(Math.multiplyExact(minutes, SECONDS_PER_MINUTE), 0);
204     }
205 
206     //-----------------------------------------------------------------------
207     /**
208      * Obtains a {@code Duration} representing a number of seconds.
209      * <p>
210      * The nanosecond in second field is set to zero.
211      *
212      * @param seconds  the number of seconds, positive or negative
213      * @return a {@code Duration}, not null
214      */
ofSeconds(long seconds)215     public static Duration ofSeconds(long seconds) {
216         return create(seconds, 0);
217     }
218 
219     /**
220      * Obtains a {@code Duration} representing a number of seconds and an
221      * adjustment in nanoseconds.
222      * <p>
223      * This method allows an arbitrary number of nanoseconds to be passed in.
224      * The factory will alter the values of the second and nanosecond in order
225      * to ensure that the stored nanosecond is in the range 0 to 999,999,999.
226      * For example, the following will result in the exactly the same duration:
227      * <pre>
228      *  Duration.ofSeconds(3, 1);
229      *  Duration.ofSeconds(4, -999_999_999);
230      *  Duration.ofSeconds(2, 1000_000_001);
231      * </pre>
232      *
233      * @param seconds  the number of seconds, positive or negative
234      * @param nanoAdjustment  the nanosecond adjustment to the number of seconds, positive or negative
235      * @return a {@code Duration}, not null
236      * @throws ArithmeticException if the adjustment causes the seconds to exceed the capacity of {@code Duration}
237      */
ofSeconds(long seconds, long nanoAdjustment)238     public static Duration ofSeconds(long seconds, long nanoAdjustment) {
239         long secs = Math.addExact(seconds, Math.floorDiv(nanoAdjustment, NANOS_PER_SECOND));
240         int nos = (int) Math.floorMod(nanoAdjustment, NANOS_PER_SECOND);
241         return create(secs, nos);
242     }
243 
244     //-----------------------------------------------------------------------
245     /**
246      * Obtains a {@code Duration} representing a number of milliseconds.
247      * <p>
248      * The seconds and nanoseconds are extracted from the specified milliseconds.
249      *
250      * @param millis  the number of milliseconds, positive or negative
251      * @return a {@code Duration}, not null
252      */
ofMillis(long millis)253     public static Duration ofMillis(long millis) {
254         long secs = millis / 1000;
255         int mos = (int) (millis % 1000);
256         if (mos < 0) {
257             mos += 1000;
258             secs--;
259         }
260         return create(secs, mos * 1000_000);
261     }
262 
263     //-----------------------------------------------------------------------
264     /**
265      * Obtains a {@code Duration} representing a number of nanoseconds.
266      * <p>
267      * The seconds and nanoseconds are extracted from the specified nanoseconds.
268      *
269      * @param nanos  the number of nanoseconds, positive or negative
270      * @return a {@code Duration}, not null
271      */
ofNanos(long nanos)272     public static Duration ofNanos(long nanos) {
273         long secs = nanos / NANOS_PER_SECOND;
274         int nos = (int) (nanos % NANOS_PER_SECOND);
275         if (nos < 0) {
276             nos += NANOS_PER_SECOND;
277             secs--;
278         }
279         return create(secs, nos);
280     }
281 
282     //-----------------------------------------------------------------------
283     /**
284      * Obtains a {@code Duration} representing an amount in the specified unit.
285      * <p>
286      * The parameters represent the two parts of a phrase like '6 Hours'. For example:
287      * <pre>
288      *  Duration.of(3, SECONDS);
289      *  Duration.of(465, HOURS);
290      * </pre>
291      * Only a subset of units are accepted by this method.
292      * The unit must either have an {@linkplain TemporalUnit#isDurationEstimated() exact duration} or
293      * be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception.
294      *
295      * @param amount  the amount of the duration, measured in terms of the unit, positive or negative
296      * @param unit  the unit that the duration is measured in, must have an exact duration, not null
297      * @return a {@code Duration}, not null
298      * @throws DateTimeException if the period unit has an estimated duration
299      * @throws ArithmeticException if a numeric overflow occurs
300      */
of(long amount, TemporalUnit unit)301     public static Duration of(long amount, TemporalUnit unit) {
302         return ZERO.plus(amount, unit);
303     }
304 
305     //-----------------------------------------------------------------------
306     /**
307      * Obtains an instance of {@code Duration} from a temporal amount.
308      * <p>
309      * This obtains a duration based on the specified amount.
310      * A {@code TemporalAmount} represents an  amount of time, which may be
311      * date-based or time-based, which this factory extracts to a duration.
312      * <p>
313      * The conversion loops around the set of units from the amount and uses
314      * the {@linkplain TemporalUnit#getDuration() duration} of the unit to
315      * calculate the total {@code Duration}.
316      * Only a subset of units are accepted by this method. The unit must either
317      * have an {@linkplain TemporalUnit#isDurationEstimated() exact duration}
318      * or be {@link ChronoUnit#DAYS} which is treated as 24 hours.
319      * If any other units are found then an exception is thrown.
320      *
321      * @param amount  the temporal amount to convert, not null
322      * @return the equivalent duration, not null
323      * @throws DateTimeException if unable to convert to a {@code Duration}
324      * @throws ArithmeticException if numeric overflow occurs
325      */
from(TemporalAmount amount)326     public static Duration from(TemporalAmount amount) {
327         Objects.requireNonNull(amount, "amount");
328         Duration duration = ZERO;
329         for (TemporalUnit unit : amount.getUnits()) {
330             duration = duration.plus(amount.get(unit), unit);
331         }
332         return duration;
333     }
334 
335     //-----------------------------------------------------------------------
336     /**
337      * Obtains a {@code Duration} from a text string such as {@code PnDTnHnMn.nS}.
338      * <p>
339      * This will parse a textual representation of a duration, including the
340      * string produced by {@code toString()}. The formats accepted are based
341      * on the ISO-8601 duration format {@code PnDTnHnMn.nS} with days
342      * considered to be exactly 24 hours.
343      * <p>
344      * The string starts with an optional sign, denoted by the ASCII negative
345      * or positive symbol. If negative, the whole period is negated.
346      * The ASCII letter "P" is next in upper or lower case.
347      * There are then four sections, each consisting of a number and a suffix.
348      * The sections have suffixes in ASCII of "D", "H", "M" and "S" for
349      * days, hours, minutes and seconds, accepted in upper or lower case.
350      * The suffixes must occur in order. The ASCII letter "T" must occur before
351      * the first occurrence, if any, of an hour, minute or second section.
352      * At least one of the four sections must be present, and if "T" is present
353      * there must be at least one section after the "T".
354      * The number part of each section must consist of one or more ASCII digits.
355      * The number may be prefixed by the ASCII negative or positive symbol.
356      * The number of days, hours and minutes must parse to an {@code long}.
357      * The number of seconds must parse to an {@code long} with optional fraction.
358      * The decimal point may be either a dot or a comma.
359      * The fractional part may have from zero to 9 digits.
360      * <p>
361      * The leading plus/minus sign, and negative values for other units are
362      * not part of the ISO-8601 standard.
363      * <p>
364      * Examples:
365      * <pre>
366      *    "PT20.345S" -- parses as "20.345 seconds"
367      *    "PT15M"     -- parses as "15 minutes" (where a minute is 60 seconds)
368      *    "PT10H"     -- parses as "10 hours" (where an hour is 3600 seconds)
369      *    "P2D"       -- parses as "2 days" (where a day is 24 hours or 86400 seconds)
370      *    "P2DT3H4M"  -- parses as "2 days, 3 hours and 4 minutes"
371      *    "P-6H3M"    -- parses as "-6 hours and +3 minutes"
372      *    "-P6H3M"    -- parses as "-6 hours and -3 minutes"
373      *    "-P-6H+3M"  -- parses as "+6 hours and -3 minutes"
374      * </pre>
375      *
376      * @param text  the text to parse, not null
377      * @return the parsed duration, not null
378      * @throws DateTimeParseException if the text cannot be parsed to a duration
379      */
parse(CharSequence text)380     public static Duration parse(CharSequence text) {
381         Objects.requireNonNull(text, "text");
382         Matcher matcher = PATTERN.matcher(text);
383         if (matcher.matches()) {
384             // check for letter T but no time sections
385             if ("T".equals(matcher.group(3)) == false) {
386                 boolean negate = "-".equals(matcher.group(1));
387                 String dayMatch = matcher.group(2);
388                 String hourMatch = matcher.group(4);
389                 String minuteMatch = matcher.group(5);
390                 String secondMatch = matcher.group(6);
391                 String fractionMatch = matcher.group(7);
392                 if (dayMatch != null || hourMatch != null || minuteMatch != null || secondMatch != null) {
393                     long daysAsSecs = parseNumber(text, dayMatch, SECONDS_PER_DAY, "days");
394                     long hoursAsSecs = parseNumber(text, hourMatch, SECONDS_PER_HOUR, "hours");
395                     long minsAsSecs = parseNumber(text, minuteMatch, SECONDS_PER_MINUTE, "minutes");
396                     long seconds = parseNumber(text, secondMatch, 1, "seconds");
397                     int nanos = parseFraction(text,  fractionMatch, seconds < 0 ? -1 : 1);
398                     try {
399                         return create(negate, daysAsSecs, hoursAsSecs, minsAsSecs, seconds, nanos);
400                     } catch (ArithmeticException ex) {
401                         throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: overflow", text, 0).initCause(ex);
402                     }
403                 }
404             }
405         }
406         throw new DateTimeParseException("Text cannot be parsed to a Duration", text, 0);
407     }
408 
parseNumber(CharSequence text, String parsed, int multiplier, String errorText)409     private static long parseNumber(CharSequence text, String parsed, int multiplier, String errorText) {
410         // regex limits to [-+]?[0-9]+
411         if (parsed == null) {
412             return 0;
413         }
414         try {
415             long val = Long.parseLong(parsed);
416             return Math.multiplyExact(val, multiplier);
417         } catch (NumberFormatException | ArithmeticException ex) {
418             throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: " + errorText, text, 0).initCause(ex);
419         }
420     }
421 
parseFraction(CharSequence text, String parsed, int negate)422     private static int parseFraction(CharSequence text, String parsed, int negate) {
423         // regex limits to [0-9]{0,9}
424         if (parsed == null || parsed.length() == 0) {
425             return 0;
426         }
427         try {
428             parsed = (parsed + "000000000").substring(0, 9);
429             return Integer.parseInt(parsed) * negate;
430         } catch (NumberFormatException | ArithmeticException ex) {
431             throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: fraction", text, 0).initCause(ex);
432         }
433     }
434 
create(boolean negate, long daysAsSecs, long hoursAsSecs, long minsAsSecs, long secs, int nanos)435     private static Duration create(boolean negate, long daysAsSecs, long hoursAsSecs, long minsAsSecs, long secs, int nanos) {
436         long seconds = Math.addExact(daysAsSecs, Math.addExact(hoursAsSecs, Math.addExact(minsAsSecs, secs)));
437         if (negate) {
438             return ofSeconds(seconds, nanos).negated();
439         }
440         return ofSeconds(seconds, nanos);
441     }
442 
443     //-----------------------------------------------------------------------
444     /**
445      * Obtains a {@code Duration} representing the duration between two temporal objects.
446      * <p>
447      * This calculates the duration between two temporal objects. If the objects
448      * are of different types, then the duration is calculated based on the type
449      * of the first object. For example, if the first argument is a {@code LocalTime}
450      * then the second argument is converted to a {@code LocalTime}.
451      * <p>
452      * The specified temporal objects must support the {@link ChronoUnit#SECONDS SECONDS} unit.
453      * For full accuracy, either the {@link ChronoUnit#NANOS NANOS} unit or the
454      * {@link ChronoField#NANO_OF_SECOND NANO_OF_SECOND} field should be supported.
455      * <p>
456      * The result of this method can be a negative period if the end is before the start.
457      * To guarantee to obtain a positive duration call {@link #abs()} on the result.
458      *
459      * @param startInclusive  the start instant, inclusive, not null
460      * @param endExclusive  the end instant, exclusive, not null
461      * @return a {@code Duration}, not null
462      * @throws DateTimeException if the seconds between the temporals cannot be obtained
463      * @throws ArithmeticException if the calculation exceeds the capacity of {@code Duration}
464      */
between(Temporal startInclusive, Temporal endExclusive)465     public static Duration between(Temporal startInclusive, Temporal endExclusive) {
466         try {
467             return ofNanos(startInclusive.until(endExclusive, NANOS));
468         } catch (DateTimeException | ArithmeticException ex) {
469             long secs = startInclusive.until(endExclusive, SECONDS);
470             long nanos;
471             try {
472                 nanos = endExclusive.getLong(NANO_OF_SECOND) - startInclusive.getLong(NANO_OF_SECOND);
473                 if (secs > 0 && nanos < 0) {
474                     secs++;
475                 } else if (secs < 0 && nanos > 0) {
476                     secs--;
477                 }
478             } catch (DateTimeException ex2) {
479                 nanos = 0;
480             }
481             return ofSeconds(secs, nanos);
482         }
483     }
484 
485     //-----------------------------------------------------------------------
486     /**
487      * Obtains an instance of {@code Duration} using seconds and nanoseconds.
488      *
489      * @param seconds  the length of the duration in seconds, positive or negative
490      * @param nanoAdjustment  the nanosecond adjustment within the second, from 0 to 999,999,999
491      */
create(long seconds, int nanoAdjustment)492     private static Duration create(long seconds, int nanoAdjustment) {
493         if ((seconds | nanoAdjustment) == 0) {
494             return ZERO;
495         }
496         return new Duration(seconds, nanoAdjustment);
497     }
498 
499     /**
500      * Constructs an instance of {@code Duration} using seconds and nanoseconds.
501      *
502      * @param seconds  the length of the duration in seconds, positive or negative
503      * @param nanos  the nanoseconds within the second, from 0 to 999,999,999
504      */
Duration(long seconds, int nanos)505     private Duration(long seconds, int nanos) {
506         super();
507         this.seconds = seconds;
508         this.nanos = nanos;
509     }
510 
511     //-----------------------------------------------------------------------
512     /**
513      * Gets the value of the requested unit.
514      * <p>
515      * This returns a value for each of the two supported units,
516      * {@link ChronoUnit#SECONDS SECONDS} and {@link ChronoUnit#NANOS NANOS}.
517      * All other units throw an exception.
518      *
519      * @param unit the {@code TemporalUnit} for which to return the value
520      * @return the long value of the unit
521      * @throws DateTimeException if the unit is not supported
522      * @throws UnsupportedTemporalTypeException if the unit is not supported
523      */
524     @Override
get(TemporalUnit unit)525     public long get(TemporalUnit unit) {
526         if (unit == SECONDS) {
527             return seconds;
528         } else if (unit == NANOS) {
529             return nanos;
530         } else {
531             throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
532         }
533     }
534 
535     /**
536      * Gets the set of units supported by this duration.
537      * <p>
538      * The supported units are {@link ChronoUnit#SECONDS SECONDS},
539      * and {@link ChronoUnit#NANOS NANOS}.
540      * They are returned in the order seconds, nanos.
541      * <p>
542      * This set can be used in conjunction with {@link #get(TemporalUnit)}
543      * to access the entire state of the duration.
544      *
545      * @return a list containing the seconds and nanos units, not null
546      */
547     @Override
getUnits()548     public List<TemporalUnit> getUnits() {
549         return DurationUnits.UNITS;
550     }
551 
552     /**
553      * Private class to delay initialization of this list until needed.
554      * The circular dependency between Duration and ChronoUnit prevents
555      * the simple initialization in Duration.
556      */
557     private static class DurationUnits {
558         static final List<TemporalUnit> UNITS =
559                 Collections.unmodifiableList(Arrays.<TemporalUnit>asList(SECONDS, NANOS));
560     }
561 
562     //-----------------------------------------------------------------------
563     /**
564      * Checks if this duration is zero length.
565      * <p>
566      * A {@code Duration} represents a directed distance between two points on
567      * the time-line and can therefore be positive, zero or negative.
568      * This method checks whether the length is zero.
569      *
570      * @return true if this duration has a total length equal to zero
571      */
isZero()572     public boolean isZero() {
573         return (seconds | nanos) == 0;
574     }
575 
576     /**
577      * Checks if this duration is negative, excluding zero.
578      * <p>
579      * A {@code Duration} represents a directed distance between two points on
580      * the time-line and can therefore be positive, zero or negative.
581      * This method checks whether the length is less than zero.
582      *
583      * @return true if this duration has a total length less than zero
584      */
isNegative()585     public boolean isNegative() {
586         return seconds < 0;
587     }
588 
589     //-----------------------------------------------------------------------
590     /**
591      * Gets the number of seconds in this duration.
592      * <p>
593      * The length of the duration is stored using two fields - seconds and nanoseconds.
594      * The nanoseconds part is a value from 0 to 999,999,999 that is an adjustment to
595      * the length in seconds.
596      * The total duration is defined by calling this method and {@link #getNano()}.
597      * <p>
598      * A {@code Duration} represents a directed distance between two points on the time-line.
599      * A negative duration is expressed by the negative sign of the seconds part.
600      * A duration of -1 nanosecond is stored as -1 seconds plus 999,999,999 nanoseconds.
601      *
602      * @return the whole seconds part of the length of the duration, positive or negative
603      */
getSeconds()604     public long getSeconds() {
605         return seconds;
606     }
607 
608     /**
609      * Gets the number of nanoseconds within the second in this duration.
610      * <p>
611      * The length of the duration is stored using two fields - seconds and nanoseconds.
612      * The nanoseconds part is a value from 0 to 999,999,999 that is an adjustment to
613      * the length in seconds.
614      * The total duration is defined by calling this method and {@link #getSeconds()}.
615      * <p>
616      * A {@code Duration} represents a directed distance between two points on the time-line.
617      * A negative duration is expressed by the negative sign of the seconds part.
618      * A duration of -1 nanosecond is stored as -1 seconds plus 999,999,999 nanoseconds.
619      *
620      * @return the nanoseconds within the second part of the length of the duration, from 0 to 999,999,999
621      */
getNano()622     public int getNano() {
623         return nanos;
624     }
625 
626     //-----------------------------------------------------------------------
627     /**
628      * Returns a copy of this duration with the specified amount of seconds.
629      * <p>
630      * This returns a duration with the specified seconds, retaining the
631      * nano-of-second part of this duration.
632      * <p>
633      * This instance is immutable and unaffected by this method call.
634      *
635      * @param seconds  the seconds to represent, may be negative
636      * @return a {@code Duration} based on this period with the requested seconds, not null
637      */
withSeconds(long seconds)638     public Duration withSeconds(long seconds) {
639         return create(seconds, nanos);
640     }
641 
642     /**
643      * Returns a copy of this duration with the specified nano-of-second.
644      * <p>
645      * This returns a duration with the specified nano-of-second, retaining the
646      * seconds part of this duration.
647      * <p>
648      * This instance is immutable and unaffected by this method call.
649      *
650      * @param nanoOfSecond  the nano-of-second to represent, from 0 to 999,999,999
651      * @return a {@code Duration} based on this period with the requested nano-of-second, not null
652      * @throws DateTimeException if the nano-of-second is invalid
653      */
withNanos(int nanoOfSecond)654     public Duration withNanos(int nanoOfSecond) {
655         NANO_OF_SECOND.checkValidIntValue(nanoOfSecond);
656         return create(seconds, nanoOfSecond);
657     }
658 
659     //-----------------------------------------------------------------------
660     /**
661      * Returns a copy of this duration with the specified duration added.
662      * <p>
663      * This instance is immutable and unaffected by this method call.
664      *
665      * @param duration  the duration to add, positive or negative, not null
666      * @return a {@code Duration} based on this duration with the specified duration added, not null
667      * @throws ArithmeticException if numeric overflow occurs
668      */
plus(Duration duration)669     public Duration plus(Duration duration) {
670         return plus(duration.getSeconds(), duration.getNano());
671      }
672 
673     /**
674      * Returns a copy of this duration with the specified duration added.
675      * <p>
676      * The duration amount is measured in terms of the specified unit.
677      * Only a subset of units are accepted by this method.
678      * The unit must either have an {@linkplain TemporalUnit#isDurationEstimated() exact duration} or
679      * be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception.
680      * <p>
681      * This instance is immutable and unaffected by this method call.
682      *
683      * @param amountToAdd  the amount to add, measured in terms of the unit, positive or negative
684      * @param unit  the unit that the amount is measured in, must have an exact duration, not null
685      * @return a {@code Duration} based on this duration with the specified duration added, not null
686      * @throws UnsupportedTemporalTypeException if the unit is not supported
687      * @throws ArithmeticException if numeric overflow occurs
688      */
plus(long amountToAdd, TemporalUnit unit)689     public Duration plus(long amountToAdd, TemporalUnit unit) {
690         Objects.requireNonNull(unit, "unit");
691         if (unit == DAYS) {
692             return plus(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY), 0);
693         }
694         if (unit.isDurationEstimated()) {
695             throw new UnsupportedTemporalTypeException("Unit must not have an estimated duration");
696         }
697         if (amountToAdd == 0) {
698             return this;
699         }
700         if (unit instanceof ChronoUnit) {
701             switch ((ChronoUnit) unit) {
702                 case NANOS: return plusNanos(amountToAdd);
703                 case MICROS: return plusSeconds((amountToAdd / (1000_000L * 1000)) * 1000).plusNanos((amountToAdd % (1000_000L * 1000)) * 1000);
704                 case MILLIS: return plusMillis(amountToAdd);
705                 case SECONDS: return plusSeconds(amountToAdd);
706             }
707             return plusSeconds(Math.multiplyExact(unit.getDuration().seconds, amountToAdd));
708         }
709         Duration duration = unit.getDuration().multipliedBy(amountToAdd);
710         return plusSeconds(duration.getSeconds()).plusNanos(duration.getNano());
711     }
712 
713     //-----------------------------------------------------------------------
714     /**
715      * Returns a copy of this duration with the specified duration in standard 24 hour days added.
716      * <p>
717      * The number of days is multiplied by 86400 to obtain the number of seconds to add.
718      * This is based on the standard definition of a day as 24 hours.
719      * <p>
720      * This instance is immutable and unaffected by this method call.
721      *
722      * @param daysToAdd  the days to add, positive or negative
723      * @return a {@code Duration} based on this duration with the specified days added, not null
724      * @throws ArithmeticException if numeric overflow occurs
725      */
plusDays(long daysToAdd)726     public Duration plusDays(long daysToAdd) {
727         return plus(Math.multiplyExact(daysToAdd, SECONDS_PER_DAY), 0);
728     }
729 
730     /**
731      * Returns a copy of this duration with the specified duration in hours added.
732      * <p>
733      * This instance is immutable and unaffected by this method call.
734      *
735      * @param hoursToAdd  the hours to add, positive or negative
736      * @return a {@code Duration} based on this duration with the specified hours added, not null
737      * @throws ArithmeticException if numeric overflow occurs
738      */
plusHours(long hoursToAdd)739     public Duration plusHours(long hoursToAdd) {
740         return plus(Math.multiplyExact(hoursToAdd, SECONDS_PER_HOUR), 0);
741     }
742 
743     /**
744      * Returns a copy of this duration with the specified duration in minutes added.
745      * <p>
746      * This instance is immutable and unaffected by this method call.
747      *
748      * @param minutesToAdd  the minutes to add, positive or negative
749      * @return a {@code Duration} based on this duration with the specified minutes added, not null
750      * @throws ArithmeticException if numeric overflow occurs
751      */
plusMinutes(long minutesToAdd)752     public Duration plusMinutes(long minutesToAdd) {
753         return plus(Math.multiplyExact(minutesToAdd, SECONDS_PER_MINUTE), 0);
754     }
755 
756     /**
757      * Returns a copy of this duration with the specified duration in seconds added.
758      * <p>
759      * This instance is immutable and unaffected by this method call.
760      *
761      * @param secondsToAdd  the seconds to add, positive or negative
762      * @return a {@code Duration} based on this duration with the specified seconds added, not null
763      * @throws ArithmeticException if numeric overflow occurs
764      */
plusSeconds(long secondsToAdd)765     public Duration plusSeconds(long secondsToAdd) {
766         return plus(secondsToAdd, 0);
767     }
768 
769     /**
770      * Returns a copy of this duration with the specified duration in milliseconds added.
771      * <p>
772      * This instance is immutable and unaffected by this method call.
773      *
774      * @param millisToAdd  the milliseconds to add, positive or negative
775      * @return a {@code Duration} based on this duration with the specified milliseconds added, not null
776      * @throws ArithmeticException if numeric overflow occurs
777      */
plusMillis(long millisToAdd)778     public Duration plusMillis(long millisToAdd) {
779         return plus(millisToAdd / 1000, (millisToAdd % 1000) * 1000_000);
780     }
781 
782     /**
783      * Returns a copy of this duration with the specified duration in nanoseconds added.
784      * <p>
785      * This instance is immutable and unaffected by this method call.
786      *
787      * @param nanosToAdd  the nanoseconds to add, positive or negative
788      * @return a {@code Duration} based on this duration with the specified nanoseconds added, not null
789      * @throws ArithmeticException if numeric overflow occurs
790      */
plusNanos(long nanosToAdd)791     public Duration plusNanos(long nanosToAdd) {
792         return plus(0, nanosToAdd);
793     }
794 
795     /**
796      * Returns a copy of this duration with the specified duration added.
797      * <p>
798      * This instance is immutable and unaffected by this method call.
799      *
800      * @param secondsToAdd  the seconds to add, positive or negative
801      * @param nanosToAdd  the nanos to add, positive or negative
802      * @return a {@code Duration} based on this duration with the specified seconds added, not null
803      * @throws ArithmeticException if numeric overflow occurs
804      */
plus(long secondsToAdd, long nanosToAdd)805     private Duration plus(long secondsToAdd, long nanosToAdd) {
806         if ((secondsToAdd | nanosToAdd) == 0) {
807             return this;
808         }
809         long epochSec = Math.addExact(seconds, secondsToAdd);
810         epochSec = Math.addExact(epochSec, nanosToAdd / NANOS_PER_SECOND);
811         nanosToAdd = nanosToAdd % NANOS_PER_SECOND;
812         long nanoAdjustment = nanos + nanosToAdd;  // safe int+NANOS_PER_SECOND
813         return ofSeconds(epochSec, nanoAdjustment);
814     }
815 
816     //-----------------------------------------------------------------------
817     /**
818      * Returns a copy of this duration with the specified duration subtracted.
819      * <p>
820      * This instance is immutable and unaffected by this method call.
821      *
822      * @param duration  the duration to subtract, positive or negative, not null
823      * @return a {@code Duration} based on this duration with the specified duration subtracted, not null
824      * @throws ArithmeticException if numeric overflow occurs
825      */
minus(Duration duration)826     public Duration minus(Duration duration) {
827         long secsToSubtract = duration.getSeconds();
828         int nanosToSubtract = duration.getNano();
829         if (secsToSubtract == Long.MIN_VALUE) {
830             return plus(Long.MAX_VALUE, -nanosToSubtract).plus(1, 0);
831         }
832         return plus(-secsToSubtract, -nanosToSubtract);
833      }
834 
835     /**
836      * Returns a copy of this duration with the specified duration subtracted.
837      * <p>
838      * The duration amount is measured in terms of the specified unit.
839      * Only a subset of units are accepted by this method.
840      * The unit must either have an {@linkplain TemporalUnit#isDurationEstimated() exact duration} or
841      * be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception.
842      * <p>
843      * This instance is immutable and unaffected by this method call.
844      *
845      * @param amountToSubtract  the amount to subtract, measured in terms of the unit, positive or negative
846      * @param unit  the unit that the amount is measured in, must have an exact duration, not null
847      * @return a {@code Duration} based on this duration with the specified duration subtracted, not null
848      * @throws ArithmeticException if numeric overflow occurs
849      */
minus(long amountToSubtract, TemporalUnit unit)850     public Duration minus(long amountToSubtract, TemporalUnit unit) {
851         return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
852     }
853 
854     //-----------------------------------------------------------------------
855     /**
856      * Returns a copy of this duration with the specified duration in standard 24 hour days subtracted.
857      * <p>
858      * The number of days is multiplied by 86400 to obtain the number of seconds to subtract.
859      * This is based on the standard definition of a day as 24 hours.
860      * <p>
861      * This instance is immutable and unaffected by this method call.
862      *
863      * @param daysToSubtract  the days to subtract, positive or negative
864      * @return a {@code Duration} based on this duration with the specified days subtracted, not null
865      * @throws ArithmeticException if numeric overflow occurs
866      */
minusDays(long daysToSubtract)867     public Duration minusDays(long daysToSubtract) {
868         return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));
869     }
870 
871     /**
872      * Returns a copy of this duration with the specified duration in hours subtracted.
873      * <p>
874      * The number of hours is multiplied by 3600 to obtain the number of seconds to subtract.
875      * <p>
876      * This instance is immutable and unaffected by this method call.
877      *
878      * @param hoursToSubtract  the hours to subtract, positive or negative
879      * @return a {@code Duration} based on this duration with the specified hours subtracted, not null
880      * @throws ArithmeticException if numeric overflow occurs
881      */
minusHours(long hoursToSubtract)882     public Duration minusHours(long hoursToSubtract) {
883         return (hoursToSubtract == Long.MIN_VALUE ? plusHours(Long.MAX_VALUE).plusHours(1) : plusHours(-hoursToSubtract));
884     }
885 
886     /**
887      * Returns a copy of this duration with the specified duration in minutes subtracted.
888      * <p>
889      * The number of hours is multiplied by 60 to obtain the number of seconds to subtract.
890      * <p>
891      * This instance is immutable and unaffected by this method call.
892      *
893      * @param minutesToSubtract  the minutes to subtract, positive or negative
894      * @return a {@code Duration} based on this duration with the specified minutes subtracted, not null
895      * @throws ArithmeticException if numeric overflow occurs
896      */
minusMinutes(long minutesToSubtract)897     public Duration minusMinutes(long minutesToSubtract) {
898         return (minutesToSubtract == Long.MIN_VALUE ? plusMinutes(Long.MAX_VALUE).plusMinutes(1) : plusMinutes(-minutesToSubtract));
899     }
900 
901     /**
902      * Returns a copy of this duration with the specified duration in seconds subtracted.
903      * <p>
904      * This instance is immutable and unaffected by this method call.
905      *
906      * @param secondsToSubtract  the seconds to subtract, positive or negative
907      * @return a {@code Duration} based on this duration with the specified seconds subtracted, not null
908      * @throws ArithmeticException if numeric overflow occurs
909      */
minusSeconds(long secondsToSubtract)910     public Duration minusSeconds(long secondsToSubtract) {
911         return (secondsToSubtract == Long.MIN_VALUE ? plusSeconds(Long.MAX_VALUE).plusSeconds(1) : plusSeconds(-secondsToSubtract));
912     }
913 
914     /**
915      * Returns a copy of this duration with the specified duration in milliseconds subtracted.
916      * <p>
917      * This instance is immutable and unaffected by this method call.
918      *
919      * @param millisToSubtract  the milliseconds to subtract, positive or negative
920      * @return a {@code Duration} based on this duration with the specified milliseconds subtracted, not null
921      * @throws ArithmeticException if numeric overflow occurs
922      */
minusMillis(long millisToSubtract)923     public Duration minusMillis(long millisToSubtract) {
924         return (millisToSubtract == Long.MIN_VALUE ? plusMillis(Long.MAX_VALUE).plusMillis(1) : plusMillis(-millisToSubtract));
925     }
926 
927     /**
928      * Returns a copy of this duration with the specified duration in nanoseconds subtracted.
929      * <p>
930      * This instance is immutable and unaffected by this method call.
931      *
932      * @param nanosToSubtract  the nanoseconds to subtract, positive or negative
933      * @return a {@code Duration} based on this duration with the specified nanoseconds subtracted, not null
934      * @throws ArithmeticException if numeric overflow occurs
935      */
minusNanos(long nanosToSubtract)936     public Duration minusNanos(long nanosToSubtract) {
937         return (nanosToSubtract == Long.MIN_VALUE ? plusNanos(Long.MAX_VALUE).plusNanos(1) : plusNanos(-nanosToSubtract));
938     }
939 
940     //-----------------------------------------------------------------------
941     /**
942      * Returns a copy of this duration multiplied by the scalar.
943      * <p>
944      * This instance is immutable and unaffected by this method call.
945      *
946      * @param multiplicand  the value to multiply the duration by, positive or negative
947      * @return a {@code Duration} based on this duration multiplied by the specified scalar, not null
948      * @throws ArithmeticException if numeric overflow occurs
949      */
multipliedBy(long multiplicand)950     public Duration multipliedBy(long multiplicand) {
951         if (multiplicand == 0) {
952             return ZERO;
953         }
954         if (multiplicand == 1) {
955             return this;
956         }
957         return create(toSeconds().multiply(BigDecimal.valueOf(multiplicand)));
958      }
959 
960     /**
961      * Returns a copy of this duration divided by the specified value.
962      * <p>
963      * This instance is immutable and unaffected by this method call.
964      *
965      * @param divisor  the value to divide the duration by, positive or negative, not zero
966      * @return a {@code Duration} based on this duration divided by the specified divisor, not null
967      * @throws ArithmeticException if the divisor is zero or if numeric overflow occurs
968      */
dividedBy(long divisor)969     public Duration dividedBy(long divisor) {
970         if (divisor == 0) {
971             throw new ArithmeticException("Cannot divide by zero");
972         }
973         if (divisor == 1) {
974             return this;
975         }
976         return create(toSeconds().divide(BigDecimal.valueOf(divisor), RoundingMode.DOWN));
977      }
978 
979     /**
980      * Converts this duration to the total length in seconds and
981      * fractional nanoseconds expressed as a {@code BigDecimal}.
982      *
983      * @return the total length of the duration in seconds, with a scale of 9, not null
984      */
toSeconds()985     private BigDecimal toSeconds() {
986         return BigDecimal.valueOf(seconds).add(BigDecimal.valueOf(nanos, 9));
987     }
988 
989     /**
990      * Creates an instance of {@code Duration} from a number of seconds.
991      *
992      * @param seconds  the number of seconds, up to scale 9, positive or negative
993      * @return a {@code Duration}, not null
994      * @throws ArithmeticException if numeric overflow occurs
995      */
create(BigDecimal seconds)996     private static Duration create(BigDecimal seconds) {
997         BigInteger nanos = seconds.movePointRight(9).toBigIntegerExact();
998         BigInteger[] divRem = nanos.divideAndRemainder(BI_NANOS_PER_SECOND);
999         if (divRem[0].bitLength() > 63) {
1000             throw new ArithmeticException("Exceeds capacity of Duration: " + nanos);
1001         }
1002         return ofSeconds(divRem[0].longValue(), divRem[1].intValue());
1003     }
1004 
1005     //-----------------------------------------------------------------------
1006     /**
1007      * Returns a copy of this duration with the length negated.
1008      * <p>
1009      * This method swaps the sign of the total length of this duration.
1010      * For example, {@code PT1.3S} will be returned as {@code PT-1.3S}.
1011      * <p>
1012      * This instance is immutable and unaffected by this method call.
1013      *
1014      * @return a {@code Duration} based on this duration with the amount negated, not null
1015      * @throws ArithmeticException if numeric overflow occurs
1016      */
negated()1017     public Duration negated() {
1018         return multipliedBy(-1);
1019     }
1020 
1021     /**
1022      * Returns a copy of this duration with a positive length.
1023      * <p>
1024      * This method returns a positive duration by effectively removing the sign from any negative total length.
1025      * For example, {@code PT-1.3S} will be returned as {@code PT1.3S}.
1026      * <p>
1027      * This instance is immutable and unaffected by this method call.
1028      *
1029      * @return a {@code Duration} based on this duration with an absolute length, not null
1030      * @throws ArithmeticException if numeric overflow occurs
1031      */
abs()1032     public Duration abs() {
1033         return isNegative() ? negated() : this;
1034     }
1035 
1036     //-------------------------------------------------------------------------
1037     /**
1038      * Adds this duration to the specified temporal object.
1039      * <p>
1040      * This returns a temporal object of the same observable type as the input
1041      * with this duration added.
1042      * <p>
1043      * In most cases, it is clearer to reverse the calling pattern by using
1044      * {@link Temporal#plus(TemporalAmount)}.
1045      * <pre>
1046      *   // these two lines are equivalent, but the second approach is recommended
1047      *   dateTime = thisDuration.addTo(dateTime);
1048      *   dateTime = dateTime.plus(thisDuration);
1049      * </pre>
1050      * <p>
1051      * The calculation will add the seconds, then nanos.
1052      * Only non-zero amounts will be added.
1053      * <p>
1054      * This instance is immutable and unaffected by this method call.
1055      *
1056      * @param temporal  the temporal object to adjust, not null
1057      * @return an object of the same type with the adjustment made, not null
1058      * @throws DateTimeException if unable to add
1059      * @throws ArithmeticException if numeric overflow occurs
1060      */
1061     @Override
addTo(Temporal temporal)1062     public Temporal addTo(Temporal temporal) {
1063         if (seconds != 0) {
1064             temporal = temporal.plus(seconds, SECONDS);
1065         }
1066         if (nanos != 0) {
1067             temporal = temporal.plus(nanos, NANOS);
1068         }
1069         return temporal;
1070     }
1071 
1072     /**
1073      * Subtracts this duration from the specified temporal object.
1074      * <p>
1075      * This returns a temporal object of the same observable type as the input
1076      * with this duration subtracted.
1077      * <p>
1078      * In most cases, it is clearer to reverse the calling pattern by using
1079      * {@link Temporal#minus(TemporalAmount)}.
1080      * <pre>
1081      *   // these two lines are equivalent, but the second approach is recommended
1082      *   dateTime = thisDuration.subtractFrom(dateTime);
1083      *   dateTime = dateTime.minus(thisDuration);
1084      * </pre>
1085      * <p>
1086      * The calculation will subtract the seconds, then nanos.
1087      * Only non-zero amounts will be added.
1088      * <p>
1089      * This instance is immutable and unaffected by this method call.
1090      *
1091      * @param temporal  the temporal object to adjust, not null
1092      * @return an object of the same type with the adjustment made, not null
1093      * @throws DateTimeException if unable to subtract
1094      * @throws ArithmeticException if numeric overflow occurs
1095      */
1096     @Override
subtractFrom(Temporal temporal)1097     public Temporal subtractFrom(Temporal temporal) {
1098         if (seconds != 0) {
1099             temporal = temporal.minus(seconds, SECONDS);
1100         }
1101         if (nanos != 0) {
1102             temporal = temporal.minus(nanos, NANOS);
1103         }
1104         return temporal;
1105     }
1106 
1107     //-----------------------------------------------------------------------
1108     /**
1109      * Gets the number of days in this duration.
1110      * <p>
1111      * This returns the total number of days in the duration by dividing the
1112      * number of seconds by 86400.
1113      * This is based on the standard definition of a day as 24 hours.
1114      * <p>
1115      * This instance is immutable and unaffected by this method call.
1116      *
1117      * @return the number of days in the duration, may be negative
1118      */
toDays()1119     public long toDays() {
1120         return seconds / SECONDS_PER_DAY;
1121     }
1122 
1123     /**
1124      * Gets the number of hours in this duration.
1125      * <p>
1126      * This returns the total number of hours in the duration by dividing the
1127      * number of seconds by 3600.
1128      * <p>
1129      * This instance is immutable and unaffected by this method call.
1130      *
1131      * @return the number of hours in the duration, may be negative
1132      */
toHours()1133     public long toHours() {
1134         return seconds / SECONDS_PER_HOUR;
1135     }
1136 
1137     /**
1138      * Gets the number of minutes in this duration.
1139      * <p>
1140      * This returns the total number of minutes in the duration by dividing the
1141      * number of seconds by 60.
1142      * <p>
1143      * This instance is immutable and unaffected by this method call.
1144      *
1145      * @return the number of minutes in the duration, may be negative
1146      */
toMinutes()1147     public long toMinutes() {
1148         return seconds / SECONDS_PER_MINUTE;
1149     }
1150 
1151     /**
1152      * Converts this duration to the total length in milliseconds.
1153      * <p>
1154      * If this duration is too large to fit in a {@code long} milliseconds, then an
1155      * exception is thrown.
1156      * <p>
1157      * If this duration has greater than millisecond precision, then the conversion
1158      * will drop any excess precision information as though the amount in nanoseconds
1159      * was subject to integer division by one million.
1160      *
1161      * @return the total length of the duration in milliseconds
1162      * @throws ArithmeticException if numeric overflow occurs
1163      */
toMillis()1164     public long toMillis() {
1165         long millis = Math.multiplyExact(seconds, 1000);
1166         millis = Math.addExact(millis, nanos / 1000_000);
1167         return millis;
1168     }
1169 
1170     /**
1171      * Converts this duration to the total length in nanoseconds expressed as a {@code long}.
1172      * <p>
1173      * If this duration is too large to fit in a {@code long} nanoseconds, then an
1174      * exception is thrown.
1175      *
1176      * @return the total length of the duration in nanoseconds
1177      * @throws ArithmeticException if numeric overflow occurs
1178      */
toNanos()1179     public long toNanos() {
1180         long totalNanos = Math.multiplyExact(seconds, NANOS_PER_SECOND);
1181         totalNanos = Math.addExact(totalNanos, nanos);
1182         return totalNanos;
1183     }
1184 
1185     //-----------------------------------------------------------------------
1186     /**
1187      * Compares this duration to the specified {@code Duration}.
1188      * <p>
1189      * The comparison is based on the total length of the durations.
1190      * It is "consistent with equals", as defined by {@link Comparable}.
1191      *
1192      * @param otherDuration  the other duration to compare to, not null
1193      * @return the comparator value, negative if less, positive if greater
1194      */
1195     @Override
compareTo(Duration otherDuration)1196     public int compareTo(Duration otherDuration) {
1197         int cmp = Long.compare(seconds, otherDuration.seconds);
1198         if (cmp != 0) {
1199             return cmp;
1200         }
1201         return nanos - otherDuration.nanos;
1202     }
1203 
1204     //-----------------------------------------------------------------------
1205     /**
1206      * Checks if this duration is equal to the specified {@code Duration}.
1207      * <p>
1208      * The comparison is based on the total length of the durations.
1209      *
1210      * @param otherDuration  the other duration, null returns false
1211      * @return true if the other duration is equal to this one
1212      */
1213     @Override
equals(Object otherDuration)1214     public boolean equals(Object otherDuration) {
1215         if (this == otherDuration) {
1216             return true;
1217         }
1218         if (otherDuration instanceof Duration) {
1219             Duration other = (Duration) otherDuration;
1220             return this.seconds == other.seconds &&
1221                    this.nanos == other.nanos;
1222         }
1223         return false;
1224     }
1225 
1226     /**
1227      * A hash code for this duration.
1228      *
1229      * @return a suitable hash code
1230      */
1231     @Override
hashCode()1232     public int hashCode() {
1233         return ((int) (seconds ^ (seconds >>> 32))) + (51 * nanos);
1234     }
1235 
1236     //-----------------------------------------------------------------------
1237     /**
1238      * A string representation of this duration using ISO-8601 seconds
1239      * based representation, such as {@code PT8H6M12.345S}.
1240      * <p>
1241      * The format of the returned string will be {@code PTnHnMnS}, where n is
1242      * the relevant hours, minutes or seconds part of the duration.
1243      * Any fractional seconds are placed after a decimal point i the seconds section.
1244      * If a section has a zero value, it is omitted.
1245      * The hours, minutes and seconds will all have the same sign.
1246      * <p>
1247      * Examples:
1248      * <pre>
1249      *    "20.345 seconds"                 -- "PT20.345S
1250      *    "15 minutes" (15 * 60 seconds)   -- "PT15M"
1251      *    "10 hours" (10 * 3600 seconds)   -- "PT10H"
1252      *    "2 days" (2 * 86400 seconds)     -- "PT48H"
1253      * </pre>
1254      * Note that multiples of 24 hours are not output as days to avoid confusion
1255      * with {@code Period}.
1256      *
1257      * @return an ISO-8601 representation of this duration, not null
1258      */
1259     @Override
toString()1260     public String toString() {
1261         if (this == ZERO) {
1262             return "PT0S";
1263         }
1264         long hours = seconds / SECONDS_PER_HOUR;
1265         int minutes = (int) ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
1266         int secs = (int) (seconds % SECONDS_PER_MINUTE);
1267         StringBuilder buf = new StringBuilder(24);
1268         buf.append("PT");
1269         if (hours != 0) {
1270             buf.append(hours).append('H');
1271         }
1272         if (minutes != 0) {
1273             buf.append(minutes).append('M');
1274         }
1275         if (secs == 0 && nanos == 0 && buf.length() > 2) {
1276             return buf.toString();
1277         }
1278         if (secs < 0 && nanos > 0) {
1279             if (secs == -1) {
1280                 buf.append("-0");
1281             } else {
1282                 buf.append(secs + 1);
1283             }
1284         } else {
1285             buf.append(secs);
1286         }
1287         if (nanos > 0) {
1288             int pos = buf.length();
1289             if (secs < 0) {
1290                 buf.append(2 * NANOS_PER_SECOND - nanos);
1291             } else {
1292                 buf.append(nanos + NANOS_PER_SECOND);
1293             }
1294             while (buf.charAt(buf.length() - 1) == '0') {
1295                 buf.setLength(buf.length() - 1);
1296             }
1297             buf.setCharAt(pos, '.');
1298         }
1299         buf.append('S');
1300         return buf.toString();
1301     }
1302 
1303     //-----------------------------------------------------------------------
1304     /**
1305      * Writes the object using a
1306      * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>.
1307      * @serialData
1308      * <pre>
1309      *  out.writeByte(1);  // identifies a Duration
1310      *  out.writeLong(seconds);
1311      *  out.writeInt(nanos);
1312      * </pre>
1313      *
1314      * @return the instance of {@code Ser}, not null
1315      */
writeReplace()1316     private Object writeReplace() {
1317         return new Ser(Ser.DURATION_TYPE, this);
1318     }
1319 
1320     /**
1321      * Defend against malicious streams.
1322      *
1323      * @param s the stream to read
1324      * @throws InvalidObjectException always
1325      */
readObject(ObjectInputStream s)1326     private void readObject(ObjectInputStream s) throws InvalidObjectException {
1327         throw new InvalidObjectException("Deserialization via serialization delegate");
1328     }
1329 
writeExternal(DataOutput out)1330     void writeExternal(DataOutput out) throws IOException {
1331         out.writeLong(seconds);
1332         out.writeInt(nanos);
1333     }
1334 
readExternal(DataInput in)1335     static Duration readExternal(DataInput in) throws IOException {
1336         long seconds = in.readLong();
1337         int nanos = in.readInt();
1338         return Duration.ofSeconds(seconds, nanos);
1339     }
1340 
1341 }
1342