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