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