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