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