001/* 002 * Copyright (c) 2007-2013, Stephen Colebourne & Michael Nascimento Santos 003 * 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions are met: 008 * 009 * * Redistributions of source code must retain the above copyright notice, 010 * this list of conditions and the following disclaimer. 011 * 012 * * Redistributions in binary form must reproduce the above copyright notice, 013 * this list of conditions and the following disclaimer in the documentation 014 * and/or other materials provided with the distribution. 015 * 016 * * Neither the name of JSR-310 nor the names of its contributors 017 * may be used to endorse or promote products derived from this software 018 * without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 021 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 022 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 023 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 024 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 031 */ 032package org.threeten.bp; 033 034import static org.threeten.bp.LocalTime.SECONDS_PER_DAY; 035import static org.threeten.bp.temporal.ChronoField.INSTANT_SECONDS; 036import static org.threeten.bp.temporal.ChronoField.NANO_OF_SECOND; 037import static org.threeten.bp.temporal.ChronoUnit.DAYS; 038 039import java.io.DataInput; 040import java.io.DataOutput; 041import java.io.IOException; 042import java.io.InvalidObjectException; 043import java.io.ObjectStreamException; 044import java.io.Serializable; 045import java.math.BigDecimal; 046import java.math.BigInteger; 047import java.math.RoundingMode; 048import java.util.Objects; 049 050import org.threeten.bp.format.DateTimeParseException; 051import org.threeten.bp.jdk8.Jdk8Methods; 052import org.threeten.bp.temporal.ChronoField; 053import org.threeten.bp.temporal.ChronoUnit; 054import org.threeten.bp.temporal.Temporal; 055import org.threeten.bp.temporal.TemporalAccessor; 056import org.threeten.bp.temporal.TemporalAdder; 057import org.threeten.bp.temporal.TemporalSubtractor; 058import org.threeten.bp.temporal.TemporalUnit; 059 060/** 061 * A duration between two instants on the time-line. 062 * <p> 063 * This class models a duration of time and is not tied to any instant. 064 * The model is of a directed duration, meaning that the duration may be negative. 065 * <p> 066 * A physical duration could be of infinite length. 067 * For practicality, the duration is stored with constraints similar to {@link Instant}. 068 * The duration uses nanosecond resolution with a maximum value of the seconds that can 069 * be held in a {@code long}. This is greater than the current estimated age of the universe. 070 * <p> 071 * The range of a duration requires the storage of a number larger than a {@code long}. 072 * To achieve this, the class stores a {@code long} representing seconds and an {@code int} 073 * representing nanosecond-of-second, which will always be between 0 and 999,999,999. 074 * <p> 075 * The duration is measured in "seconds", but these are not necessarily identical to 076 * the scientific "SI second" definition based on atomic clocks. 077 * This difference only impacts durations measured near a leap-second and should not affect 078 * most applications. 079 * See {@link Instant} for a discussion as to the meaning of the second and time-scales. 080 * 081 * <h3>Specification for implementors</h3> 082 * This class is immutable and thread-safe. 083 */ 084public final class Duration 085 implements TemporalAdder, TemporalSubtractor, Comparable<Duration>, Serializable { 086 087 /** 088 * Constant for a duration of zero. 089 */ 090 public static final Duration ZERO = new Duration(0, 0); 091 /** 092 * Serialization version. 093 */ 094 private static final long serialVersionUID = 3078945930695997490L; 095 /** 096 * Constant for nanos per second. 097 */ 098 private static final int NANOS_PER_SECOND = 1000_000_000; 099 /** 100 * Constant for nanos per second. 101 */ 102 private static final BigInteger BI_NANOS_PER_SECOND = BigInteger.valueOf(NANOS_PER_SECOND); 103 104 /** 105 * The number of seconds in the duration. 106 */ 107 private final long seconds; 108 /** 109 * The number of nanoseconds in the duration, expressed as a fraction of the 110 * number of seconds. This is always positive, and never exceeds 999,999,999. 111 */ 112 private final int nanos; 113 114 //----------------------------------------------------------------------- 115 /** 116 * Obtains an instance of {@code Duration} from a number of seconds. 117 * <p> 118 * The nanosecond in second field is set to zero. 119 * 120 * @param seconds the number of seconds, positive or negative 121 * @return a {@code Duration}, not null 122 */ 123 public static Duration ofSeconds(long seconds) { 124 return create(seconds, 0); 125 } 126 127 /** 128 * Obtains an instance of {@code Duration} from a number of seconds 129 * and an adjustment in nanoseconds. 130 * <p> 131 * This method allows an arbitrary number of nanoseconds to be passed in. 132 * The factory will alter the values of the second and nanosecond in order 133 * to ensure that the stored nanosecond is in the range 0 to 999,999,999. 134 * For example, the following will result in the exactly the same duration: 135 * <pre> 136 * Duration.ofSeconds(3, 1); 137 * Duration.ofSeconds(4, -999_999_999); 138 * Duration.ofSeconds(2, 1000_000_001); 139 * </pre> 140 * 141 * @param seconds the number of seconds, positive or negative 142 * @param nanoAdjustment the nanosecond adjustment to the number of seconds, positive or negative 143 * @return a {@code Duration}, not null 144 * @throws ArithmeticException if the adjustment causes the seconds to exceed the capacity of {@code Duration} 145 */ 146 public static Duration ofSeconds(long seconds, long nanoAdjustment) { 147 long secs = Jdk8Methods.safeAdd(seconds, Jdk8Methods.floorDiv(nanoAdjustment, NANOS_PER_SECOND)); 148 int nos = Jdk8Methods.floorMod(nanoAdjustment, NANOS_PER_SECOND); 149 return create(secs, nos); 150 } 151 152 //----------------------------------------------------------------------- 153 /** 154 * Obtains an instance of {@code Duration} from a number of milliseconds. 155 * <p> 156 * The seconds and nanoseconds are extracted from the specified milliseconds. 157 * 158 * @param millis the number of milliseconds, positive or negative 159 * @return a {@code Duration}, not null 160 */ 161 public static Duration ofMillis(long millis) { 162 long secs = millis / 1000; 163 int mos = (int) (millis % 1000); 164 if (mos < 0) { 165 mos += 1000; 166 secs--; 167 } 168 return create(secs, mos * 1000_000); 169 } 170 171 //----------------------------------------------------------------------- 172 /** 173 * Obtains an instance of {@code Duration} from a number of nanoseconds. 174 * <p> 175 * The seconds and nanoseconds are extracted from the specified nanoseconds. 176 * 177 * @param nanos the number of nanoseconds, positive or negative 178 * @return a {@code Duration}, not null 179 */ 180 public static Duration ofNanos(long nanos) { 181 long secs = nanos / NANOS_PER_SECOND; 182 int nos = (int) (nanos % NANOS_PER_SECOND); 183 if (nos < 0) { 184 nos += NANOS_PER_SECOND; 185 secs--; 186 } 187 return create(secs, nos); 188 } 189 190 //----------------------------------------------------------------------- 191 /** 192 * Obtains an instance of {@code Duration} from a number of standard length minutes. 193 * <p> 194 * The seconds are calculated based on the standard definition of a minute, 195 * where each minute is 60 seconds. 196 * The nanosecond in second field is set to zero. 197 * 198 * @param minutes the number of minutes, positive or negative 199 * @return a {@code Duration}, not null 200 * @throws ArithmeticException if the input minutes exceeds the capacity of {@code Duration} 201 */ 202 public static Duration ofMinutes(long minutes) { 203 return create(Jdk8Methods.safeMultiply(minutes, 60), 0); 204 } 205 206 /** 207 * Obtains an instance of {@code Duration} from a number of standard length hours. 208 * <p> 209 * The seconds are calculated based on the standard definition of an hour, 210 * where each hour is 3600 seconds. 211 * The nanosecond in second field is set to zero. 212 * 213 * @param hours the number of hours, positive or negative 214 * @return a {@code Duration}, not null 215 * @throws ArithmeticException if the input hours exceeds the capacity of {@code Duration} 216 */ 217 public static Duration ofHours(long hours) { 218 return create(Jdk8Methods.safeMultiply(hours, 3600), 0); 219 } 220 221 /** 222 * Obtains an instance of {@code Duration} from a number of standard 24 hour days. 223 * <p> 224 * The seconds are calculated based on the standard definition of a day, 225 * where each day is 86400 seconds which implies a 24 hour day. 226 * The nanosecond in second field is set to zero. 227 * 228 * @param days the number of days, positive or negative 229 * @return a {@code Duration}, not null 230 * @throws ArithmeticException if the input days exceeds the capacity of {@code Duration} 231 */ 232 public static Duration ofDays(long days) { 233 return create(Jdk8Methods.safeMultiply(days, 86400), 0); 234 } 235 236 //----------------------------------------------------------------------- 237 /** 238 * Obtains an instance of {@code Duration} from a duration in the specified unit. 239 * <p> 240 * The parameters represent the two parts of a phrase like '6 Hours'. For example: 241 * <pre> 242 * Duration.of(3, SECONDS); 243 * Duration.of(465, HOURS); 244 * </pre> 245 * Only a subset of units are accepted by this method. 246 * The unit must either have an {@link TemporalUnit#isDurationEstimated() exact duration} or 247 * be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception. 248 * 249 * @param amount the amount of the duration, measured in terms of the unit, positive or negative 250 * @param unit the unit that the duration is measured in, must have an exact duration, not null 251 * @return a {@code Duration}, not null 252 * @throws DateTimeException if the period unit has an estimated duration 253 * @throws ArithmeticException if a numeric overflow occurs 254 */ 255 public static Duration of(long amount, TemporalUnit unit) { 256 return ZERO.plus(amount, unit); 257 } 258 259 //----------------------------------------------------------------------- 260 /** 261 * Obtains an instance of {@code Duration} representing the duration between two instants. 262 * <p> 263 * A {@code Duration} represents a directed distance between two points on the time-line. 264 * As such, this method will return a negative duration if the end is before the start. 265 * To guarantee to obtain a positive duration call {@link #abs()} on the result of this factory. 266 * 267 * @param startInclusive the start instant, inclusive, not null 268 * @param endExclusive the end instant, exclusive, not null 269 * @return a {@code Duration}, not null 270 * @throws ArithmeticException if the calculation exceeds the capacity of {@code Duration} 271 */ 272 public static Duration between(TemporalAccessor startInclusive, TemporalAccessor endExclusive) { 273 long secs = Jdk8Methods.safeSubtract(endExclusive.getLong(INSTANT_SECONDS), startInclusive.getLong(INSTANT_SECONDS)); 274 long nanos = endExclusive.getLong(NANO_OF_SECOND) - startInclusive.getLong(NANO_OF_SECOND); 275 secs = Jdk8Methods.safeAdd(secs, Jdk8Methods.floorDiv(nanos, NANOS_PER_SECOND)); 276 nanos = Jdk8Methods.floorMod(nanos, NANOS_PER_SECOND); 277 return create(secs, (int) nanos); // safe from overflow 278 } 279 280 //----------------------------------------------------------------------- 281 /** 282 * Obtains an instance of {@code Duration} by parsing a text string. 283 * <p> 284 * This will parse the string produced by {@link #toString()} which is 285 * the ISO-8601 format {@code PTnS} where {@code n} is 286 * the number of seconds with optional decimal part. 287 * The number must consist of ASCII numerals. 288 * There must only be a negative sign at the start of the number and it can 289 * only be present if the value is less than zero. 290 * There must be at least one digit before any decimal point. 291 * There must be between 1 and 9 inclusive digits after any decimal point. 292 * The letters (P, T and S) will be accepted in upper or lower case. 293 * The decimal point may be either a dot or a comma. 294 * 295 * @param text the text to parse, not null 296 * @return a {@code Duration}, not null 297 * @throws DateTimeParseException if the text cannot be parsed to a {@code Duration} 298 */ 299 public static Duration parse(final CharSequence text) { 300 Objects.requireNonNull(text, "text"); 301 int len = text.length(); 302 if (len < 4 || 303 (text.charAt(0) != 'P' && text.charAt(0) != 'p') || 304 (text.charAt(1) != 'T' && text.charAt(1) != 't') || 305 (text.charAt(len - 1) != 'S' && text.charAt(len - 1) != 's') || 306 (len == 5 && text.charAt(2) == '-' && text.charAt(3) == '0')) { 307 throw new DateTimeParseException("Duration could not be parsed: " + text, text, 0); 308 } 309 String numberText = text.subSequence(2, len - 1).toString().replace(',', '.'); 310 if (numberText.charAt(0) == '+') { 311 throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2); 312 } 313 int dot = numberText.indexOf('.'); 314 try { 315 if (dot == -1) { 316 // no decimal places 317 if (numberText.startsWith("-0")) { 318 throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2); 319 } 320 return create(Long.parseLong(numberText), 0); 321 } 322 // decimal places 323 boolean negative = false; 324 if (numberText.charAt(0) == '-') { 325 negative = true; 326 } 327 long secs = Long.parseLong(numberText.substring(0, dot)); 328 numberText = numberText.substring(dot + 1); 329 len = numberText.length(); 330 if (len == 0 || len > 9 || numberText.charAt(0) == '-' || numberText.charAt(0) == '+') { 331 throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2); 332 } 333 int nanos = Integer.parseInt(numberText); 334 switch (len) { 335 case 1: 336 nanos *= 100000000; 337 break; 338 case 2: 339 nanos *= 10000000; 340 break; 341 case 3: 342 nanos *= 1000000; 343 break; 344 case 4: 345 nanos *= 100000; 346 break; 347 case 5: 348 nanos *= 10000; 349 break; 350 case 6: 351 nanos *= 1000; 352 break; 353 case 7: 354 nanos *= 100; 355 break; 356 case 8: 357 nanos *= 10; 358 break; 359 } 360 return negative ? ofSeconds(secs, -nanos) : create(secs, nanos); 361 362 } catch (ArithmeticException | NumberFormatException ex) { 363 throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2, ex); 364 } 365 } 366 367 //----------------------------------------------------------------------- 368 /** 369 * Obtains an instance of {@code Duration} using seconds and nanoseconds. 370 * 371 * @param seconds the length of the duration in seconds, positive or negative 372 * @param nanoAdjustment the nanosecond adjustment within the second, from 0 to 999,999,999 373 */ 374 private static Duration create(long seconds, int nanoAdjustment) { 375 if ((seconds | nanoAdjustment) == 0) { 376 return ZERO; 377 } 378 return new Duration(seconds, nanoAdjustment); 379 } 380 381 /** 382 * Constructs an instance of {@code Duration} using seconds and nanoseconds. 383 * 384 * @param seconds the length of the duration in seconds, positive or negative 385 * @param nanos the nanoseconds within the second, from 0 to 999,999,999 386 */ 387 private Duration(long seconds, int nanos) { 388 super(); 389 this.seconds = seconds; 390 this.nanos = nanos; 391 } 392 393 //----------------------------------------------------------------------- 394 /** 395 * Checks if this duration is zero length. 396 * <p> 397 * A {@code Duration} represents a directed distance between two points on 398 * the time-line and can therefore be positive, zero or negative. 399 * This method checks whether the length is zero. 400 * 401 * @return true if this duration has a total length equal to zero 402 */ 403 public boolean isZero() { 404 return (seconds | nanos) == 0; 405 } 406 407 /** 408 * Checks if this duration is positive, excluding zero. 409 * <p> 410 * A {@code Duration} represents a directed distance between two points on 411 * the time-line and can therefore be positive, zero or negative. 412 * This method checks whether the length is greater than zero. 413 * 414 * @return true if this duration has a total length greater than zero 415 */ 416 public boolean isPositive() { 417 return seconds >= 0 && ((seconds | nanos) != 0); 418 } 419 420 /** 421 * Checks if this duration is negative, excluding zero. 422 * <p> 423 * A {@code Duration} represents a directed distance between two points on 424 * the time-line and can therefore be positive, zero or negative. 425 * This method checks whether the length is less than zero. 426 * 427 * @return true if this duration has a total length less than zero 428 */ 429 public boolean isNegative() { 430 return seconds < 0; 431 } 432 433 //----------------------------------------------------------------------- 434 /** 435 * Gets the number of seconds in this duration. 436 * <p> 437 * The length of the duration is stored using two fields - seconds and nanoseconds. 438 * The nanoseconds part is a value from 0 to 999,999,999 that is an adjustment to 439 * the length in seconds. 440 * The total duration is defined by calling this method and {@link #getNano()}. 441 * <p> 442 * A {@code Duration} represents a directed distance between two points on the time-line. 443 * A negative duration is expressed by the negative sign of the seconds part. 444 * A duration of -1 nanosecond is stored as -1 seconds plus 999,999,999 nanoseconds. 445 * 446 * @return the whole seconds part of the length of the duration, positive or negative 447 */ 448 public long getSeconds() { 449 return seconds; 450 } 451 452 /** 453 * Gets the number of nanoseconds within the second in this duration. 454 * <p> 455 * The length of the duration is stored using two fields - seconds and nanoseconds. 456 * The nanoseconds part is a value from 0 to 999,999,999 that is an adjustment to 457 * the length in seconds. 458 * The total duration is defined by calling this method and {@link #getSeconds()}. 459 * <p> 460 * A {@code Duration} represents a directed distance between two points on the time-line. 461 * A negative duration is expressed by the negative sign of the seconds part. 462 * A duration of -1 nanosecond is stored as -1 seconds plus 999,999,999 nanoseconds. 463 * 464 * @return the nanoseconds within the second part of the length of the duration, from 0 to 999,999,999 465 */ 466 public int getNano() { 467 return nanos; 468 } 469 470 //----------------------------------------------------------------------- 471 /** 472 * Returns a copy of this duration with the specified duration added. 473 * <p> 474 * This instance is immutable and unaffected by this method call. 475 * 476 * @param duration the duration to add, positive or negative, not null 477 * @return a {@code Duration} based on this duration with the specified duration added, not null 478 * @throws ArithmeticException if numeric overflow occurs 479 */ 480 public Duration plus(Duration duration) { 481 return plus(duration.getSeconds(), duration.getNano()); 482 } 483 484 /** 485 * Returns a copy of this duration with the specified duration added. 486 * <p> 487 * The duration amount is measured in terms of the specified unit. 488 * Only a subset of units are accepted by this method. 489 * The unit must either have an {@link TemporalUnit#isDurationEstimated() exact duration} or 490 * be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception. 491 * <p> 492 * This instance is immutable and unaffected by this method call. 493 * 494 * @param amountToAdd the amount of the period, measured in terms of the unit, positive or negative 495 * @param unit the unit that the period is measured in, must have an exact duration, not null 496 * @return a {@code Duration} based on this duration with the specified duration added, not null 497 * @throws ArithmeticException if numeric overflow occurs 498 */ 499 public Duration plus(long amountToAdd, TemporalUnit unit) { 500 Objects.requireNonNull(unit, "unit"); 501 if (unit == DAYS) { 502 return plus(Jdk8Methods.safeMultiply(amountToAdd, SECONDS_PER_DAY), 0); 503 } 504 if (unit.isDurationEstimated()) { 505 throw new DateTimeException("Unit must not have an estimated duration"); 506 } 507 if (amountToAdd == 0) { 508 return this; 509 } 510 if (unit instanceof ChronoUnit) { 511 switch ((ChronoUnit) unit) { 512 case NANOS: return plusNanos(amountToAdd); 513 case MICROS: return plusSeconds((amountToAdd / (1000_000L * 1000)) * 1000).plusNanos((amountToAdd % (1000_000L * 1000)) * 1000); 514 case MILLIS: return plusMillis(amountToAdd); 515 case SECONDS: return plusSeconds(amountToAdd); 516 } 517 return plusSeconds(Jdk8Methods.safeMultiply(unit.getDuration().seconds, amountToAdd)); 518 } 519 Duration duration = unit.getDuration().multipliedBy(amountToAdd); 520 return plusSeconds(duration.getSeconds()).plusNanos(duration.getNano()); 521 } 522 523 //----------------------------------------------------------------------- 524 /** 525 * Returns a copy of this duration with the specified duration in seconds added. 526 * <p> 527 * This instance is immutable and unaffected by this method call. 528 * 529 * @param secondsToAdd the seconds to add, positive or negative 530 * @return a {@code Duration} based on this duration with the specified seconds added, not null 531 * @throws ArithmeticException if numeric overflow occurs 532 */ 533 public Duration plusSeconds(long secondsToAdd) { 534 return plus(secondsToAdd, 0); 535 } 536 537 /** 538 * Returns a copy of this duration with the specified duration in milliseconds added. 539 * <p> 540 * This instance is immutable and unaffected by this method call. 541 * 542 * @param millisToAdd the milliseconds to add, positive or negative 543 * @return a {@code Duration} based on this duration with the specified milliseconds added, not null 544 * @throws ArithmeticException if numeric overflow occurs 545 */ 546 public Duration plusMillis(long millisToAdd) { 547 return plus(millisToAdd / 1000, (millisToAdd % 1000) * 1000_000); 548 } 549 550 /** 551 * Returns a copy of this duration with the specified duration in nanoseconds added. 552 * <p> 553 * This instance is immutable and unaffected by this method call. 554 * 555 * @param nanosToAdd the nanoseconds to add, positive or negative 556 * @return a {@code Duration} based on this duration with the specified nanoseconds added, not null 557 * @throws ArithmeticException if numeric overflow occurs 558 */ 559 public Duration plusNanos(long nanosToAdd) { 560 return plus(0, nanosToAdd); 561 } 562 563 /** 564 * Returns a copy of this duration with the specified duration added. 565 * <p> 566 * This instance is immutable and unaffected by this method call. 567 * 568 * @param secondsToAdd the seconds to add, positive or negative 569 * @param nanosToAdd the nanos to add, positive or negative 570 * @return a {@code Duration} based on this duration with the specified seconds added, not null 571 * @throws ArithmeticException if numeric overflow occurs 572 */ 573 private Duration plus(long secondsToAdd, long nanosToAdd) { 574 if ((secondsToAdd | nanosToAdd) == 0) { 575 return this; 576 } 577 long epochSec = Jdk8Methods.safeAdd(seconds, secondsToAdd); 578 epochSec = Jdk8Methods.safeAdd(epochSec, nanosToAdd / NANOS_PER_SECOND); 579 nanosToAdd = nanosToAdd % NANOS_PER_SECOND; 580 long nanoAdjustment = nanos + nanosToAdd; // safe int+NANOS_PER_SECOND 581 return ofSeconds(epochSec, nanoAdjustment); 582 } 583 584 //----------------------------------------------------------------------- 585 /** 586 * Returns a copy of this duration with the specified duration subtracted. 587 * <p> 588 * This instance is immutable and unaffected by this method call. 589 * 590 * @param duration the duration to subtract, positive or negative, not null 591 * @return a {@code Duration} based on this duration with the specified duration subtracted, not null 592 * @throws ArithmeticException if numeric overflow occurs 593 */ 594 public Duration minus(Duration duration) { 595 long secsToSubtract = duration.getSeconds(); 596 int nanosToSubtract = duration.getNano(); 597 if (secsToSubtract == Long.MIN_VALUE) { 598 return plus(Long.MAX_VALUE, -nanosToSubtract).plus(1, 0); 599 } 600 return plus(-secsToSubtract, -nanosToSubtract); 601 } 602 603 /** 604 * Returns a copy of this duration with the specified duration subtracted. 605 * <p> 606 * The duration amount is measured in terms of the specified unit. 607 * Only a subset of units are accepted by this method. 608 * The unit must either have an {@link TemporalUnit#isDurationEstimated() exact duration} or 609 * be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception. 610 * <p> 611 * This instance is immutable and unaffected by this method call. 612 * 613 * @param amountToSubtract the amount of the period, measured in terms of the unit, positive or negative 614 * @param unit the unit that the period is measured in, must have an exact duration, not null 615 * @return a {@code Duration} based on this duration with the specified duration subtracted, not null 616 * @throws ArithmeticException if numeric overflow occurs 617 */ 618 public Duration minus(long amountToSubtract, TemporalUnit unit) { 619 return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit)); 620 } 621 622 //----------------------------------------------------------------------- 623 /** 624 * Returns a copy of this duration with the specified duration in seconds subtracted. 625 * <p> 626 * This instance is immutable and unaffected by this method call. 627 * 628 * @param secondsToSubtract the seconds to subtract, positive or negative 629 * @return a {@code Duration} based on this duration with the specified seconds subtracted, not null 630 * @throws ArithmeticException if numeric overflow occurs 631 */ 632 public Duration minusSeconds(long secondsToSubtract) { 633 return (secondsToSubtract == Long.MIN_VALUE ? plusSeconds(Long.MAX_VALUE).plusSeconds(1) : plusSeconds(-secondsToSubtract)); 634 } 635 636 /** 637 * Returns a copy of this duration with the specified duration in milliseconds subtracted. 638 * <p> 639 * This instance is immutable and unaffected by this method call. 640 * 641 * @param millisToSubtract the milliseconds to subtract, positive or negative 642 * @return a {@code Duration} based on this duration with the specified milliseconds subtracted, not null 643 * @throws ArithmeticException if numeric overflow occurs 644 */ 645 public Duration minusMillis(long millisToSubtract) { 646 return (millisToSubtract == Long.MIN_VALUE ? plusMillis(Long.MAX_VALUE).plusMillis(1) : plusMillis(-millisToSubtract)); 647 } 648 649 /** 650 * Returns a copy of this duration with the specified duration in nanoseconds subtracted. 651 * <p> 652 * This instance is immutable and unaffected by this method call. 653 * 654 * @param nanosToSubtract the nanoseconds to subtract, positive or negative 655 * @return a {@code Duration} based on this duration with the specified nanoseconds subtracted, not null 656 * @throws ArithmeticException if numeric overflow occurs 657 */ 658 public Duration minusNanos(long nanosToSubtract) { 659 return (nanosToSubtract == Long.MIN_VALUE ? plusNanos(Long.MAX_VALUE).plusNanos(1) : plusNanos(-nanosToSubtract)); 660 } 661 662 //----------------------------------------------------------------------- 663 /** 664 * Returns a copy of this duration multiplied by the scalar. 665 * <p> 666 * This instance is immutable and unaffected by this method call. 667 * 668 * @param multiplicand the value to multiply the duration by, positive or negative 669 * @return a {@code Duration} based on this duration multiplied by the specified scalar, not null 670 * @throws ArithmeticException if numeric overflow occurs 671 */ 672 public Duration multipliedBy(long multiplicand) { 673 if (multiplicand == 0) { 674 return ZERO; 675 } 676 if (multiplicand == 1) { 677 return this; 678 } 679 return create(toSeconds().multiply(BigDecimal.valueOf(multiplicand))); 680 } 681 682 /** 683 * Returns a copy of this duration divided by the specified value. 684 * <p> 685 * This instance is immutable and unaffected by this method call. 686 * 687 * @param divisor the value to divide the duration by, positive or negative, not zero 688 * @return a {@code Duration} based on this duration divided by the specified divisor, not null 689 * @throws ArithmeticException if the divisor is zero 690 * @throws ArithmeticException if numeric overflow occurs 691 */ 692 public Duration dividedBy(long divisor) { 693 if (divisor == 0) { 694 throw new ArithmeticException("Cannot divide by zero"); 695 } 696 if (divisor == 1) { 697 return this; 698 } 699 return create(toSeconds().divide(BigDecimal.valueOf(divisor), RoundingMode.DOWN)); 700 } 701 702 /** 703 * Converts this duration to the total length in seconds and 704 * fractional nanoseconds expressed as a {@code BigDecimal}. 705 * 706 * @return the total length of the duration in seconds, with a scale of 9, not null 707 */ 708 private BigDecimal toSeconds() { 709 return BigDecimal.valueOf(seconds).add(BigDecimal.valueOf(nanos, 9)); 710 } 711 712 /** 713 * Creates an instance of {@code Duration} from a number of seconds. 714 * 715 * @param seconds the number of seconds, up to scale 9, positive or negative 716 * @return a {@code Duration}, not null 717 * @throws ArithmeticException if numeric overflow occurs 718 */ 719 private static Duration create(BigDecimal seconds) { 720 BigInteger nanos = seconds.movePointRight(9).toBigIntegerExact(); 721 BigInteger[] divRem = nanos.divideAndRemainder(BI_NANOS_PER_SECOND); 722 if (divRem[0].bitLength() > 63) { 723 throw new ArithmeticException("Exceeds capacity of Duration: " + nanos); 724 } 725 return ofSeconds(divRem[0].longValue(), divRem[1].intValue()); 726 } 727 728 //----------------------------------------------------------------------- 729 /** 730 * Returns a copy of this duration with the length negated. 731 * <p> 732 * This method swaps the sign of the total length of this duration. 733 * For example, {@code PT1.3S} will be returned as {@code PT-1.3S}. 734 * <p> 735 * This instance is immutable and unaffected by this method call. 736 * 737 * @return a {@code Duration} based on this duration with the amount negated, not null 738 * @throws ArithmeticException if numeric overflow occurs 739 */ 740 public Duration negated() { 741 return multipliedBy(-1); 742 } 743 744 /** 745 * Returns a copy of this duration with a positive length. 746 * <p> 747 * This method returns a positive duration by effectively removing the sign from any negative total length. 748 * For example, {@code PT-1.3S} will be returned as {@code PT1.3S}. 749 * <p> 750 * This instance is immutable and unaffected by this method call. 751 * 752 * @return a {@code Duration} based on this duration with an absolute length, not null 753 * @throws ArithmeticException if numeric overflow occurs 754 */ 755 public Duration abs() { 756 return isNegative() ? negated() : this; 757 } 758 759 //------------------------------------------------------------------------- 760 /** 761 * Adds this duration to the specified temporal object. 762 * <p> 763 * This returns a temporal object of the same observable type as the input 764 * with this duration added. 765 * <p> 766 * In most cases, it is clearer to reverse the calling pattern by using 767 * {@link Temporal#plus(TemporalAdder)}. 768 * <pre> 769 * // these two lines are equivalent, but the second approach is recommended 770 * dateTime = thisDuration.addTo(dateTime); 771 * dateTime = dateTime.plus(thisDuration); 772 * </pre> 773 * <p> 774 * A {@code Duration} can only be added to a {@code Temporal} that 775 * represents an instant and can supply {@link ChronoField#INSTANT_SECONDS}. 776 * <p> 777 * This instance is immutable and unaffected by this method call. 778 * 779 * @param temporal the temporal object to adjust, not null 780 * @return an object of the same type with the adjustment made, not null 781 * @throws DateTimeException if unable to add 782 * @throws ArithmeticException if numeric overflow occurs 783 */ 784 @Override 785 public Temporal addTo(Temporal temporal) { 786 long instantSecs = temporal.getLong(INSTANT_SECONDS); 787 long instantNanos = temporal.getLong(NANO_OF_SECOND); 788 instantSecs = Jdk8Methods.safeAdd(instantSecs, seconds); 789 instantNanos = Jdk8Methods.safeAdd(instantNanos, nanos); 790 instantSecs = Jdk8Methods.safeAdd(instantSecs, Jdk8Methods.floorDiv(instantNanos, NANOS_PER_SECOND)); 791 instantNanos = Jdk8Methods.floorMod(instantNanos, NANOS_PER_SECOND); 792 return temporal.with(INSTANT_SECONDS, instantSecs).with(NANO_OF_SECOND, instantNanos); 793 } 794 795 /** 796 * Subtracts this duration from the specified temporal object. 797 * <p> 798 * This returns a temporal object of the same observable type as the input 799 * with this duration subtracted. 800 * <p> 801 * In most cases, it is clearer to reverse the calling pattern by using 802 * {@link Temporal#minus(TemporalSubtractor)}. 803 * <pre> 804 * // these two lines are equivalent, but the second approach is recommended 805 * dateTime = thisDuration.subtractFrom(dateTime); 806 * dateTime = dateTime.minus(thisDuration); 807 * </pre> 808 * <p> 809 * A {@code Duration} can only be subtracted from a {@code Temporal} that 810 * represents an instant and can supply {@link ChronoField#INSTANT_SECONDS}. 811 * <p> 812 * This instance is immutable and unaffected by this method call. 813 * 814 * @param temporal the temporal object to adjust, not null 815 * @return an object of the same type with the adjustment made, not null 816 * @throws DateTimeException if unable to subtract 817 * @throws ArithmeticException if numeric overflow occurs 818 */ 819 @Override 820 public Temporal subtractFrom(Temporal temporal) { 821 long instantSecs = temporal.getLong(INSTANT_SECONDS); 822 long instantNanos = temporal.getLong(NANO_OF_SECOND); 823 instantSecs = Jdk8Methods.safeSubtract(instantSecs, seconds); 824 instantNanos = Jdk8Methods.safeSubtract(instantNanos, nanos); 825 instantSecs = Jdk8Methods.safeAdd(instantSecs, Jdk8Methods.floorDiv(instantNanos, NANOS_PER_SECOND)); 826 instantNanos = Jdk8Methods.floorMod(instantNanos, NANOS_PER_SECOND); 827 return temporal.with(INSTANT_SECONDS, instantSecs).with(NANO_OF_SECOND, instantNanos); 828 } 829 830 //----------------------------------------------------------------------- 831 /** 832 * Converts this duration to the total length in milliseconds. 833 * <p> 834 * If this duration is too large to fit in a {@code long} milliseconds, then an 835 * exception is thrown. 836 * <p> 837 * If this duration has greater than millisecond precision, then the conversion 838 * will drop any excess precision information as though the amount in nanoseconds 839 * was subject to integer division by one million. 840 * 841 * @return the total length of the duration in milliseconds 842 * @throws ArithmeticException if numeric overflow occurs 843 */ 844 public long toMillis() { 845 long millis = Jdk8Methods.safeMultiply(seconds, 1000); 846 millis = Jdk8Methods.safeAdd(millis, nanos / 1000_000); 847 return millis; 848 } 849 850 /** 851 * Converts this duration to the total length in nanoseconds expressed as a {@code long}. 852 * <p> 853 * If this duration is too large to fit in a {@code long} nanoseconds, then an 854 * exception is thrown. 855 * 856 * @return the total length of the duration in nanoseconds 857 * @throws ArithmeticException if numeric overflow occurs 858 */ 859 public long toNanos() { 860 long millis = Jdk8Methods.safeMultiply(seconds, 1000_000_000); 861 millis = Jdk8Methods.safeAdd(millis, nanos); 862 return millis; 863 } 864 865 //----------------------------------------------------------------------- 866 /** 867 * Compares this duration to the specified {@code Duration}. 868 * <p> 869 * The comparison is based on the total length of the durations. 870 * It is "consistent with equals", as defined by {@link Comparable}. 871 * 872 * @param otherDuration the other duration to compare to, not null 873 * @return the comparator value, negative if less, positive if greater 874 */ 875 @Override 876 public int compareTo(Duration otherDuration) { 877 int cmp = Long.compare(seconds, otherDuration.seconds); 878 if (cmp != 0) { 879 return cmp; 880 } 881 return nanos - otherDuration.nanos; 882 } 883 884 /** 885 * Checks if this duration is greater than the specified {@code Duration}. 886 * <p> 887 * The comparison is based on the total length of the durations. 888 * 889 * @param otherDuration the other duration to compare to, not null 890 * @return true if this duration is greater than the specified duration 891 */ 892 public boolean isGreaterThan(Duration otherDuration) { 893 return compareTo(otherDuration) > 0; 894 } 895 896 /** 897 * Checks if this duration is less than the specified {@code Duration}. 898 * <p> 899 * The comparison is based on the total length of the durations. 900 * 901 * @param otherDuration the other duration to compare to, not null 902 * @return true if this duration is less than the specified duration 903 */ 904 public boolean isLessThan(Duration otherDuration) { 905 return compareTo(otherDuration) < 0; 906 } 907 908 //----------------------------------------------------------------------- 909 /** 910 * Checks if this duration is equal to the specified {@code Duration}. 911 * <p> 912 * The comparison is based on the total length of the durations. 913 * 914 * @param otherDuration the other duration, null returns false 915 * @return true if the other duration is equal to this one 916 */ 917 @Override 918 public boolean equals(Object otherDuration) { 919 if (this == otherDuration) { 920 return true; 921 } 922 if (otherDuration instanceof Duration) { 923 Duration other = (Duration) otherDuration; 924 return this.seconds == other.seconds && 925 this.nanos == other.nanos; 926 } 927 return false; 928 } 929 930 /** 931 * A hash code for this duration. 932 * 933 * @return a suitable hash code 934 */ 935 @Override 936 public int hashCode() { 937 return ((int) (seconds ^ (seconds >>> 32))) + (51 * nanos); 938 } 939 940 //----------------------------------------------------------------------- 941 /** 942 * A string representation of this duration using ISO-8601 seconds 943 * based representation, such as {@code PT12.345S}. 944 * <p> 945 * The format of the returned string will be {@code PTnS} where n is 946 * the seconds and fractional seconds of the duration. 947 * 948 * @return an ISO-8601 representation of this duration, not null 949 */ 950 @Override 951 public String toString() { 952 StringBuilder buf = new StringBuilder(24); 953 buf.append("PT"); 954 if (seconds < 0 && nanos > 0) { 955 if (seconds == -1) { 956 buf.append("-0"); 957 } else { 958 buf.append(seconds + 1); 959 } 960 } else { 961 buf.append(seconds); 962 } 963 if (nanos > 0) { 964 int pos = buf.length(); 965 if (seconds < 0) { 966 buf.append(2 * NANOS_PER_SECOND - nanos); 967 } else { 968 buf.append(nanos + NANOS_PER_SECOND); 969 } 970 while (buf.charAt(buf.length() - 1) == '0') { 971 buf.setLength(buf.length() - 1); 972 } 973 buf.setCharAt(pos, '.'); 974 } 975 buf.append('S'); 976 return buf.toString(); 977 } 978 979 //----------------------------------------------------------------------- 980 private Object writeReplace() { 981 return new Ser(Ser.DURATION_TYPE, this); 982 } 983 984 /** 985 * Defend against malicious streams. 986 * @return never 987 * @throws InvalidObjectException always 988 */ 989 private Object readResolve() throws ObjectStreamException { 990 throw new InvalidObjectException("Deserialization via serialization delegate"); 991 } 992 993 void writeExternal(DataOutput out) throws IOException { 994 out.writeLong(seconds); 995 out.writeInt(nanos); 996 } 997 998 static Duration readExternal(DataInput in) throws IOException { 999 long seconds = in.readLong(); 1000 int nanos = in.readInt(); 1001 return Duration.ofSeconds(seconds, nanos); 1002 } 1003 1004}