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