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