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