001/*
002 * Copyright (c) 2007-2013, Stephen Colebourne & Michael Nascimento Santos
003 *
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions are met:
008 *
009 *  * Redistributions of source code must retain the above copyright notice,
010 *    this list of conditions and the following disclaimer.
011 *
012 *  * Redistributions in binary form must reproduce the above copyright notice,
013 *    this list of conditions and the following disclaimer in the documentation
014 *    and/or other materials provided with the distribution.
015 *
016 *  * Neither the name of JSR-310 nor the names of its contributors
017 *    may be used to endorse or promote products derived from this software
018 *    without specific prior written permission.
019 *
020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031 */
032package org.threeten.bp;
033
034import static org.threeten.bp.LocalTime.SECONDS_PER_DAY;
035import static org.threeten.bp.temporal.ChronoField.INSTANT_SECONDS;
036import static org.threeten.bp.temporal.ChronoField.NANO_OF_SECOND;
037import static org.threeten.bp.temporal.ChronoUnit.DAYS;
038
039import java.io.DataInput;
040import java.io.DataOutput;
041import java.io.IOException;
042import java.io.InvalidObjectException;
043import java.io.ObjectStreamException;
044import java.io.Serializable;
045import java.math.BigDecimal;
046import java.math.BigInteger;
047import java.math.RoundingMode;
048import java.util.Objects;
049
050import org.threeten.bp.format.DateTimeParseException;
051import org.threeten.bp.jdk8.Jdk8Methods;
052import org.threeten.bp.temporal.ChronoField;
053import org.threeten.bp.temporal.ChronoUnit;
054import org.threeten.bp.temporal.Temporal;
055import org.threeten.bp.temporal.TemporalAccessor;
056import org.threeten.bp.temporal.TemporalAdder;
057import org.threeten.bp.temporal.TemporalSubtractor;
058import org.threeten.bp.temporal.TemporalUnit;
059
060/**
061 * A duration between two instants on the time-line.
062 * <p>
063 * This class models a duration of time and is not tied to any instant.
064 * The model is of a directed duration, meaning that the duration may be negative.
065 * <p>
066 * A physical duration could be of infinite length.
067 * For practicality, the duration is stored with constraints similar to {@link Instant}.
068 * The duration uses nanosecond resolution with a maximum value of the seconds that can
069 * be held in a {@code long}. This is greater than the current estimated age of the universe.
070 * <p>
071 * The range of a duration requires the storage of a number larger than a {@code long}.
072 * To achieve this, the class stores a {@code long} representing seconds and an {@code int}
073 * representing nanosecond-of-second, which will always be between 0 and 999,999,999.
074 * <p>
075 * The duration is measured in "seconds", but these are not necessarily identical to
076 * the scientific "SI second" definition based on atomic clocks.
077 * This difference only impacts durations measured near a leap-second and should not affect
078 * most applications.
079 * See {@link Instant} for a discussion as to the meaning of the second and time-scales.
080 *
081 * <h3>Specification for implementors</h3>
082 * This class is immutable and thread-safe.
083 */
084public final class Duration
085        implements TemporalAdder, TemporalSubtractor, Comparable<Duration>, Serializable {
086
087    /**
088     * Constant for a duration of zero.
089     */
090    public static final Duration ZERO = new Duration(0, 0);
091    /**
092     * Serialization version.
093     */
094    private static final long serialVersionUID = 3078945930695997490L;
095    /**
096     * Constant for nanos per second.
097     */
098    private static final int NANOS_PER_SECOND = 1000_000_000;
099    /**
100     * Constant for nanos per second.
101     */
102    private static final BigInteger BI_NANOS_PER_SECOND = BigInteger.valueOf(NANOS_PER_SECOND);
103
104    /**
105     * The number of seconds in the duration.
106     */
107    private final long seconds;
108    /**
109     * The number of nanoseconds in the duration, expressed as a fraction of the
110     * number of seconds. This is always positive, and never exceeds 999,999,999.
111     */
112    private final int nanos;
113
114    //-----------------------------------------------------------------------
115    /**
116     * Obtains an instance of {@code Duration} from a number of seconds.
117     * <p>
118     * The nanosecond in second field is set to zero.
119     *
120     * @param seconds  the number of seconds, positive or negative
121     * @return a {@code Duration}, not null
122     */
123    public static Duration ofSeconds(long seconds) {
124        return create(seconds, 0);
125    }
126
127    /**
128     * Obtains an instance of {@code Duration} from a number of seconds
129     * and an adjustment in nanoseconds.
130     * <p>
131     * This method allows an arbitrary number of nanoseconds to be passed in.
132     * The factory will alter the values of the second and nanosecond in order
133     * to ensure that the stored nanosecond is in the range 0 to 999,999,999.
134     * For example, the following will result in the exactly the same duration:
135     * <pre>
136     *  Duration.ofSeconds(3, 1);
137     *  Duration.ofSeconds(4, -999_999_999);
138     *  Duration.ofSeconds(2, 1000_000_001);
139     * </pre>
140     *
141     * @param seconds  the number of seconds, positive or negative
142     * @param nanoAdjustment  the nanosecond adjustment to the number of seconds, positive or negative
143     * @return a {@code Duration}, not null
144     * @throws ArithmeticException if the adjustment causes the seconds to exceed the capacity of {@code Duration}
145     */
146    public static Duration ofSeconds(long seconds, long nanoAdjustment) {
147        long secs = Jdk8Methods.safeAdd(seconds, Jdk8Methods.floorDiv(nanoAdjustment, NANOS_PER_SECOND));
148        int nos = Jdk8Methods.floorMod(nanoAdjustment, NANOS_PER_SECOND);
149        return create(secs, nos);
150    }
151
152    //-----------------------------------------------------------------------
153    /**
154     * Obtains an instance of {@code Duration} from a number of milliseconds.
155     * <p>
156     * The seconds and nanoseconds are extracted from the specified milliseconds.
157     *
158     * @param millis  the number of milliseconds, positive or negative
159     * @return a {@code Duration}, not null
160     */
161    public static Duration ofMillis(long millis) {
162        long secs = millis / 1000;
163        int mos = (int) (millis % 1000);
164        if (mos < 0) {
165            mos += 1000;
166            secs--;
167        }
168        return create(secs, mos * 1000_000);
169    }
170
171    //-----------------------------------------------------------------------
172    /**
173     * Obtains an instance of {@code Duration} from a number of nanoseconds.
174     * <p>
175     * The seconds and nanoseconds are extracted from the specified nanoseconds.
176     *
177     * @param nanos  the number of nanoseconds, positive or negative
178     * @return a {@code Duration}, not null
179     */
180    public static Duration ofNanos(long nanos) {
181        long secs = nanos / NANOS_PER_SECOND;
182        int nos = (int) (nanos % NANOS_PER_SECOND);
183        if (nos < 0) {
184            nos += NANOS_PER_SECOND;
185            secs--;
186        }
187        return create(secs, nos);
188    }
189
190    //-----------------------------------------------------------------------
191    /**
192     * Obtains an instance of {@code Duration} from a number of standard length 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     */
202    public static Duration ofMinutes(long minutes) {
203        return create(Jdk8Methods.safeMultiply(minutes, 60), 0);
204    }
205
206    /**
207     * Obtains an instance of {@code Duration} from a number of standard length hours.
208     * <p>
209     * The seconds are calculated based on the standard definition of an hour,
210     * where each hour is 3600 seconds.
211     * The nanosecond in second field is set to zero.
212     *
213     * @param hours  the number of hours, positive or negative
214     * @return a {@code Duration}, not null
215     * @throws ArithmeticException if the input hours exceeds the capacity of {@code Duration}
216     */
217    public static Duration ofHours(long hours) {
218        return create(Jdk8Methods.safeMultiply(hours, 3600), 0);
219    }
220
221    /**
222     * Obtains an instance of {@code Duration} from a number of standard 24 hour days.
223     * <p>
224     * The seconds are calculated based on the standard definition of a day,
225     * where each day is 86400 seconds which implies a 24 hour day.
226     * The nanosecond in second field is set to zero.
227     *
228     * @param days  the number of days, positive or negative
229     * @return a {@code Duration}, not null
230     * @throws ArithmeticException if the input days exceeds the capacity of {@code Duration}
231     */
232    public static Duration ofDays(long days) {
233        return create(Jdk8Methods.safeMultiply(days, 86400), 0);
234    }
235
236    //-----------------------------------------------------------------------
237    /**
238     * Obtains an instance of {@code Duration} from a duration in the specified unit.
239     * <p>
240     * The parameters represent the two parts of a phrase like '6 Hours'. For example:
241     * <pre>
242     *  Duration.of(3, SECONDS);
243     *  Duration.of(465, HOURS);
244     * </pre>
245     * Only a subset of units are accepted by this method.
246     * The unit must either have an {@link TemporalUnit#isDurationEstimated() exact duration} or
247     * be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception.
248     *
249     * @param amount  the amount of the duration, measured in terms of the unit, positive or negative
250     * @param unit  the unit that the duration is measured in, must have an exact duration, not null
251     * @return a {@code Duration}, not null
252     * @throws DateTimeException if the period unit has an estimated duration
253     * @throws ArithmeticException if a numeric overflow occurs
254     */
255    public static Duration of(long amount, TemporalUnit unit) {
256        return ZERO.plus(amount, unit);
257    }
258
259    //-----------------------------------------------------------------------
260    /**
261     * Obtains an instance of {@code Duration} representing the duration between two instants.
262     * <p>
263     * A {@code Duration} represents a directed distance between two points on the time-line.
264     * As such, this method will return a negative duration if the end is before the start.
265     * To guarantee to obtain a positive duration call {@link #abs()} on the result of this factory.
266     *
267     * @param startInclusive  the start instant, inclusive, not null
268     * @param endExclusive  the end instant, exclusive, not null
269     * @return a {@code Duration}, not null
270     * @throws ArithmeticException if the calculation exceeds the capacity of {@code Duration}
271     */
272    public static Duration between(TemporalAccessor startInclusive, TemporalAccessor endExclusive) {
273        long secs = Jdk8Methods.safeSubtract(endExclusive.getLong(INSTANT_SECONDS), startInclusive.getLong(INSTANT_SECONDS));
274        long nanos = endExclusive.getLong(NANO_OF_SECOND) - startInclusive.getLong(NANO_OF_SECOND);
275        secs = Jdk8Methods.safeAdd(secs, Jdk8Methods.floorDiv(nanos, NANOS_PER_SECOND));
276        nanos = Jdk8Methods.floorMod(nanos, NANOS_PER_SECOND);
277        return create(secs, (int) nanos);  // safe from overflow
278    }
279
280    //-----------------------------------------------------------------------
281    /**
282     * Obtains an instance of {@code Duration} by parsing a text string.
283     * <p>
284     * This will parse the string produced by {@link #toString()} which is
285     * the ISO-8601 format {@code PTnS} where {@code n} is
286     * the number of seconds with optional decimal part.
287     * The number must consist of ASCII numerals.
288     * There must only be a negative sign at the start of the number and it can
289     * only be present if the value is less than zero.
290     * There must be at least one digit before any decimal point.
291     * There must be between 1 and 9 inclusive digits after any decimal point.
292     * The letters (P, T and S) will be accepted in upper or lower case.
293     * The decimal point may be either a dot or a comma.
294     *
295     * @param text  the text to parse, not null
296     * @return a {@code Duration}, not null
297     * @throws DateTimeParseException if the text cannot be parsed to a {@code Duration}
298     */
299    public static Duration parse(final CharSequence text) {
300        Objects.requireNonNull(text, "text");
301        int len = text.length();
302        if (len < 4 ||
303                (text.charAt(0) != 'P' && text.charAt(0) != 'p') ||
304                (text.charAt(1) != 'T' && text.charAt(1) != 't') ||
305                (text.charAt(len - 1) != 'S' && text.charAt(len - 1) != 's') ||
306                (len == 5 && text.charAt(2) == '-' && text.charAt(3) == '0')) {
307            throw new DateTimeParseException("Duration could not be parsed: " + text, text, 0);
308        }
309        String numberText = text.subSequence(2, len - 1).toString().replace(',', '.');
310        if (numberText.charAt(0) == '+') {
311            throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2);
312        }
313        int dot = numberText.indexOf('.');
314        try {
315            if (dot == -1) {
316                // no decimal places
317                if (numberText.startsWith("-0")) {
318                    throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2);
319                }
320                return create(Long.parseLong(numberText), 0);
321            }
322            // decimal places
323            boolean negative = false;
324            if (numberText.charAt(0) == '-') {
325                negative = true;
326            }
327            long secs = Long.parseLong(numberText.substring(0, dot));
328            numberText = numberText.substring(dot + 1);
329            len = numberText.length();
330            if (len == 0 || len > 9 || numberText.charAt(0) == '-' || numberText.charAt(0) == '+') {
331                throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2);
332            }
333            int nanos = Integer.parseInt(numberText);
334            switch (len) {
335                case 1:
336                    nanos *= 100000000;
337                    break;
338                case 2:
339                    nanos *= 10000000;
340                    break;
341                case 3:
342                    nanos *= 1000000;
343                    break;
344                case 4:
345                    nanos *= 100000;
346                    break;
347                case 5:
348                    nanos *= 10000;
349                    break;
350                case 6:
351                    nanos *= 1000;
352                    break;
353                case 7:
354                    nanos *= 100;
355                    break;
356                case 8:
357                    nanos *= 10;
358                    break;
359            }
360            return negative ? ofSeconds(secs, -nanos) : create(secs, nanos);
361
362        } catch (ArithmeticException | NumberFormatException ex) {
363            throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2, ex);
364        }
365    }
366
367    //-----------------------------------------------------------------------
368    /**
369     * Obtains an instance of {@code Duration} using seconds and nanoseconds.
370     *
371     * @param seconds  the length of the duration in seconds, positive or negative
372     * @param nanoAdjustment  the nanosecond adjustment within the second, from 0 to 999,999,999
373     */
374    private static Duration create(long seconds, int nanoAdjustment) {
375        if ((seconds | nanoAdjustment) == 0) {
376            return ZERO;
377        }
378        return new Duration(seconds, nanoAdjustment);
379    }
380
381    /**
382     * Constructs an instance of {@code Duration} using seconds and nanoseconds.
383     *
384     * @param seconds  the length of the duration in seconds, positive or negative
385     * @param nanos  the nanoseconds within the second, from 0 to 999,999,999
386     */
387    private Duration(long seconds, int nanos) {
388        super();
389        this.seconds = seconds;
390        this.nanos = nanos;
391    }
392
393    //-----------------------------------------------------------------------
394    /**
395     * Checks if this duration is zero length.
396     * <p>
397     * A {@code Duration} represents a directed distance between two points on
398     * the time-line and can therefore be positive, zero or negative.
399     * This method checks whether the length is zero.
400     *
401     * @return true if this duration has a total length equal to zero
402     */
403    public boolean isZero() {
404        return (seconds | nanos) == 0;
405    }
406
407    /**
408     * Checks if this duration is positive, excluding zero.
409     * <p>
410     * A {@code Duration} represents a directed distance between two points on
411     * the time-line and can therefore be positive, zero or negative.
412     * This method checks whether the length is greater than zero.
413     *
414     * @return true if this duration has a total length greater than zero
415     */
416    public boolean isPositive() {
417        return seconds >= 0 && ((seconds | nanos) != 0);
418    }
419
420    /**
421     * Checks if this duration is negative, excluding zero.
422     * <p>
423     * A {@code Duration} represents a directed distance between two points on
424     * the time-line and can therefore be positive, zero or negative.
425     * This method checks whether the length is less than zero.
426     *
427     * @return true if this duration has a total length less than zero
428     */
429    public boolean isNegative() {
430        return seconds < 0;
431    }
432
433    //-----------------------------------------------------------------------
434    /**
435     * Gets the number of seconds in this duration.
436     * <p>
437     * The length of the duration is stored using two fields - seconds and nanoseconds.
438     * The nanoseconds part is a value from 0 to 999,999,999 that is an adjustment to
439     * the length in seconds.
440     * The total duration is defined by calling this method and {@link #getNano()}.
441     * <p>
442     * A {@code Duration} represents a directed distance between two points on the time-line.
443     * A negative duration is expressed by the negative sign of the seconds part.
444     * A duration of -1 nanosecond is stored as -1 seconds plus 999,999,999 nanoseconds.
445     *
446     * @return the whole seconds part of the length of the duration, positive or negative
447     */
448    public long getSeconds() {
449        return seconds;
450    }
451
452    /**
453     * Gets the number of nanoseconds within the second in this duration.
454     * <p>
455     * The length of the duration is stored using two fields - seconds and nanoseconds.
456     * The nanoseconds part is a value from 0 to 999,999,999 that is an adjustment to
457     * the length in seconds.
458     * The total duration is defined by calling this method and {@link #getSeconds()}.
459     * <p>
460     * A {@code Duration} represents a directed distance between two points on the time-line.
461     * A negative duration is expressed by the negative sign of the seconds part.
462     * A duration of -1 nanosecond is stored as -1 seconds plus 999,999,999 nanoseconds.
463     *
464     * @return the nanoseconds within the second part of the length of the duration, from 0 to 999,999,999
465     */
466    public int getNano() {
467        return nanos;
468    }
469
470    //-----------------------------------------------------------------------
471    /**
472     * Returns a copy of this duration with the specified duration added.
473     * <p>
474     * This instance is immutable and unaffected by this method call.
475     *
476     * @param duration  the duration to add, positive or negative, not null
477     * @return a {@code Duration} based on this duration with the specified duration added, not null
478     * @throws ArithmeticException if numeric overflow occurs
479     */
480    public Duration plus(Duration duration) {
481        return plus(duration.getSeconds(), duration.getNano());
482     }
483
484    /**
485     * Returns a copy of this duration with the specified duration added.
486     * <p>
487     * The duration amount is measured in terms of the specified unit.
488     * Only a subset of units are accepted by this method.
489     * The unit must either have an {@link TemporalUnit#isDurationEstimated() exact duration} or
490     * be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception.
491     * <p>
492     * This instance is immutable and unaffected by this method call.
493     *
494     * @param amountToAdd  the amount of the period, measured in terms of the unit, positive or negative
495     * @param unit  the unit that the period is measured in, must have an exact duration, not null
496     * @return a {@code Duration} based on this duration with the specified duration added, not null
497     * @throws ArithmeticException if numeric overflow occurs
498     */
499    public Duration plus(long amountToAdd, TemporalUnit unit) {
500        Objects.requireNonNull(unit, "unit");
501        if (unit == DAYS) {
502            return plus(Jdk8Methods.safeMultiply(amountToAdd, SECONDS_PER_DAY), 0);
503        }
504        if (unit.isDurationEstimated()) {
505            throw new DateTimeException("Unit must not have an estimated duration");
506        }
507        if (amountToAdd == 0) {
508            return this;
509        }
510        if (unit instanceof ChronoUnit) {
511            switch ((ChronoUnit) unit) {
512                case NANOS: return plusNanos(amountToAdd);
513                case MICROS: return plusSeconds((amountToAdd / (1000_000L * 1000)) * 1000).plusNanos((amountToAdd % (1000_000L * 1000)) * 1000);
514                case MILLIS: return plusMillis(amountToAdd);
515                case SECONDS: return plusSeconds(amountToAdd);
516            }
517            return plusSeconds(Jdk8Methods.safeMultiply(unit.getDuration().seconds, amountToAdd));
518        }
519        Duration duration = unit.getDuration().multipliedBy(amountToAdd);
520        return plusSeconds(duration.getSeconds()).plusNanos(duration.getNano());
521    }
522
523    //-----------------------------------------------------------------------
524    /**
525     * Returns a copy of this duration with the specified duration in seconds added.
526     * <p>
527     * This instance is immutable and unaffected by this method call.
528     *
529     * @param secondsToAdd  the seconds to add, positive or negative
530     * @return a {@code Duration} based on this duration with the specified seconds added, not null
531     * @throws ArithmeticException if numeric overflow occurs
532     */
533    public Duration plusSeconds(long secondsToAdd) {
534        return plus(secondsToAdd, 0);
535    }
536
537    /**
538     * Returns a copy of this duration with the specified duration in milliseconds added.
539     * <p>
540     * This instance is immutable and unaffected by this method call.
541     *
542     * @param millisToAdd  the milliseconds to add, positive or negative
543     * @return a {@code Duration} based on this duration with the specified milliseconds added, not null
544     * @throws ArithmeticException if numeric overflow occurs
545     */
546    public Duration plusMillis(long millisToAdd) {
547        return plus(millisToAdd / 1000, (millisToAdd % 1000) * 1000_000);
548    }
549
550    /**
551     * Returns a copy of this duration with the specified duration in nanoseconds added.
552     * <p>
553     * This instance is immutable and unaffected by this method call.
554     *
555     * @param nanosToAdd  the nanoseconds to add, positive or negative
556     * @return a {@code Duration} based on this duration with the specified nanoseconds added, not null
557     * @throws ArithmeticException if numeric overflow occurs
558     */
559    public Duration plusNanos(long nanosToAdd) {
560        return plus(0, nanosToAdd);
561    }
562
563    /**
564     * Returns a copy of this duration with the specified duration added.
565     * <p>
566     * This instance is immutable and unaffected by this method call.
567     *
568     * @param secondsToAdd  the seconds to add, positive or negative
569     * @param nanosToAdd  the nanos to add, positive or negative
570     * @return a {@code Duration} based on this duration with the specified seconds added, not null
571     * @throws ArithmeticException if numeric overflow occurs
572     */
573    private Duration plus(long secondsToAdd, long nanosToAdd) {
574        if ((secondsToAdd | nanosToAdd) == 0) {
575            return this;
576        }
577        long epochSec = Jdk8Methods.safeAdd(seconds, secondsToAdd);
578        epochSec = Jdk8Methods.safeAdd(epochSec, nanosToAdd / NANOS_PER_SECOND);
579        nanosToAdd = nanosToAdd % NANOS_PER_SECOND;
580        long nanoAdjustment = nanos + nanosToAdd;  // safe int+NANOS_PER_SECOND
581        return ofSeconds(epochSec, nanoAdjustment);
582    }
583
584    //-----------------------------------------------------------------------
585    /**
586     * Returns a copy of this duration with the specified duration subtracted.
587     * <p>
588     * This instance is immutable and unaffected by this method call.
589     *
590     * @param duration  the duration to subtract, positive or negative, not null
591     * @return a {@code Duration} based on this duration with the specified duration subtracted, not null
592     * @throws ArithmeticException if numeric overflow occurs
593     */
594    public Duration minus(Duration duration) {
595        long secsToSubtract = duration.getSeconds();
596        int nanosToSubtract = duration.getNano();
597        if (secsToSubtract == Long.MIN_VALUE) {
598            return plus(Long.MAX_VALUE, -nanosToSubtract).plus(1, 0);
599        }
600        return plus(-secsToSubtract, -nanosToSubtract);
601     }
602
603    /**
604     * Returns a copy of this duration with the specified duration subtracted.
605     * <p>
606     * The duration amount is measured in terms of the specified unit.
607     * Only a subset of units are accepted by this method.
608     * The unit must either have an {@link TemporalUnit#isDurationEstimated() exact duration} or
609     * be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception.
610     * <p>
611     * This instance is immutable and unaffected by this method call.
612     *
613     * @param amountToSubtract  the amount of the period, measured in terms of the unit, positive or negative
614     * @param unit  the unit that the period is measured in, must have an exact duration, not null
615     * @return a {@code Duration} based on this duration with the specified duration subtracted, not null
616     * @throws ArithmeticException if numeric overflow occurs
617     */
618    public Duration minus(long amountToSubtract, TemporalUnit unit) {
619        return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
620    }
621
622    //-----------------------------------------------------------------------
623    /**
624     * Returns a copy of this duration with the specified duration in seconds subtracted.
625     * <p>
626     * This instance is immutable and unaffected by this method call.
627     *
628     * @param secondsToSubtract  the seconds to subtract, positive or negative
629     * @return a {@code Duration} based on this duration with the specified seconds subtracted, not null
630     * @throws ArithmeticException if numeric overflow occurs
631     */
632    public Duration minusSeconds(long secondsToSubtract) {
633        return (secondsToSubtract == Long.MIN_VALUE ? plusSeconds(Long.MAX_VALUE).plusSeconds(1) : plusSeconds(-secondsToSubtract));
634    }
635
636    /**
637     * Returns a copy of this duration with the specified duration in milliseconds subtracted.
638     * <p>
639     * This instance is immutable and unaffected by this method call.
640     *
641     * @param millisToSubtract  the milliseconds to subtract, positive or negative
642     * @return a {@code Duration} based on this duration with the specified milliseconds subtracted, not null
643     * @throws ArithmeticException if numeric overflow occurs
644     */
645    public Duration minusMillis(long millisToSubtract) {
646        return (millisToSubtract == Long.MIN_VALUE ? plusMillis(Long.MAX_VALUE).plusMillis(1) : plusMillis(-millisToSubtract));
647    }
648
649    /**
650     * Returns a copy of this duration with the specified duration in nanoseconds subtracted.
651     * <p>
652     * This instance is immutable and unaffected by this method call.
653     *
654     * @param nanosToSubtract  the nanoseconds to subtract, positive or negative
655     * @return a {@code Duration} based on this duration with the specified nanoseconds subtracted, not null
656     * @throws ArithmeticException if numeric overflow occurs
657     */
658    public Duration minusNanos(long nanosToSubtract) {
659        return (nanosToSubtract == Long.MIN_VALUE ? plusNanos(Long.MAX_VALUE).plusNanos(1) : plusNanos(-nanosToSubtract));
660    }
661
662    //-----------------------------------------------------------------------
663    /**
664     * Returns a copy of this duration multiplied by the scalar.
665     * <p>
666     * This instance is immutable and unaffected by this method call.
667     *
668     * @param multiplicand  the value to multiply the duration by, positive or negative
669     * @return a {@code Duration} based on this duration multiplied by the specified scalar, not null
670     * @throws ArithmeticException if numeric overflow occurs
671     */
672    public Duration multipliedBy(long multiplicand) {
673        if (multiplicand == 0) {
674            return ZERO;
675        }
676        if (multiplicand == 1) {
677            return this;
678        }
679        return create(toSeconds().multiply(BigDecimal.valueOf(multiplicand)));
680     }
681
682    /**
683     * Returns a copy of this duration divided by the specified value.
684     * <p>
685     * This instance is immutable and unaffected by this method call.
686     *
687     * @param divisor  the value to divide the duration by, positive or negative, not zero
688     * @return a {@code Duration} based on this duration divided by the specified divisor, not null
689     * @throws ArithmeticException if the divisor is zero
690     * @throws ArithmeticException if numeric overflow occurs
691     */
692    public Duration dividedBy(long divisor) {
693        if (divisor == 0) {
694            throw new ArithmeticException("Cannot divide by zero");
695        }
696        if (divisor == 1) {
697            return this;
698        }
699        return create(toSeconds().divide(BigDecimal.valueOf(divisor), RoundingMode.DOWN));
700     }
701
702    /**
703     * Converts this duration to the total length in seconds and
704     * fractional nanoseconds expressed as a {@code BigDecimal}.
705     *
706     * @return the total length of the duration in seconds, with a scale of 9, not null
707     */
708    private BigDecimal toSeconds() {
709        return BigDecimal.valueOf(seconds).add(BigDecimal.valueOf(nanos, 9));
710    }
711
712    /**
713     * Creates an instance of {@code Duration} from a number of seconds.
714     *
715     * @param seconds  the number of seconds, up to scale 9, positive or negative
716     * @return a {@code Duration}, not null
717     * @throws ArithmeticException if numeric overflow occurs
718     */
719    private static Duration create(BigDecimal seconds) {
720        BigInteger nanos = seconds.movePointRight(9).toBigIntegerExact();
721        BigInteger[] divRem = nanos.divideAndRemainder(BI_NANOS_PER_SECOND);
722        if (divRem[0].bitLength() > 63) {
723            throw new ArithmeticException("Exceeds capacity of Duration: " + nanos);
724        }
725        return ofSeconds(divRem[0].longValue(), divRem[1].intValue());
726    }
727
728    //-----------------------------------------------------------------------
729    /**
730     * Returns a copy of this duration with the length negated.
731     * <p>
732     * This method swaps the sign of the total length of this duration.
733     * For example, {@code PT1.3S} will be returned as {@code PT-1.3S}.
734     * <p>
735     * This instance is immutable and unaffected by this method call.
736     *
737     * @return a {@code Duration} based on this duration with the amount negated, not null
738     * @throws ArithmeticException if numeric overflow occurs
739     */
740    public Duration negated() {
741        return multipliedBy(-1);
742    }
743
744    /**
745     * Returns a copy of this duration with a positive length.
746     * <p>
747     * This method returns a positive duration by effectively removing the sign from any negative total length.
748     * For example, {@code PT-1.3S} will be returned as {@code PT1.3S}.
749     * <p>
750     * This instance is immutable and unaffected by this method call.
751     *
752     * @return a {@code Duration} based on this duration with an absolute length, not null
753     * @throws ArithmeticException if numeric overflow occurs
754     */
755    public Duration abs() {
756        return isNegative() ? negated() : this;
757    }
758
759    //-------------------------------------------------------------------------
760    /**
761     * Adds this duration to the specified temporal object.
762     * <p>
763     * This returns a temporal object of the same observable type as the input
764     * with this duration added.
765     * <p>
766     * In most cases, it is clearer to reverse the calling pattern by using
767     * {@link Temporal#plus(TemporalAdder)}.
768     * <pre>
769     *   // these two lines are equivalent, but the second approach is recommended
770     *   dateTime = thisDuration.addTo(dateTime);
771     *   dateTime = dateTime.plus(thisDuration);
772     * </pre>
773     * <p>
774     * A {@code Duration} can only be added to a {@code Temporal} that
775     * represents an instant and can supply {@link ChronoField#INSTANT_SECONDS}.
776     * <p>
777     * This instance is immutable and unaffected by this method call.
778     *
779     * @param temporal  the temporal object to adjust, not null
780     * @return an object of the same type with the adjustment made, not null
781     * @throws DateTimeException if unable to add
782     * @throws ArithmeticException if numeric overflow occurs
783     */
784    @Override
785    public Temporal addTo(Temporal temporal) {
786        long instantSecs = temporal.getLong(INSTANT_SECONDS);
787        long instantNanos = temporal.getLong(NANO_OF_SECOND);
788        instantSecs = Jdk8Methods.safeAdd(instantSecs, seconds);
789        instantNanos = Jdk8Methods.safeAdd(instantNanos, nanos);
790        instantSecs = Jdk8Methods.safeAdd(instantSecs, Jdk8Methods.floorDiv(instantNanos, NANOS_PER_SECOND));
791        instantNanos = Jdk8Methods.floorMod(instantNanos, NANOS_PER_SECOND);
792        return temporal.with(INSTANT_SECONDS, instantSecs).with(NANO_OF_SECOND, instantNanos);
793    }
794
795    /**
796     * Subtracts this duration from the specified temporal object.
797     * <p>
798     * This returns a temporal object of the same observable type as the input
799     * with this duration subtracted.
800     * <p>
801     * In most cases, it is clearer to reverse the calling pattern by using
802     * {@link Temporal#minus(TemporalSubtractor)}.
803     * <pre>
804     *   // these two lines are equivalent, but the second approach is recommended
805     *   dateTime = thisDuration.subtractFrom(dateTime);
806     *   dateTime = dateTime.minus(thisDuration);
807     * </pre>
808     * <p>
809     * A {@code Duration} can only be subtracted from a {@code Temporal} that
810     * represents an instant and can supply {@link ChronoField#INSTANT_SECONDS}.
811     * <p>
812     * This instance is immutable and unaffected by this method call.
813     *
814     * @param temporal  the temporal object to adjust, not null
815     * @return an object of the same type with the adjustment made, not null
816     * @throws DateTimeException if unable to subtract
817     * @throws ArithmeticException if numeric overflow occurs
818     */
819    @Override
820    public Temporal subtractFrom(Temporal temporal) {
821        long instantSecs = temporal.getLong(INSTANT_SECONDS);
822        long instantNanos = temporal.getLong(NANO_OF_SECOND);
823        instantSecs = Jdk8Methods.safeSubtract(instantSecs, seconds);
824        instantNanos = Jdk8Methods.safeSubtract(instantNanos, nanos);
825        instantSecs = Jdk8Methods.safeAdd(instantSecs, Jdk8Methods.floorDiv(instantNanos, NANOS_PER_SECOND));
826        instantNanos = Jdk8Methods.floorMod(instantNanos, NANOS_PER_SECOND);
827        return temporal.with(INSTANT_SECONDS, instantSecs).with(NANO_OF_SECOND, instantNanos);
828    }
829
830    //-----------------------------------------------------------------------
831    /**
832     * Converts this duration to the total length in milliseconds.
833     * <p>
834     * If this duration is too large to fit in a {@code long} milliseconds, then an
835     * exception is thrown.
836     * <p>
837     * If this duration has greater than millisecond precision, then the conversion
838     * will drop any excess precision information as though the amount in nanoseconds
839     * was subject to integer division by one million.
840     *
841     * @return the total length of the duration in milliseconds
842     * @throws ArithmeticException if numeric overflow occurs
843     */
844    public long toMillis() {
845        long millis = Jdk8Methods.safeMultiply(seconds, 1000);
846        millis = Jdk8Methods.safeAdd(millis, nanos / 1000_000);
847        return millis;
848    }
849
850    /**
851     * Converts this duration to the total length in nanoseconds expressed as a {@code long}.
852     * <p>
853     * If this duration is too large to fit in a {@code long} nanoseconds, then an
854     * exception is thrown.
855     *
856     * @return the total length of the duration in nanoseconds
857     * @throws ArithmeticException if numeric overflow occurs
858     */
859    public long toNanos() {
860        long millis = Jdk8Methods.safeMultiply(seconds, 1000_000_000);
861        millis = Jdk8Methods.safeAdd(millis, nanos);
862        return millis;
863    }
864
865    //-----------------------------------------------------------------------
866    /**
867     * Compares this duration to the specified {@code Duration}.
868     * <p>
869     * The comparison is based on the total length of the durations.
870     * It is "consistent with equals", as defined by {@link Comparable}.
871     *
872     * @param otherDuration  the other duration to compare to, not null
873     * @return the comparator value, negative if less, positive if greater
874     */
875    @Override
876    public int compareTo(Duration otherDuration) {
877        int cmp = Long.compare(seconds, otherDuration.seconds);
878        if (cmp != 0) {
879            return cmp;
880        }
881        return nanos - otherDuration.nanos;
882    }
883
884    /**
885     * Checks if this duration is greater than the specified {@code Duration}.
886     * <p>
887     * The comparison is based on the total length of the durations.
888     *
889     * @param otherDuration  the other duration to compare to, not null
890     * @return true if this duration is greater than the specified duration
891     */
892    public boolean isGreaterThan(Duration otherDuration) {
893        return compareTo(otherDuration) > 0;
894    }
895
896    /**
897     * Checks if this duration is less than the specified {@code Duration}.
898     * <p>
899     * The comparison is based on the total length of the durations.
900     *
901     * @param otherDuration  the other duration to compare to, not null
902     * @return true if this duration is less than the specified duration
903     */
904    public boolean isLessThan(Duration otherDuration) {
905        return compareTo(otherDuration) < 0;
906    }
907
908    //-----------------------------------------------------------------------
909    /**
910     * Checks if this duration is equal to the specified {@code Duration}.
911     * <p>
912     * The comparison is based on the total length of the durations.
913     *
914     * @param otherDuration  the other duration, null returns false
915     * @return true if the other duration is equal to this one
916     */
917    @Override
918    public boolean equals(Object otherDuration) {
919        if (this == otherDuration) {
920            return true;
921        }
922        if (otherDuration instanceof Duration) {
923            Duration other = (Duration) otherDuration;
924            return this.seconds == other.seconds &&
925                   this.nanos == other.nanos;
926        }
927        return false;
928    }
929
930    /**
931     * A hash code for this duration.
932     *
933     * @return a suitable hash code
934     */
935    @Override
936    public int hashCode() {
937        return ((int) (seconds ^ (seconds >>> 32))) + (51 * nanos);
938    }
939
940    //-----------------------------------------------------------------------
941    /**
942     * A string representation of this duration using ISO-8601 seconds
943     * based representation, such as {@code PT12.345S}.
944     * <p>
945     * The format of the returned string will be {@code PTnS} where n is
946     * the seconds and fractional seconds of the duration.
947     *
948     * @return an ISO-8601 representation of this duration, not null
949     */
950    @Override
951    public String toString() {
952        StringBuilder buf = new StringBuilder(24);
953        buf.append("PT");
954        if (seconds < 0 && nanos > 0) {
955            if (seconds == -1) {
956                buf.append("-0");
957            } else {
958                buf.append(seconds + 1);
959            }
960        } else {
961            buf.append(seconds);
962        }
963        if (nanos > 0) {
964            int pos = buf.length();
965            if (seconds < 0) {
966                buf.append(2 * NANOS_PER_SECOND - nanos);
967            } else {
968                buf.append(nanos + NANOS_PER_SECOND);
969            }
970            while (buf.charAt(buf.length() - 1) == '0') {
971                buf.setLength(buf.length() - 1);
972            }
973            buf.setCharAt(pos, '.');
974        }
975        buf.append('S');
976        return buf.toString();
977    }
978
979    //-----------------------------------------------------------------------
980    private Object writeReplace() {
981        return new Ser(Ser.DURATION_TYPE, this);
982    }
983
984    /**
985     * Defend against malicious streams.
986     * @return never
987     * @throws InvalidObjectException always
988     */
989    private Object readResolve() throws ObjectStreamException {
990        throw new InvalidObjectException("Deserialization via serialization delegate");
991    }
992
993    void writeExternal(DataOutput out) throws IOException {
994        out.writeLong(seconds);
995        out.writeInt(nanos);
996    }
997
998    static Duration readExternal(DataInput in) throws IOException {
999        long seconds = in.readLong();
1000        int nanos = in.readInt();
1001        return Duration.ofSeconds(seconds, nanos);
1002    }
1003
1004}