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