jdk/src/share/classes/java/time/Duration.java
changeset 15658 55b829ca2334
parent 15289 3ac550392e43
child 16852 60207b2b4b42
equal deleted inserted replaced
15657:c588664d547e 15658:55b829ca2334
    59  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    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.
    60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    61  */
    61  */
    62 package java.time;
    62 package java.time;
    63 
    63 
       
    64 import static java.time.LocalTime.NANOS_PER_SECOND;
    64 import static java.time.LocalTime.SECONDS_PER_DAY;
    65 import static java.time.LocalTime.SECONDS_PER_DAY;
    65 import static java.time.temporal.ChronoField.INSTANT_SECONDS;
    66 import static java.time.LocalTime.SECONDS_PER_HOUR;
       
    67 import static java.time.LocalTime.SECONDS_PER_MINUTE;
    66 import static java.time.temporal.ChronoField.NANO_OF_SECOND;
    68 import static java.time.temporal.ChronoField.NANO_OF_SECOND;
    67 import static java.time.temporal.ChronoUnit.DAYS;
    69 import static java.time.temporal.ChronoUnit.DAYS;
       
    70 import static java.time.temporal.ChronoUnit.NANOS;
       
    71 import static java.time.temporal.ChronoUnit.SECONDS;
    68 
    72 
    69 import java.io.DataInput;
    73 import java.io.DataInput;
    70 import java.io.DataOutput;
    74 import java.io.DataOutput;
    71 import java.io.IOException;
    75 import java.io.IOException;
    72 import java.io.InvalidObjectException;
    76 import java.io.InvalidObjectException;
    77 import java.math.RoundingMode;
    81 import java.math.RoundingMode;
    78 import java.time.format.DateTimeParseException;
    82 import java.time.format.DateTimeParseException;
    79 import java.time.temporal.ChronoField;
    83 import java.time.temporal.ChronoField;
    80 import java.time.temporal.ChronoUnit;
    84 import java.time.temporal.ChronoUnit;
    81 import java.time.temporal.Temporal;
    85 import java.time.temporal.Temporal;
    82 import java.time.temporal.TemporalAccessor;
    86 import java.time.temporal.TemporalAmount;
    83 import java.time.temporal.TemporalAdder;
       
    84 import java.time.temporal.TemporalSubtractor;
       
    85 import java.time.temporal.TemporalUnit;
    87 import java.time.temporal.TemporalUnit;
       
    88 import java.util.Arrays;
       
    89 import java.util.Collections;
       
    90 import java.util.List;
    86 import java.util.Objects;
    91 import java.util.Objects;
       
    92 import java.util.regex.Matcher;
       
    93 import java.util.regex.Pattern;
    87 
    94 
    88 /**
    95 /**
    89  * A duration between two instants on the time-line.
    96  * A time-based amount of time, such as '34.5 seconds'.
    90  * <p>
    97  * <p>
    91  * This class models a duration of time and is not tied to any instant.
    98  * This class models a quantity or amount of time in terms of seconds and nanoseconds.
    92  * The model is of a directed duration, meaning that the duration may be negative.
    99  * It can be accessed using other duration-based units, such as minutes and hours.
       
   100  * In addition, the {@link ChronoUnit#DAYS DAYS} unit can be used and is treated as
       
   101  * exactly equal to 24 hours, thus ignoring daylight savings effects.
       
   102  * See {@link Period} for the date-based equivalent to this class.
    93  * <p>
   103  * <p>
    94  * A physical duration could be of infinite length.
   104  * A physical duration could be of infinite length.
    95  * For practicality, the duration is stored with constraints similar to {@link Instant}.
   105  * 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
   106  * 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.
   107  * be held in a {@code long}. This is greater than the current estimated age of the universe.
    98  * <p>
   108  * <p>
    99  * The range of a duration requires the storage of a number larger than a {@code long}.
   109  * 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}
   110  * 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.
   111  * representing nanosecond-of-second, which will always be between 0 and 999,999,999.
       
   112  * The model is of a directed duration, meaning that the duration may be negative.
   102  * <p>
   113  * <p>
   103  * The duration is measured in "seconds", but these are not necessarily identical to
   114  * The duration is measured in "seconds", but these are not necessarily identical to
   104  * the scientific "SI second" definition based on atomic clocks.
   115  * the scientific "SI second" definition based on atomic clocks.
   105  * This difference only impacts durations measured near a leap-second and should not affect
   116  * This difference only impacts durations measured near a leap-second and should not affect
   106  * most applications.
   117  * most applications.
   110  * This class is immutable and thread-safe.
   121  * This class is immutable and thread-safe.
   111  *
   122  *
   112  * @since 1.8
   123  * @since 1.8
   113  */
   124  */
   114 public final class Duration
   125 public final class Duration
   115         implements TemporalAdder, TemporalSubtractor, Comparable<Duration>, Serializable {
   126         implements TemporalAmount, Comparable<Duration>, Serializable {
   116 
   127 
   117     /**
   128     /**
   118      * Constant for a duration of zero.
   129      * Constant for a duration of zero.
   119      */
   130      */
   120     public static final Duration ZERO = new Duration(0, 0);
   131     public static final Duration ZERO = new Duration(0, 0);
   123      */
   134      */
   124     private static final long serialVersionUID = 3078945930695997490L;
   135     private static final long serialVersionUID = 3078945930695997490L;
   125     /**
   136     /**
   126      * Constant for nanos per second.
   137      * Constant for nanos per second.
   127      */
   138      */
   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);
   139     private static final BigInteger BI_NANOS_PER_SECOND = BigInteger.valueOf(NANOS_PER_SECOND);
       
   140     /**
       
   141      * The pattern for parsing.
       
   142      */
       
   143     private final static Pattern PATTERN =
       
   144             Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)D)?" +
       
   145                     "(T(?:([-+]?[0-9]+)H)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)(?:[.,]([0-9]{0,9}))?S)?)?",
       
   146                     Pattern.CASE_INSENSITIVE);
   133 
   147 
   134     /**
   148     /**
   135      * The number of seconds in the duration.
   149      * The number of seconds in the duration.
   136      */
   150      */
   137     private final long seconds;
   151     private final long seconds;
   141      */
   155      */
   142     private final int nanos;
   156     private final int nanos;
   143 
   157 
   144     //-----------------------------------------------------------------------
   158     //-----------------------------------------------------------------------
   145     /**
   159     /**
   146      * Obtains an instance of {@code Duration} from a number of seconds.
   160      * Obtains a {@code Duration} representing a number of standard 24 hour days.
       
   161      * <p>
       
   162      * The seconds are calculated based on the standard definition of a day,
       
   163      * where each day is 86400 seconds which implies a 24 hour day.
       
   164      * The nanosecond in second field is set to zero.
       
   165      *
       
   166      * @param days  the number of days, positive or negative
       
   167      * @return a {@code Duration}, not null
       
   168      * @throws ArithmeticException if the input days exceeds the capacity of {@code Duration}
       
   169      */
       
   170     public static Duration ofDays(long days) {
       
   171         return create(Math.multiplyExact(days, SECONDS_PER_DAY), 0);
       
   172     }
       
   173 
       
   174     /**
       
   175      * Obtains a {@code Duration} representing a number of standard hours.
       
   176      * <p>
       
   177      * The seconds are calculated based on the standard definition of an hour,
       
   178      * where each hour is 3600 seconds.
       
   179      * The nanosecond in second field is set to zero.
       
   180      *
       
   181      * @param hours  the number of hours, positive or negative
       
   182      * @return a {@code Duration}, not null
       
   183      * @throws ArithmeticException if the input hours exceeds the capacity of {@code Duration}
       
   184      */
       
   185     public static Duration ofHours(long hours) {
       
   186         return create(Math.multiplyExact(hours, SECONDS_PER_HOUR), 0);
       
   187     }
       
   188 
       
   189     /**
       
   190      * Obtains a {@code Duration} representing a number of standard minutes.
       
   191      * <p>
       
   192      * The seconds are calculated based on the standard definition of a minute,
       
   193      * where each minute is 60 seconds.
       
   194      * The nanosecond in second field is set to zero.
       
   195      *
       
   196      * @param minutes  the number of minutes, positive or negative
       
   197      * @return a {@code Duration}, not null
       
   198      * @throws ArithmeticException if the input minutes exceeds the capacity of {@code Duration}
       
   199      */
       
   200     public static Duration ofMinutes(long minutes) {
       
   201         return create(Math.multiplyExact(minutes, SECONDS_PER_MINUTE), 0);
       
   202     }
       
   203 
       
   204     //-----------------------------------------------------------------------
       
   205     /**
       
   206      * Obtains a {@code Duration} representing a number of seconds.
   147      * <p>
   207      * <p>
   148      * The nanosecond in second field is set to zero.
   208      * The nanosecond in second field is set to zero.
   149      *
   209      *
   150      * @param seconds  the number of seconds, positive or negative
   210      * @param seconds  the number of seconds, positive or negative
   151      * @return a {@code Duration}, not null
   211      * @return a {@code Duration}, not null
   153     public static Duration ofSeconds(long seconds) {
   213     public static Duration ofSeconds(long seconds) {
   154         return create(seconds, 0);
   214         return create(seconds, 0);
   155     }
   215     }
   156 
   216 
   157     /**
   217     /**
   158      * Obtains an instance of {@code Duration} from a number of seconds
   218      * Obtains a {@code Duration} representing a number of seconds and an
   159      * and an adjustment in nanoseconds.
   219      * adjustment in nanoseconds.
   160      * <p>
   220      * <p>
   161      * This method allows an arbitrary number of nanoseconds to be passed in.
   221      * 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
   222      * 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.
   223      * 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:
   224      * For example, the following will result in the exactly the same duration:
   173      * @return a {@code Duration}, not null
   233      * @return a {@code Duration}, not null
   174      * @throws ArithmeticException if the adjustment causes the seconds to exceed the capacity of {@code Duration}
   234      * @throws ArithmeticException if the adjustment causes the seconds to exceed the capacity of {@code Duration}
   175      */
   235      */
   176     public static Duration ofSeconds(long seconds, long nanoAdjustment) {
   236     public static Duration ofSeconds(long seconds, long nanoAdjustment) {
   177         long secs = Math.addExact(seconds, Math.floorDiv(nanoAdjustment, NANOS_PER_SECOND));
   237         long secs = Math.addExact(seconds, Math.floorDiv(nanoAdjustment, NANOS_PER_SECOND));
   178         int nos = (int)Math.floorMod(nanoAdjustment, NANOS_PER_SECOND);
   238         int nos = (int) Math.floorMod(nanoAdjustment, NANOS_PER_SECOND);
   179         return create(secs, nos);
   239         return create(secs, nos);
   180     }
   240     }
   181 
   241 
   182     //-----------------------------------------------------------------------
   242     //-----------------------------------------------------------------------
   183     /**
   243     /**
   184      * Obtains an instance of {@code Duration} from a number of milliseconds.
   244      * Obtains a {@code Duration} representing a number of milliseconds.
   185      * <p>
   245      * <p>
   186      * The seconds and nanoseconds are extracted from the specified milliseconds.
   246      * The seconds and nanoseconds are extracted from the specified milliseconds.
   187      *
   247      *
   188      * @param millis  the number of milliseconds, positive or negative
   248      * @param millis  the number of milliseconds, positive or negative
   189      * @return a {@code Duration}, not null
   249      * @return a {@code Duration}, not null
   198         return create(secs, mos * 1000_000);
   258         return create(secs, mos * 1000_000);
   199     }
   259     }
   200 
   260 
   201     //-----------------------------------------------------------------------
   261     //-----------------------------------------------------------------------
   202     /**
   262     /**
   203      * Obtains an instance of {@code Duration} from a number of nanoseconds.
   263      * Obtains a {@code Duration} representing a number of nanoseconds.
   204      * <p>
   264      * <p>
   205      * The seconds and nanoseconds are extracted from the specified nanoseconds.
   265      * The seconds and nanoseconds are extracted from the specified nanoseconds.
   206      *
   266      *
   207      * @param nanos  the number of nanoseconds, positive or negative
   267      * @param nanos  the number of nanoseconds, positive or negative
   208      * @return a {@code Duration}, not null
   268      * @return a {@code Duration}, not null
   217         return create(secs, nos);
   277         return create(secs, nos);
   218     }
   278     }
   219 
   279 
   220     //-----------------------------------------------------------------------
   280     //-----------------------------------------------------------------------
   221     /**
   281     /**
   222      * Obtains an instance of {@code Duration} from a number of standard length minutes.
   282      * Obtains a {@code Duration} representing an amount in the specified unit.
   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>
   283      * <p>
   270      * The parameters represent the two parts of a phrase like '6 Hours'. For example:
   284      * The parameters represent the two parts of a phrase like '6 Hours'. For example:
   271      * <pre>
   285      * <pre>
   272      *  Duration.of(3, SECONDS);
   286      *  Duration.of(3, SECONDS);
   273      *  Duration.of(465, HOURS);
   287      *  Duration.of(465, HOURS);
   286         return ZERO.plus(amount, unit);
   300         return ZERO.plus(amount, unit);
   287     }
   301     }
   288 
   302 
   289     //-----------------------------------------------------------------------
   303     //-----------------------------------------------------------------------
   290     /**
   304     /**
   291      * Obtains an instance of {@code Duration} representing the duration between two instants.
   305      * Obtains a {@code Duration} representing the duration between two instants.
   292      * <p>
   306      * <p>
   293      * A {@code Duration} represents a directed distance between two points on the time-line.
   307      * This calculates the duration between two temporal objects of the same type.
   294      * As such, this method will return a negative duration if the end is before the start.
   308      * The difference in seconds is calculated using
   295      * To guarantee to obtain a positive duration call {@link #abs()} on the result of this factory.
   309      * {@link Temporal#periodUntil(Temporal, TemporalUnit)}.
       
   310      * The difference in nanoseconds is calculated using by querying the
       
   311      * {@link ChronoField#NANO_OF_SECOND NANO_OF_SECOND} field.
       
   312      * <p>
       
   313      * The result of this method can be a negative period if the end is before the start.
       
   314      * To guarantee to obtain a positive duration call {@link #abs()} on the result.
   296      *
   315      *
   297      * @param startInclusive  the start instant, inclusive, not null
   316      * @param startInclusive  the start instant, inclusive, not null
   298      * @param endExclusive  the end instant, exclusive, not null
   317      * @param endExclusive  the end instant, exclusive, not null
   299      * @return a {@code Duration}, not null
   318      * @return a {@code Duration}, not null
   300      * @throws ArithmeticException if the calculation exceeds the capacity of {@code Duration}
   319      * @throws ArithmeticException if the calculation exceeds the capacity of {@code Duration}
   301      */
   320      */
   302     public static Duration between(TemporalAccessor startInclusive, TemporalAccessor endExclusive) {
   321     public static  Duration between(Temporal startInclusive, Temporal endExclusive) {
   303         long secs = Math.subtractExact(endExclusive.getLong(INSTANT_SECONDS), startInclusive.getLong(INSTANT_SECONDS));
   322         long secs = startInclusive.periodUntil(endExclusive, SECONDS);
   304         long nanos = endExclusive.getLong(NANO_OF_SECOND) - startInclusive.getLong(NANO_OF_SECOND);
   323         long nanos;
   305         secs = Math.addExact(secs, Math.floorDiv(nanos, NANOS_PER_SECOND));
   324         try {
   306         nanos = Math.floorMod(nanos, NANOS_PER_SECOND);
   325             nanos = endExclusive.getLong(NANO_OF_SECOND) - startInclusive.getLong(NANO_OF_SECOND);
   307         return create(secs, (int) nanos);  // safe from overflow
   326         } catch (DateTimeException ex) {
   308     }
   327             nanos = 0;
   309 
   328         }
   310     //-----------------------------------------------------------------------
   329         return ofSeconds(secs, nanos);
   311     /**
   330     }
   312      * Obtains an instance of {@code Duration} by parsing a text string.
   331 
   313      * <p>
   332     //-----------------------------------------------------------------------
   314      * This will parse the string produced by {@link #toString()} which is
   333     /**
   315      * the ISO-8601 format {@code PTnS} where {@code n} is
   334      * Obtains a {@code Duration} from a text string such as {@code PnDTnHnMn.nS}.
   316      * the number of seconds with optional decimal part.
   335      * <p>
   317      * The number must consist of ASCII numerals.
   336      * This will parse a textual representation of a duration, including the
   318      * There must only be a negative sign at the start of the number and it can
   337      * string produced by {@code toString()}. The formats accepted are based
   319      * only be present if the value is less than zero.
   338      * on the ISO-8601 duration format {@code PnDTnHnMn.nS} with days
   320      * There must be at least one digit before any decimal point.
   339      * considered to be exactly 24 hours.
   321      * There must be between 1 and 9 inclusive digits after any decimal point.
   340      * <p>
   322      * The letters (P, T and S) will be accepted in upper or lower case.
   341      * The string starts with an optional sign, denoted by the ASCII negative
       
   342      * or positive symbol. If negative, the whole period is negated.
       
   343      * The ASCII letter "P" is next in upper or lower case.
       
   344      * There are then four sections, each consisting of a number and a suffix.
       
   345      * The sections have suffixes in ASCII of "D", "H", "M" and "S" for
       
   346      * days, hours, minutes and seconds, accepted in upper or lower case.
       
   347      * The suffixes must occur in order. The ASCII letter "T" must occur before
       
   348      * the first occurrence, if any, of an hour, minute or second section.
       
   349      * At least one of the four sections must be present, and if "T" is present
       
   350      * there must be at least one section after the "T".
       
   351      * The number part of each section must consist of one or more ASCII digits.
       
   352      * The number may be prefixed by the ASCII negative or positive symbol.
       
   353      * The number of days, hours and minutes must parse to an {@code long}.
       
   354      * The number of seconds must parse to an {@code long} with optional fraction.
   323      * The decimal point may be either a dot or a comma.
   355      * The decimal point may be either a dot or a comma.
       
   356      * The fractional part may have from zero to 9 digits.
       
   357      * <p>
       
   358      * The leading plus/minus sign, and negative values for other units are
       
   359      * not part of the ISO-8601 standard.
       
   360      * <p>
       
   361      * Examples:
       
   362      * <pre>
       
   363      *    "PT20.345S" -> parses as "20.345 seconds"
       
   364      *    "PT15M"     -> parses as "15 minutes" (where a minute is 60 seconds)
       
   365      *    "PT10H"     -> parses as "10 hours" (where an hour is 3600 seconds)
       
   366      *    "P2D"       -> parses as "2 days" (where a day is 24 hours or 86400 seconds)
       
   367      *    "P2DT3H4M"  -> parses as "2 days, 3 hours and 4 minutes"
       
   368      *    "P-6H3M"    -> parses as "-6 hours and +3 minutes"
       
   369      *    "-P6H3M"    -> parses as "-6 hours and -3 minutes"
       
   370      *    "-P-6H+3M"  -> parses as "+6 hours and -3 minutes"
       
   371      * </pre>
   324      *
   372      *
   325      * @param text  the text to parse, not null
   373      * @param text  the text to parse, not null
   326      * @return a {@code Duration}, not null
   374      * @return the parsed duration, not null
   327      * @throws DateTimeParseException if the text cannot be parsed to a {@code Duration}
   375      * @throws DateTimeParseException if the text cannot be parsed to a duration
   328      */
   376      */
   329     public static Duration parse(final CharSequence text) {
   377     public static Duration parse(CharSequence text) {
   330         Objects.requireNonNull(text, "text");
   378         Objects.requireNonNull(text, "text");
   331         int len = text.length();
   379         Matcher matcher = PATTERN.matcher(text);
   332         if (len < 4 ||
   380         if (matcher.matches()) {
   333                 (text.charAt(0) != 'P' && text.charAt(0) != 'p') ||
   381             // check for letter T but no time sections
   334                 (text.charAt(1) != 'T' && text.charAt(1) != 't') ||
   382             if ("T".equals(matcher.group(3)) == false) {
   335                 (text.charAt(len - 1) != 'S' && text.charAt(len - 1) != 's') ||
   383                 boolean negate = "-".equals(matcher.group(1));
   336                 (len == 5 && text.charAt(2) == '-' && text.charAt(3) == '0')) {
   384                 String dayMatch = matcher.group(2);
   337             throw new DateTimeParseException("Duration could not be parsed: " + text, text, 0);
   385                 String hourMatch = matcher.group(4);
   338         }
   386                 String minuteMatch = matcher.group(5);
   339         String numberText = text.subSequence(2, len - 1).toString().replace(',', '.');
   387                 String secondMatch = matcher.group(6);
   340         if (numberText.charAt(0) == '+') {
   388                 String fractionMatch = matcher.group(7);
   341             throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2);
   389                 if (dayMatch != null || hourMatch != null || minuteMatch != null || secondMatch != null) {
   342         }
   390                     long daysAsSecs = parseNumber(text, dayMatch, SECONDS_PER_DAY, "days");
   343         int dot = numberText.indexOf('.');
   391                     long hoursAsSecs = parseNumber(text, hourMatch, SECONDS_PER_HOUR, "hours");
       
   392                     long minsAsSecs = parseNumber(text, minuteMatch, SECONDS_PER_MINUTE, "minutes");
       
   393                     long seconds = parseNumber(text, secondMatch, 1, "seconds");
       
   394                     int nanos = parseFraction(text,  fractionMatch, seconds < 0 ? -1 : 1);
       
   395                     try {
       
   396                         return create(negate, daysAsSecs, hoursAsSecs, minsAsSecs, seconds, nanos);
       
   397                     } catch (ArithmeticException ex) {
       
   398                         throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: overflow", text, 0).initCause(ex);
       
   399                     }
       
   400                 }
       
   401             }
       
   402         }
       
   403         throw new DateTimeParseException("Text cannot be parsed to a Duration", text, 0);
       
   404     }
       
   405 
       
   406     private static long parseNumber(CharSequence text, String parsed, int multiplier, String errorText) {
       
   407         // regex limits to [-+]?[0-9]+
       
   408         if (parsed == null) {
       
   409             return 0;
       
   410         }
   344         try {
   411         try {
   345             if (dot == -1) {
   412             long val = Long.parseLong(parsed);
   346                 // no decimal places
   413             return Math.multiplyExact(val, multiplier);
   347                 if (numberText.startsWith("-0")) {
   414         } catch (NumberFormatException | ArithmeticException ex) {
   348                     throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2);
   415             throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: " + errorText, text, 0).initCause(ex);
   349                 }
   416         }
   350                 return create(Long.parseLong(numberText), 0);
   417     }
   351             }
   418 
   352             // decimal places
   419     private static int parseFraction(CharSequence text, String parsed, int negate) {
   353             boolean negative = false;
   420         // regex limits to [0-9]{0,9}
   354             if (numberText.charAt(0) == '-') {
   421         if (parsed == null || parsed.length() == 0) {
   355                 negative = true;
   422             return 0;
   356             }
   423         }
   357             long secs = Long.parseLong(numberText.substring(0, dot));
   424         try {
   358             numberText = numberText.substring(dot + 1);
   425             parsed = (parsed + "000000000").substring(0, 9);
   359             len = numberText.length();
   426             return Integer.parseInt(parsed) * negate;
   360             if (len == 0 || len > 9 || numberText.charAt(0) == '-' || numberText.charAt(0) == '+') {
   427         } catch (NumberFormatException | ArithmeticException ex) {
   361                 throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2);
   428             throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: fraction", text, 0).initCause(ex);
   362             }
   429         }
   363             int nanos = Integer.parseInt(numberText);
   430     }
   364             switch (len) {
   431 
   365                 case 1:
   432     private static Duration create(boolean negate, long daysAsSecs, long hoursAsSecs, long minsAsSecs, long secs, int nanos) {
   366                     nanos *= 100000000;
   433         long seconds = Math.addExact(daysAsSecs, Math.addExact(hoursAsSecs, Math.addExact(minsAsSecs, secs)));
   367                     break;
   434         if (negate) {
   368                 case 2:
   435             return ofSeconds(seconds, nanos).negated();
   369                     nanos *= 10000000;
   436         }
   370                     break;
   437         return ofSeconds(seconds, nanos);
   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     }
   438     }
   396 
   439 
   397     //-----------------------------------------------------------------------
   440     //-----------------------------------------------------------------------
   398     /**
   441     /**
   399      * Obtains an instance of {@code Duration} using seconds and nanoseconds.
   442      * Obtains an instance of {@code Duration} using seconds and nanoseconds.
   420         this.nanos = nanos;
   463         this.nanos = nanos;
   421     }
   464     }
   422 
   465 
   423     //-----------------------------------------------------------------------
   466     //-----------------------------------------------------------------------
   424     /**
   467     /**
       
   468      * Gets the value of the requested unit.
       
   469      * <p>
       
   470      * This returns a value for each of the two supported units,
       
   471      * {@link ChronoUnit#SECONDS SECONDS} and {@link ChronoUnit#NANOS NANOS}.
       
   472      * All other units throw an exception.
       
   473      *
       
   474      * @param unit the {@code TemporalUnit} for which to return the value
       
   475      * @return the long value of the unit
       
   476      * @throws DateTimeException if the unit is not supported
       
   477      */
       
   478     @Override
       
   479     public long get(TemporalUnit unit) {
       
   480         if (unit == SECONDS) {
       
   481             return seconds;
       
   482         } else if (unit == NANOS) {
       
   483             return nanos;
       
   484         } else {
       
   485             throw new DateTimeException("Unsupported unit: " + unit.getName());
       
   486         }
       
   487     }
       
   488 
       
   489     /**
       
   490      * Gets the set of units supported by this duration.
       
   491      * <p>
       
   492      * The supported units are {@link ChronoUnit#SECONDS SECONDS},
       
   493      * and {@link ChronoUnit#NANOS NANOS}.
       
   494      * They are returned in the order seconds, nanos.
       
   495      * <p>
       
   496      * This set can be used in conjunction with {@link #get(TemporalUnit)}
       
   497      * to access the entire state of the period.
       
   498      *
       
   499      * @return a list containing the seconds and nanos units, not null
       
   500      */
       
   501     @Override
       
   502     public List<TemporalUnit> getUnits() {
       
   503         return DurationUnits.UNITS;
       
   504     }
       
   505 
       
   506     /**
       
   507      * Private class to delay initialization of this list until needed.
       
   508      * The circular dependency between Duration and ChronoUnit prevents
       
   509      * the simple initialization in Duration.
       
   510      */
       
   511     private static class DurationUnits {
       
   512         final static List<TemporalUnit> UNITS =
       
   513                 Collections.unmodifiableList(Arrays.<TemporalUnit>asList(SECONDS, NANOS));
       
   514     }
       
   515 
       
   516     //-----------------------------------------------------------------------
       
   517     /**
   425      * Checks if this duration is zero length.
   518      * Checks if this duration is zero length.
   426      * <p>
   519      * <p>
   427      * A {@code Duration} represents a directed distance between two points on
   520      * A {@code Duration} represents a directed distance between two points on
   428      * the time-line and can therefore be positive, zero or negative.
   521      * the time-line and can therefore be positive, zero or negative.
   429      * This method checks whether the length is zero.
   522      * This method checks whether the length is zero.
   430      *
   523      *
   431      * @return true if this duration has a total length equal to zero
   524      * @return true if this duration has a total length equal to zero
   432      */
   525      */
   433     public boolean isZero() {
   526     public boolean isZero() {
   434         return (seconds | nanos) == 0;
   527         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     }
   528     }
   449 
   529 
   450     /**
   530     /**
   451      * Checks if this duration is negative, excluding zero.
   531      * Checks if this duration is negative, excluding zero.
   452      * <p>
   532      * <p>
   493      *
   573      *
   494      * @return the nanoseconds within the second part of the length of the duration, from 0 to 999,999,999
   574      * @return the nanoseconds within the second part of the length of the duration, from 0 to 999,999,999
   495      */
   575      */
   496     public int getNano() {
   576     public int getNano() {
   497         return nanos;
   577         return nanos;
       
   578     }
       
   579 
       
   580     //-----------------------------------------------------------------------
       
   581     /**
       
   582      * Returns a copy of this duration with the specified amount of seconds.
       
   583      * <p>
       
   584      * This returns a duration with the specified seconds, retaining the
       
   585      * nano-of-second part of this duration.
       
   586      * <p>
       
   587      * This instance is immutable and unaffected by this method call.
       
   588      *
       
   589      * @param seconds  the seconds to represent, may be negative
       
   590      * @return a {@code Duration} based on this period with the requested seconds, not null
       
   591      */
       
   592     public Duration withSeconds(long seconds) {
       
   593         return create(seconds, nanos);
       
   594     }
       
   595 
       
   596     /**
       
   597      * Returns a copy of this duration with the specified nano-of-second.
       
   598      * <p>
       
   599      * This returns a duration with the specified nano-of-second, retaining the
       
   600      * seconds part of this duration.
       
   601      * <p>
       
   602      * This instance is immutable and unaffected by this method call.
       
   603      *
       
   604      * @param nanoOfSecond  the nano-of-second to represent, from 0 to 999,999,999
       
   605      * @return a {@code Duration} based on this period with the requested nano-of-second, not null
       
   606      * @throws DateTimeException if the nano-of-second is invalid
       
   607      */
       
   608     public Duration withNanos(int nanoOfSecond) {
       
   609         NANO_OF_SECOND.checkValidIntValue(nanoOfSecond);
       
   610         return create(seconds, nanoOfSecond);
   498     }
   611     }
   499 
   612 
   500     //-----------------------------------------------------------------------
   613     //-----------------------------------------------------------------------
   501     /**
   614     /**
   502      * Returns a copy of this duration with the specified duration added.
   615      * Returns a copy of this duration with the specified duration added.
   550         return plusSeconds(duration.getSeconds()).plusNanos(duration.getNano());
   663         return plusSeconds(duration.getSeconds()).plusNanos(duration.getNano());
   551     }
   664     }
   552 
   665 
   553     //-----------------------------------------------------------------------
   666     //-----------------------------------------------------------------------
   554     /**
   667     /**
       
   668      * Returns a copy of this duration with the specified duration in standard 24 hour days added.
       
   669      * <p>
       
   670      * The number of days is multiplied by 86400 to obtain the number of seconds to add.
       
   671      * This is based on the standard definition of a day as 24 hours.
       
   672      * <p>
       
   673      * This instance is immutable and unaffected by this method call.
       
   674      *
       
   675      * @param daysToAdd  the days to add, positive or negative
       
   676      * @return a {@code Duration} based on this duration with the specified days added, not null
       
   677      * @throws ArithmeticException if numeric overflow occurs
       
   678      */
       
   679     public Duration plusDays(long daysToAdd) {
       
   680         return plus(Math.multiplyExact(daysToAdd, SECONDS_PER_DAY), 0);
       
   681     }
       
   682 
       
   683     /**
       
   684      * Returns a copy of this duration with the specified duration in hours added.
       
   685      * <p>
       
   686      * This instance is immutable and unaffected by this method call.
       
   687      *
       
   688      * @param hoursToAdd  the hours to add, positive or negative
       
   689      * @return a {@code Duration} based on this duration with the specified hours added, not null
       
   690      * @throws ArithmeticException if numeric overflow occurs
       
   691      */
       
   692     public Duration plusHours(long hoursToAdd) {
       
   693         return plus(Math.multiplyExact(hoursToAdd, SECONDS_PER_HOUR), 0);
       
   694     }
       
   695 
       
   696     /**
       
   697      * Returns a copy of this duration with the specified duration in minutes added.
       
   698      * <p>
       
   699      * This instance is immutable and unaffected by this method call.
       
   700      *
       
   701      * @param minutesToAdd  the minutes to add, positive or negative
       
   702      * @return a {@code Duration} based on this duration with the specified minutes added, not null
       
   703      * @throws ArithmeticException if numeric overflow occurs
       
   704      */
       
   705     public Duration plusMinutes(long minutesToAdd) {
       
   706         return plus(Math.multiplyExact(minutesToAdd, SECONDS_PER_MINUTE), 0);
       
   707     }
       
   708 
       
   709     /**
   555      * Returns a copy of this duration with the specified duration in seconds added.
   710      * Returns a copy of this duration with the specified duration in seconds added.
   556      * <p>
   711      * <p>
   557      * This instance is immutable and unaffected by this method call.
   712      * This instance is immutable and unaffected by this method call.
   558      *
   713      *
   559      * @param secondsToAdd  the seconds to add, positive or negative
   714      * @param secondsToAdd  the seconds to add, positive or negative
   649         return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
   804         return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
   650     }
   805     }
   651 
   806 
   652     //-----------------------------------------------------------------------
   807     //-----------------------------------------------------------------------
   653     /**
   808     /**
       
   809      * Returns a copy of this duration with the specified duration in standard 24 hour days subtracted.
       
   810      * <p>
       
   811      * The number of days is multiplied by 86400 to obtain the number of seconds to subtract.
       
   812      * This is based on the standard definition of a day as 24 hours.
       
   813      * <p>
       
   814      * This instance is immutable and unaffected by this method call.
       
   815      *
       
   816      * @param daysToSubtract  the days to subtract, positive or negative
       
   817      * @return a {@code Duration} based on this duration with the specified days subtracted, not null
       
   818      * @throws ArithmeticException if numeric overflow occurs
       
   819      */
       
   820     public Duration minusDays(long daysToSubtract) {
       
   821         return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));
       
   822     }
       
   823 
       
   824     /**
       
   825      * Returns a copy of this duration with the specified duration in hours subtracted.
       
   826      * <p>
       
   827      * The number of hours is multiplied by 3600 to obtain the number of seconds to subtract.
       
   828      * <p>
       
   829      * This instance is immutable and unaffected by this method call.
       
   830      *
       
   831      * @param hoursToSubtract  the hours to subtract, positive or negative
       
   832      * @return a {@code Duration} based on this duration with the specified hours subtracted, not null
       
   833      * @throws ArithmeticException if numeric overflow occurs
       
   834      */
       
   835     public Duration minusHours(long hoursToSubtract) {
       
   836         return (hoursToSubtract == Long.MIN_VALUE ? plusHours(Long.MAX_VALUE).plusHours(1) : plusHours(-hoursToSubtract));
       
   837     }
       
   838 
       
   839     /**
       
   840      * Returns a copy of this duration with the specified duration in minutes subtracted.
       
   841      * <p>
       
   842      * The number of hours is multiplied by 60 to obtain the number of seconds to subtract.
       
   843      * <p>
       
   844      * This instance is immutable and unaffected by this method call.
       
   845      *
       
   846      * @param minutesToSubtract  the minutes to subtract, positive or negative
       
   847      * @return a {@code Duration} based on this duration with the specified minutes subtracted, not null
       
   848      * @throws ArithmeticException if numeric overflow occurs
       
   849      */
       
   850     public Duration minusMinutes(long minutesToSubtract) {
       
   851         return (minutesToSubtract == Long.MIN_VALUE ? plusMinutes(Long.MAX_VALUE).plusMinutes(1) : plusMinutes(-minutesToSubtract));
       
   852     }
       
   853 
       
   854     /**
   654      * Returns a copy of this duration with the specified duration in seconds subtracted.
   855      * Returns a copy of this duration with the specified duration in seconds subtracted.
   655      * <p>
   856      * <p>
   656      * This instance is immutable and unaffected by this method call.
   857      * This instance is immutable and unaffected by this method call.
   657      *
   858      *
   658      * @param secondsToSubtract  the seconds to subtract, positive or negative
   859      * @param secondsToSubtract  the seconds to subtract, positive or negative
   714      * <p>
   915      * <p>
   715      * This instance is immutable and unaffected by this method call.
   916      * This instance is immutable and unaffected by this method call.
   716      *
   917      *
   717      * @param divisor  the value to divide the duration by, positive or negative, not zero
   918      * @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
   919      * @return a {@code Duration} based on this duration divided by the specified divisor, not null
   719      * @throws ArithmeticException if the divisor is zero
   920      * @throws ArithmeticException if the divisor is zero or if numeric overflow occurs
   720      * @throws ArithmeticException if numeric overflow occurs
       
   721      */
   921      */
   722     public Duration dividedBy(long divisor) {
   922     public Duration dividedBy(long divisor) {
   723         if (divisor == 0) {
   923         if (divisor == 0) {
   724             throw new ArithmeticException("Cannot divide by zero");
   924             throw new ArithmeticException("Cannot divide by zero");
   725         }
   925         }
   792      * <p>
   992      * <p>
   793      * This returns a temporal object of the same observable type as the input
   993      * This returns a temporal object of the same observable type as the input
   794      * with this duration added.
   994      * with this duration added.
   795      * <p>
   995      * <p>
   796      * In most cases, it is clearer to reverse the calling pattern by using
   996      * In most cases, it is clearer to reverse the calling pattern by using
   797      * {@link Temporal#plus(TemporalAdder)}.
   997      * {@link Temporal#plus(TemporalAmount)}.
   798      * <pre>
   998      * <pre>
   799      *   // these two lines are equivalent, but the second approach is recommended
   999      *   // these two lines are equivalent, but the second approach is recommended
   800      *   dateTime = thisDuration.addTo(dateTime);
  1000      *   dateTime = thisDuration.addTo(dateTime);
   801      *   dateTime = dateTime.plus(thisDuration);
  1001      *   dateTime = dateTime.plus(thisDuration);
   802      * </pre>
  1002      * </pre>
   803      * <p>
  1003      * <p>
   804      * A {@code Duration} can only be added to a {@code Temporal} that
  1004      * The calculation will add the seconds, then nanos.
   805      * represents an instant and can supply {@link ChronoField#INSTANT_SECONDS}.
  1005      * Only non-zero amounts will be added.
   806      * <p>
  1006      * <p>
   807      * This instance is immutable and unaffected by this method call.
  1007      * This instance is immutable and unaffected by this method call.
   808      *
  1008      *
   809      * @param temporal  the temporal object to adjust, not null
  1009      * @param temporal  the temporal object to adjust, not null
   810      * @return an object of the same type with the adjustment made, not null
  1010      * @return an object of the same type with the adjustment made, not null
   811      * @throws DateTimeException if unable to add
  1011      * @throws DateTimeException if unable to add
   812      * @throws ArithmeticException if numeric overflow occurs
  1012      * @throws ArithmeticException if numeric overflow occurs
   813      */
  1013      */
   814     @Override
  1014     @Override
   815     public Temporal addTo(Temporal temporal) {
  1015     public Temporal addTo(Temporal temporal) {
   816         long instantSecs = temporal.getLong(INSTANT_SECONDS);
  1016         if (seconds != 0) {
   817         long instantNanos = temporal.getLong(NANO_OF_SECOND);
  1017             temporal = temporal.plus(seconds, SECONDS);
   818         instantSecs = Math.addExact(instantSecs, seconds);
  1018         }
   819         instantNanos = Math.addExact(instantNanos, nanos);
  1019         if (nanos != 0) {
   820         instantSecs = Math.addExact(instantSecs, Math.floorDiv(instantNanos, NANOS_PER_SECOND));
  1020             temporal = temporal.plus(nanos, NANOS);
   821         instantNanos = Math.floorMod(instantNanos, NANOS_PER_SECOND);
  1021         }
   822         return temporal.with(INSTANT_SECONDS, instantSecs).with(NANO_OF_SECOND, instantNanos);
  1022         return temporal;
   823     }
  1023     }
   824 
  1024 
   825     /**
  1025     /**
   826      * Subtracts this duration from the specified temporal object.
  1026      * Subtracts this duration from the specified temporal object.
   827      * <p>
  1027      * <p>
   828      * This returns a temporal object of the same observable type as the input
  1028      * This returns a temporal object of the same observable type as the input
   829      * with this duration subtracted.
  1029      * with this duration subtracted.
   830      * <p>
  1030      * <p>
   831      * In most cases, it is clearer to reverse the calling pattern by using
  1031      * In most cases, it is clearer to reverse the calling pattern by using
   832      * {@link Temporal#minus(TemporalSubtractor)}.
  1032      * {@link Temporal#minus(TemporalAmount)}.
   833      * <pre>
  1033      * <pre>
   834      *   // these two lines are equivalent, but the second approach is recommended
  1034      *   // these two lines are equivalent, but the second approach is recommended
   835      *   dateTime = thisDuration.subtractFrom(dateTime);
  1035      *   dateTime = thisDuration.subtractFrom(dateTime);
   836      *   dateTime = dateTime.minus(thisDuration);
  1036      *   dateTime = dateTime.minus(thisDuration);
   837      * </pre>
  1037      * </pre>
   838      * <p>
  1038      * <p>
   839      * A {@code Duration} can only be subtracted from a {@code Temporal} that
  1039      * The calculation will subtract the seconds, then nanos.
   840      * represents an instant and can supply {@link ChronoField#INSTANT_SECONDS}.
  1040      * Only non-zero amounts will be added.
   841      * <p>
  1041      * <p>
   842      * This instance is immutable and unaffected by this method call.
  1042      * This instance is immutable and unaffected by this method call.
   843      *
  1043      *
   844      * @param temporal  the temporal object to adjust, not null
  1044      * @param temporal  the temporal object to adjust, not null
   845      * @return an object of the same type with the adjustment made, not null
  1045      * @return an object of the same type with the adjustment made, not null
   846      * @throws DateTimeException if unable to subtract
  1046      * @throws DateTimeException if unable to subtract
   847      * @throws ArithmeticException if numeric overflow occurs
  1047      * @throws ArithmeticException if numeric overflow occurs
   848      */
  1048      */
   849     @Override
  1049     @Override
   850     public Temporal subtractFrom(Temporal temporal) {
  1050     public Temporal subtractFrom(Temporal temporal) {
   851         long instantSecs = temporal.getLong(INSTANT_SECONDS);
  1051         if (seconds != 0) {
   852         long instantNanos = temporal.getLong(NANO_OF_SECOND);
  1052             temporal = temporal.minus(seconds, SECONDS);
   853         instantSecs = Math.subtractExact(instantSecs, seconds);
  1053         }
   854         instantNanos = Math.subtractExact(instantNanos, nanos);
  1054         if (nanos != 0) {
   855         instantSecs = Math.addExact(instantSecs, Math.floorDiv(instantNanos, NANOS_PER_SECOND));
  1055             temporal = temporal.minus(nanos, NANOS);
   856         instantNanos = Math.floorMod(instantNanos, NANOS_PER_SECOND);
  1056         }
   857         return temporal.with(INSTANT_SECONDS, instantSecs).with(NANO_OF_SECOND, instantNanos);
  1057         return temporal;
   858     }
  1058     }
   859 
  1059 
   860     //-----------------------------------------------------------------------
  1060     //-----------------------------------------------------------------------
       
  1061     /**
       
  1062      * Gets the number of minutes in this duration.
       
  1063      * <p>
       
  1064      * This returns the total number of minutes in the duration by dividing the
       
  1065      * number of seconds by 86400.
       
  1066      * This is based on the standard definition of a day as 24 hours.
       
  1067      * <p>
       
  1068      * This instance is immutable and unaffected by this method call.
       
  1069      *
       
  1070      * @return the number of minutes in the duration, may be negative
       
  1071      */
       
  1072     public long toDays() {
       
  1073         return seconds / SECONDS_PER_DAY;
       
  1074     }
       
  1075 
       
  1076     /**
       
  1077      * Gets the number of minutes in this duration.
       
  1078      * <p>
       
  1079      * This returns the total number of minutes in the duration by dividing the
       
  1080      * number of seconds by 3600.
       
  1081      * <p>
       
  1082      * This instance is immutable and unaffected by this method call.
       
  1083      *
       
  1084      * @return the number of minutes in the duration, may be negative
       
  1085      */
       
  1086     public long toHours() {
       
  1087         return seconds / SECONDS_PER_HOUR;
       
  1088     }
       
  1089 
       
  1090     /**
       
  1091      * Gets the number of minutes in this duration.
       
  1092      * <p>
       
  1093      * This returns the total number of minutes in the duration by dividing the
       
  1094      * number of seconds by 60.
       
  1095      * <p>
       
  1096      * This instance is immutable and unaffected by this method call.
       
  1097      *
       
  1098      * @return the number of minutes in the duration, may be negative
       
  1099      */
       
  1100     public long toMinutes() {
       
  1101         return seconds / SECONDS_PER_MINUTE;
       
  1102     }
       
  1103 
   861     /**
  1104     /**
   862      * Converts this duration to the total length in milliseconds.
  1105      * Converts this duration to the total length in milliseconds.
   863      * <p>
  1106      * <p>
   864      * If this duration is too large to fit in a {@code long} milliseconds, then an
  1107      * If this duration is too large to fit in a {@code long} milliseconds, then an
   865      * exception is thrown.
  1108      * exception is thrown.
   885      *
  1128      *
   886      * @return the total length of the duration in nanoseconds
  1129      * @return the total length of the duration in nanoseconds
   887      * @throws ArithmeticException if numeric overflow occurs
  1130      * @throws ArithmeticException if numeric overflow occurs
   888      */
  1131      */
   889     public long toNanos() {
  1132     public long toNanos() {
   890         long millis = Math.multiplyExact(seconds, 1000_000_000);
  1133         long millis = Math.multiplyExact(seconds, NANOS_PER_SECOND);
   891         millis = Math.addExact(millis, nanos);
  1134         millis = Math.addExact(millis, nanos);
   892         return millis;
  1135         return millis;
   893     }
  1136     }
   894 
  1137 
   895     //-----------------------------------------------------------------------
  1138     //-----------------------------------------------------------------------
   909             return cmp;
  1152             return cmp;
   910         }
  1153         }
   911         return nanos - otherDuration.nanos;
  1154         return nanos - otherDuration.nanos;
   912     }
  1155     }
   913 
  1156 
   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     //-----------------------------------------------------------------------
  1157     //-----------------------------------------------------------------------
   939     /**
  1158     /**
   940      * Checks if this duration is equal to the specified {@code Duration}.
  1159      * Checks if this duration is equal to the specified {@code Duration}.
   941      * <p>
  1160      * <p>
   942      * The comparison is based on the total length of the durations.
  1161      * The comparison is based on the total length of the durations.
   968     }
  1187     }
   969 
  1188 
   970     //-----------------------------------------------------------------------
  1189     //-----------------------------------------------------------------------
   971     /**
  1190     /**
   972      * A string representation of this duration using ISO-8601 seconds
  1191      * A string representation of this duration using ISO-8601 seconds
   973      * based representation, such as {@code PT12.345S}.
  1192      * based representation, such as {@code PT8H6M12.345S}.
   974      * <p>
  1193      * <p>
   975      * The format of the returned string will be {@code PTnS} where n is
  1194      * The format of the returned string will be {@code PTnHnMnS}, where n is
   976      * the seconds and fractional seconds of the duration.
  1195      * the relevant hours, minutes or seconds part of the duration.
       
  1196      * Any fractional seconds are placed after a decimal point i the seconds section.
       
  1197      * If a section has a zero value, it is omitted.
       
  1198      * The hours, minutes and seconds will all have the same sign.
       
  1199      * <p>
       
  1200      * Examples:
       
  1201      * <pre>
       
  1202      *    "20.345 seconds"                 -> "PT20.345S
       
  1203      *    "15 minutes" (15 * 60 seconds)   -> "PT15M"
       
  1204      *    "10 hours" (10 * 3600 seconds)   -> "PT10H"
       
  1205      *    "2 days" (2 * 86400 seconds)     -> "PT48H"
       
  1206      * </pre>
       
  1207      * Note that multiples of 24 hours are not output as days to avoid confusion
       
  1208      * with {@code Period}.
   977      *
  1209      *
   978      * @return an ISO-8601 representation of this duration, not null
  1210      * @return an ISO-8601 representation of this duration, not null
   979      */
  1211      */
   980     @Override
  1212     @Override
   981     public String toString() {
  1213     public String toString() {
       
  1214         if (this == ZERO) {
       
  1215             return "PT0S";
       
  1216         }
       
  1217         long hours = seconds / SECONDS_PER_HOUR;
       
  1218         int minutes = (int) ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
       
  1219         int secs = (int) (seconds % SECONDS_PER_MINUTE);
   982         StringBuilder buf = new StringBuilder(24);
  1220         StringBuilder buf = new StringBuilder(24);
   983         buf.append("PT");
  1221         buf.append("PT");
   984         if (seconds < 0 && nanos > 0) {
  1222         if (hours != 0) {
   985             if (seconds == -1) {
  1223             buf.append(hours).append('H');
       
  1224         }
       
  1225         if (minutes != 0) {
       
  1226             buf.append(minutes).append('M');
       
  1227         }
       
  1228         if (secs == 0 && nanos == 0 && buf.length() > 2) {
       
  1229             return buf.toString();
       
  1230         }
       
  1231         if (secs < 0 && nanos > 0) {
       
  1232             if (secs == -1) {
   986                 buf.append("-0");
  1233                 buf.append("-0");
   987             } else {
  1234             } else {
   988                 buf.append(seconds + 1);
  1235                 buf.append(secs + 1);
   989             }
  1236             }
   990         } else {
  1237         } else {
   991             buf.append(seconds);
  1238             buf.append(secs);
   992         }
  1239         }
   993         if (nanos > 0) {
  1240         if (nanos > 0) {
   994             int pos = buf.length();
  1241             int pos = buf.length();
   995             if (seconds < 0) {
  1242             if (secs < 0) {
   996                 buf.append(2 * NANOS_PER_SECOND - nanos);
  1243                 buf.append(2 * NANOS_PER_SECOND - nanos);
   997             } else {
  1244             } else {
   998                 buf.append(nanos + NANOS_PER_SECOND);
  1245                 buf.append(nanos + NANOS_PER_SECOND);
   999             }
  1246             }
  1000             while (buf.charAt(buf.length() - 1) == '0') {
  1247             while (buf.charAt(buf.length() - 1) == '0') {