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