1 /* 2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * This file is available under and governed by the GNU General Public 28 * License version 2 only, as published by the Free Software Foundation. 29 * However, the following notice accompanied the original version of this 30 * file: 31 * 32 * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos 33 * 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions are met: 38 * 39 * * Redistributions of source code must retain the above copyright notice, 40 * this list of conditions and the following disclaimer. 41 * 42 * * Redistributions in binary form must reproduce the above copyright notice, 43 * this list of conditions and the following disclaimer in the documentation 44 * and/or other materials provided with the distribution. 45 * 46 * * Neither the name of JSR-310 nor the names of its contributors 47 * may be used to endorse or promote products derived from this software 48 * without specific prior written permission. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 54 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 55 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 56 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 57 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 58 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 59 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 60 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61 */ 62 package java.time; 63 64 import java.io.IOException; 65 import java.io.ObjectInputStream; 66 import static java.time.LocalTime.NANOS_PER_MINUTE; 67 import static java.time.LocalTime.NANOS_PER_SECOND; 68 69 import java.io.Serializable; 70 import java.util.Objects; 71 import java.util.TimeZone; 72 import sun.misc.VM; 73 74 /** 75 * A clock providing access to the current instant, date and time using a time-zone. 76 * <p> 77 * Instances of this class are used to find the current instant, which can be 78 * interpreted using the stored time-zone to find the current date and time. 79 * As such, a clock can be used instead of {@link System#currentTimeMillis()} 80 * and {@link TimeZone#getDefault()}. 81 * <p> 82 * Use of a {@code Clock} is optional. All key date-time classes also have a 83 * {@code now()} factory method that uses the system clock in the default time zone. 84 * The primary purpose of this abstraction is to allow alternate clocks to be 85 * plugged in as and when required. Applications use an object to obtain the 86 * current time rather than a static method. This can simplify testing. 87 * <p> 88 * Best practice for applications is to pass a {@code Clock} into any method 89 * that requires the current instant. A dependency injection framework is one 90 * way to achieve this: 91 * <pre> 92 * public class MyBean { 93 * private Clock clock; // dependency inject 94 * ... 95 * public void process(LocalDate eventDate) { 96 * if (eventDate.isBefore(LocalDate.now(clock)) { 97 * ... 98 * } 99 * } 100 * } 101 * </pre> 102 * This approach allows an alternate clock, such as {@link #fixed(Instant, ZoneId) fixed} 103 * or {@link #offset(Clock, Duration) offset} to be used during testing. 104 * <p> 105 * The {@code system} factory methods provide clocks based on the best available 106 * system clock This may use {@link System#currentTimeMillis()}, or a higher 107 * resolution clock if one is available. 108 * 109 * @implSpec 110 * This abstract class must be implemented with care to ensure other classes operate correctly. 111 * All implementations that can be instantiated must be final, immutable and thread-safe. 112 * <p> 113 * The principal methods are defined to allow the throwing of an exception. 114 * In normal use, no exceptions will be thrown, however one possible implementation would be to 115 * obtain the time from a central time server across the network. Obviously, in this case the 116 * lookup could fail, and so the method is permitted to throw an exception. 117 * <p> 118 * The returned instants from {@code Clock} work on a time-scale that ignores leap seconds, 119 * as described in {@link Instant}. If the implementation wraps a source that provides leap 120 * second information, then a mechanism should be used to "smooth" the leap second. 121 * The Java Time-Scale mandates the use of UTC-SLS, however clock implementations may choose 122 * how accurate they are with the time-scale so long as they document how they work. 123 * Implementations are therefore not required to actually perform the UTC-SLS slew or to 124 * otherwise be aware of leap seconds. 125 * <p> 126 * Implementations should implement {@code Serializable} wherever possible and must 127 * document whether or not they do support serialization. 128 * 129 * @implNote 130 * The clock implementation provided here is based on {@link System#currentTimeMillis()}. 131 * That method provides little to no guarantee about the accuracy of the clock. 132 * Applications requiring a more accurate clock must implement this abstract class 133 * themselves using a different external clock, such as an NTP server. 134 * 135 * @since 1.8 136 */ 137 public abstract class Clock { 138 139 /** 140 * Obtains a clock that returns the current instant using the best available 141 * system clock, converting to date and time using the UTC time-zone. 142 * <p> 143 * This clock, rather than {@link #systemDefaultZone()}, should be used when 144 * you need the current instant without the date or time. 145 * <p> 146 * This clock is based on the best available system clock. 147 * This may use {@link System#currentTimeMillis()}, or a higher resolution 148 * clock if one is available. 149 * <p> 150 * Conversion from instant to date or time uses the {@linkplain ZoneOffset#UTC UTC time-zone}. 151 * <p> 152 * The returned implementation is immutable, thread-safe and {@code Serializable}. 153 * It is equivalent to {@code system(ZoneOffset.UTC)}. 154 * 155 * @return a clock that uses the best available system clock in the UTC zone, not null 156 */ 157 public static Clock systemUTC() { 158 return SystemClock.UTC; 159 } 160 161 /** 162 * Obtains a clock that returns the current instant using the best available 163 * system clock, converting to date and time using the default time-zone. 164 * <p> 165 * This clock is based on the best available system clock. 166 * This may use {@link System#currentTimeMillis()}, or a higher resolution 167 * clock if one is available. 168 * <p> 169 * Using this method hard codes a dependency to the default time-zone into your application. 170 * It is recommended to avoid this and use a specific time-zone whenever possible. 171 * The {@link #systemUTC() UTC clock} should be used when you need the current instant 172 * without the date or time. 173 * <p> 174 * The returned implementation is immutable, thread-safe and {@code Serializable}. 175 * It is equivalent to {@code system(ZoneId.systemDefault())}. 176 * 177 * @return a clock that uses the best available system clock in the default zone, not null 178 * @see ZoneId#systemDefault() 179 */ 180 public static Clock systemDefaultZone() { 181 return new SystemClock(ZoneId.systemDefault()); 182 } 183 184 /** 185 * Obtains a clock that returns the current instant using best available 186 * system clock. 187 * <p> 188 * This clock is based on the best available system clock. 189 * This may use {@link System#currentTimeMillis()}, or a higher resolution 190 * clock if one is available. 191 * <p> 192 * Conversion from instant to date or time uses the specified time-zone. 193 * <p> 194 * The returned implementation is immutable, thread-safe and {@code Serializable}. 195 * 196 * @param zone the time-zone to use to convert the instant to date-time, not null 197 * @return a clock that uses the best available system clock in the specified zone, not null 198 */ 199 public static Clock system(ZoneId zone) { 200 Objects.requireNonNull(zone, "zone"); 201 if (zone == ZoneOffset.UTC) { 202 return SystemClock.UTC; 203 } 204 return new SystemClock(zone); 205 } 206 207 //------------------------------------------------------------------------- 208 /** 209 * Obtains a clock that returns the current instant ticking in whole seconds 210 * using best available system clock. 211 * <p> 212 * This clock will always have the nano-of-second field set to zero. 213 * This ensures that the visible time ticks in whole seconds. 214 * The underlying clock is the best available system clock, equivalent to 215 * using {@link #system(ZoneId)}. 216 * <p> 217 * Implementations may use a caching strategy for performance reasons. 218 * As such, it is possible that the start of the second observed via this 219 * clock will be later than that observed directly via the underlying clock. 220 * <p> 221 * The returned implementation is immutable, thread-safe and {@code Serializable}. 222 * It is equivalent to {@code tick(system(zone), Duration.ofSeconds(1))}. 223 * 224 * @param zone the time-zone to use to convert the instant to date-time, not null 225 * @return a clock that ticks in whole seconds using the specified zone, not null 226 */ 227 public static Clock tickSeconds(ZoneId zone) { 228 return new TickClock(system(zone), NANOS_PER_SECOND); 229 } 230 231 /** 232 * Obtains a clock that returns the current instant ticking in whole minutes 233 * using best available system clock. 234 * <p> 235 * This clock will always have the nano-of-second and second-of-minute fields set to zero. 236 * This ensures that the visible time ticks in whole minutes. 237 * The underlying clock is the best available system clock, equivalent to 238 * using {@link #system(ZoneId)}. 239 * <p> 240 * Implementations may use a caching strategy for performance reasons. 241 * As such, it is possible that the start of the minute observed via this 242 * clock will be later than that observed directly via the underlying clock. 243 * <p> 244 * The returned implementation is immutable, thread-safe and {@code Serializable}. 245 * It is equivalent to {@code tick(system(zone), Duration.ofMinutes(1))}. 246 * 247 * @param zone the time-zone to use to convert the instant to date-time, not null 248 * @return a clock that ticks in whole minutes using the specified zone, not null 249 */ 250 public static Clock tickMinutes(ZoneId zone) { 251 return new TickClock(system(zone), NANOS_PER_MINUTE); 252 } 253 254 /** 255 * Obtains a clock that returns instants from the specified clock truncated 256 * to the nearest occurrence of the specified duration. 257 * <p> 258 * This clock will only tick as per the specified duration. Thus, if the duration 259 * is half a second, the clock will return instants truncated to the half second. 260 * <p> 261 * The tick duration must be positive. If it has a part smaller than a whole 262 * millisecond, then the whole duration must divide into one second without 263 * leaving a remainder. All normal tick durations will match these criteria, 264 * including any multiple of hours, minutes, seconds and milliseconds, and 265 * sensible nanosecond durations, such as 20ns, 250,000ns and 500,000ns. 266 * <p> 267 * A duration of zero or one nanosecond would have no truncation effect. 268 * Passing one of these will return the underlying clock. 269 * <p> 270 * Implementations may use a caching strategy for performance reasons. 271 * As such, it is possible that the start of the requested duration observed 272 * via this clock will be later than that observed directly via the underlying clock. 273 * <p> 274 * The returned implementation is immutable, thread-safe and {@code Serializable} 275 * providing that the base clock is. 276 * 277 * @param baseClock the base clock to base the ticking clock on, not null 278 * @param tickDuration the duration of each visible tick, not negative, not null 279 * @return a clock that ticks in whole units of the duration, not null 280 * @throws IllegalArgumentException if the duration is negative, or has a 281 * part smaller than a whole millisecond such that the whole duration is not 282 * divisible into one second 283 * @throws ArithmeticException if the duration is too large to be represented as nanos 284 */ 285 public static Clock tick(Clock baseClock, Duration tickDuration) { 286 Objects.requireNonNull(baseClock, "baseClock"); 287 Objects.requireNonNull(tickDuration, "tickDuration"); 288 if (tickDuration.isNegative()) { 289 throw new IllegalArgumentException("Tick duration must not be negative"); 290 } 291 long tickNanos = tickDuration.toNanos(); 292 if (tickNanos % 1000_000 == 0) { 293 // ok, no fraction of millisecond 294 } else if (1000_000_000 % tickNanos == 0) { 295 // ok, divides into one second without remainder 296 } else { 297 throw new IllegalArgumentException("Invalid tick duration"); 298 } 299 if (tickNanos <= 1) { 300 return baseClock; 301 } 302 return new TickClock(baseClock, tickNanos); 303 } 304 305 //----------------------------------------------------------------------- 306 /** 307 * Obtains a clock that always returns the same instant. 308 * <p> 309 * This clock simply returns the specified instant. 310 * As such, it is not a clock in the conventional sense. 311 * The main use case for this is in testing, where the fixed clock ensures 312 * tests are not dependent on the current clock. 313 * <p> 314 * The returned implementation is immutable, thread-safe and {@code Serializable}. 315 * 316 * @param fixedInstant the instant to use as the clock, not null 317 * @param zone the time-zone to use to convert the instant to date-time, not null 318 * @return a clock that always returns the same instant, not null 319 */ 320 public static Clock fixed(Instant fixedInstant, ZoneId zone) { 321 Objects.requireNonNull(fixedInstant, "fixedInstant"); 322 Objects.requireNonNull(zone, "zone"); 323 return new FixedClock(fixedInstant, zone); 324 } 325 326 //------------------------------------------------------------------------- 327 /** 328 * Obtains a clock that returns instants from the specified clock with the 329 * specified duration added 330 * <p> 331 * This clock wraps another clock, returning instants that are later by the 332 * specified duration. If the duration is negative, the instants will be 333 * earlier than the current date and time. 334 * The main use case for this is to simulate running in the future or in the past. 335 * <p> 336 * A duration of zero would have no offsetting effect. 337 * Passing zero will return the underlying clock. 338 * <p> 339 * The returned implementation is immutable, thread-safe and {@code Serializable} 340 * providing that the base clock is. 341 * 342 * @param baseClock the base clock to add the duration to, not null 343 * @param offsetDuration the duration to add, not null 344 * @return a clock based on the base clock with the duration added, not null 345 */ 346 public static Clock offset(Clock baseClock, Duration offsetDuration) { 347 Objects.requireNonNull(baseClock, "baseClock"); 348 Objects.requireNonNull(offsetDuration, "offsetDuration"); 349 if (offsetDuration.equals(Duration.ZERO)) { 350 return baseClock; 351 } 352 return new OffsetClock(baseClock, offsetDuration); 353 } 354 355 //----------------------------------------------------------------------- 356 /** 357 * Constructor accessible by subclasses. 358 */ 359 protected Clock() { 360 } 361 362 //----------------------------------------------------------------------- 363 /** 364 * Gets the time-zone being used to create dates and times. 365 * <p> 366 * A clock will typically obtain the current instant and then convert that 367 * to a date or time using a time-zone. This method returns the time-zone used. 368 * 369 * @return the time-zone being used to interpret instants, not null 370 */ 371 public abstract ZoneId getZone(); 372 373 /** 374 * Returns a copy of this clock with a different time-zone. 375 * <p> 376 * A clock will typically obtain the current instant and then convert that 377 * to a date or time using a time-zone. This method returns a clock with 378 * similar properties but using a different time-zone. 379 * 380 * @param zone the time-zone to change to, not null 381 * @return a clock based on this clock with the specified time-zone, not null 382 */ 383 public abstract Clock withZone(ZoneId zone); 384 385 //------------------------------------------------------------------------- 386 /** 387 * Gets the current millisecond instant of the clock. 388 * <p> 389 * This returns the millisecond-based instant, measured from 1970-01-01T00:00Z (UTC). 390 * This is equivalent to the definition of {@link System#currentTimeMillis()}. 391 * <p> 392 * Most applications should avoid this method and use {@link Instant} to represent 393 * an instant on the time-line rather than a raw millisecond value. 394 * This method is provided to allow the use of the clock in high performance use cases 395 * where the creation of an object would be unacceptable. 396 * <p> 397 * The default implementation currently calls {@link #instant}. 398 * 399 * @return the current millisecond instant from this clock, measured from 400 * the Java epoch of 1970-01-01T00:00Z (UTC), not null 401 * @throws DateTimeException if the instant cannot be obtained, not thrown by most implementations 402 */ 403 public long millis() { 404 return instant().toEpochMilli(); 405 } 406 407 //----------------------------------------------------------------------- 408 /** 409 * Gets the current instant of the clock. 410 * <p> 411 * This returns an instant representing the current instant as defined by the clock. 412 * 413 * @return the current instant from this clock, not null 414 * @throws DateTimeException if the instant cannot be obtained, not thrown by most implementations 415 */ 416 public abstract Instant instant(); 417 418 //----------------------------------------------------------------------- 419 /** 420 * Checks if this clock is equal to another clock. 421 * <p> 422 * Clocks should override this method to compare equals based on 423 * their state and to meet the contract of {@link Object#equals}. 424 * If not overridden, the behavior is defined by {@link Object#equals} 425 * 426 * @param obj the object to check, null returns false 427 * @return true if this is equal to the other clock 428 */ 429 @Override 430 public boolean equals(Object obj) { 431 return super.equals(obj); 432 } 433 434 /** 435 * A hash code for this clock. 436 * <p> 437 * Clocks should override this method based on 438 * their state and to meet the contract of {@link Object#hashCode}. 439 * If not overridden, the behavior is defined by {@link Object#hashCode} 440 * 441 * @return a suitable hash code 442 */ 443 @Override 444 public int hashCode() { 445 return super.hashCode(); 446 } 447 448 //----------------------------------------------------------------------- 449 /** 450 * Implementation of a clock that always returns the latest time from 451 * {@link System#currentTimeMillis()}. 452 */ 453 static final class SystemClock extends Clock implements Serializable { 454 private static final long serialVersionUID = 6740630888130243051L; 455 private static final long OFFSET_SEED = 456 System.currentTimeMillis()/1000 - 1024; // initial offest 457 static final SystemClock UTC = new SystemClock(ZoneOffset.UTC); 458 459 private final ZoneId zone; 460 // We don't actually need a volatile here. 461 // We don't care if offset is set or read concurrently by multiple 462 // threads - we just need a value which is 'recent enough' - in other 463 // words something that has been updated at least once in the last 464 // 2^32 secs (~136 years). And even if we by chance see an invalid 465 // offset, the worst that can happen is that we will get a -1 value 466 // from getNanoTimeAdjustment, forcing us to update the offset 467 // once again. 468 private transient long offset; 469 470 SystemClock(ZoneId zone) { 471 this.zone = zone; 472 this.offset = OFFSET_SEED; 473 } 474 @Override 475 public ZoneId getZone() { 476 return zone; 477 } 478 @Override 479 public Clock withZone(ZoneId zone) { 480 if (zone.equals(this.zone)) { // intentional NPE 481 return this; 482 } 483 return new SystemClock(zone); 484 } 485 @Override 486 public long millis() { 487 // System.currentTimeMillis() and VM.getNanoTimeAdjustment(offset) 488 // use the same time source - System.currentTimeMillis() simply 489 // limits the resolution to milliseconds. 490 // So we take the faster path and call System.currentTimeMillis() 491 // directly - in order to avoid the performance penalty of 492 // VM.getNanoTimeAdjustment(offset) which is less efficient. 493 return System.currentTimeMillis(); 494 } 495 @Override 496 public Instant instant() { 497 // Take a local copy of offset. offset can be updated concurrently 498 // by other threads (even if we haven't made it volatile) so we will 499 // work with a local copy. 500 long localOffset = offset; 501 long adjustment = VM.getNanoTimeAdjustment(localOffset); 502 503 if (adjustment == -1) { 504 // -1 is a sentinel value returned by VM.getNanoTimeAdjustment 505 // when the offset it is given is too far off the current UTC 506 // time. In principle, this should not happen unless the 507 // JVM has run for more than ~136 years (not likely) or 508 // someone is fiddling with the system time, or the offset is 509 // by chance at 1ns in the future (very unlikely). 510 // We can easily recover from all these conditions by bringing 511 // back the offset in range and retry. 512 513 // bring back the offset in range. We use -1024 to make 514 // it more unlikely to hit the 1ns in the future condition. 515 localOffset = System.currentTimeMillis()/1000 - 1024; 516 517 // retry 518 adjustment = VM.getNanoTimeAdjustment(localOffset); 519 520 if (adjustment == -1) { 521 // Should not happen: we just recomputed a new offset. 522 // It should have fixed the issue. 523 throw new InternalError("Offset " + localOffset + " is not in range"); 524 } else { 525 // OK - recovery succeeded. Update the offset for the 526 // next call... 527 offset = localOffset; 528 } 529 } 530 return Instant.ofEpochSecond(localOffset, adjustment); 531 } 532 @Override 533 public boolean equals(Object obj) { 534 if (obj instanceof SystemClock) { 535 return zone.equals(((SystemClock) obj).zone); 536 } 537 return false; 538 } 539 @Override 540 public int hashCode() { 541 return zone.hashCode() + 1; 542 } 543 @Override 544 public String toString() { 545 return "SystemClock[" + zone + "]"; 546 } 547 private void readObject(ObjectInputStream is) 548 throws IOException, ClassNotFoundException { 549 // ensure that offset is initialized 550 is.defaultReadObject(); 551 offset = OFFSET_SEED; 552 } 553 } 554 555 //----------------------------------------------------------------------- 556 /** 557 * Implementation of a clock that always returns the same instant. 558 * This is typically used for testing. 559 */ 560 static final class FixedClock extends Clock implements Serializable { 561 private static final long serialVersionUID = 7430389292664866958L; 562 private final Instant instant; 563 private final ZoneId zone; 564 565 FixedClock(Instant fixedInstant, ZoneId zone) { 566 this.instant = fixedInstant; 567 this.zone = zone; 568 } 569 @Override 570 public ZoneId getZone() { 571 return zone; 572 } 573 @Override 574 public Clock withZone(ZoneId zone) { 575 if (zone.equals(this.zone)) { // intentional NPE 576 return this; 577 } 578 return new FixedClock(instant, zone); 579 } 580 @Override 581 public long millis() { 582 return instant.toEpochMilli(); 583 } 584 @Override 585 public Instant instant() { 586 return instant; 587 } 588 @Override 589 public boolean equals(Object obj) { 590 if (obj instanceof FixedClock) { 591 FixedClock other = (FixedClock) obj; 592 return instant.equals(other.instant) && zone.equals(other.zone); 593 } 594 return false; 595 } 596 @Override 597 public int hashCode() { 598 return instant.hashCode() ^ zone.hashCode(); 599 } 600 @Override 601 public String toString() { 602 return "FixedClock[" + instant + "," + zone + "]"; 603 } 604 } 605 606 //----------------------------------------------------------------------- 607 /** 608 * Implementation of a clock that adds an offset to an underlying clock. 609 */ 610 static final class OffsetClock extends Clock implements Serializable { 611 private static final long serialVersionUID = 2007484719125426256L; 612 private final Clock baseClock; 613 private final Duration offset; 614 615 OffsetClock(Clock baseClock, Duration offset) { 616 this.baseClock = baseClock; 617 this.offset = offset; 618 } 619 @Override 620 public ZoneId getZone() { 621 return baseClock.getZone(); 622 } 623 @Override 624 public Clock withZone(ZoneId zone) { 625 if (zone.equals(baseClock.getZone())) { // intentional NPE 626 return this; 627 } 628 return new OffsetClock(baseClock.withZone(zone), offset); 629 } 630 @Override 631 public long millis() { 632 return Math.addExact(baseClock.millis(), offset.toMillis()); 633 } 634 @Override 635 public Instant instant() { 636 return baseClock.instant().plus(offset); 637 } 638 @Override 639 public boolean equals(Object obj) { 640 if (obj instanceof OffsetClock) { 641 OffsetClock other = (OffsetClock) obj; 642 return baseClock.equals(other.baseClock) && offset.equals(other.offset); 643 } 644 return false; 645 } 646 @Override 647 public int hashCode() { 648 return baseClock.hashCode() ^ offset.hashCode(); 649 } 650 @Override 651 public String toString() { 652 return "OffsetClock[" + baseClock + "," + offset + "]"; 653 } 654 } 655 656 //----------------------------------------------------------------------- 657 /** 658 * Implementation of a clock that adds an offset to an underlying clock. 659 */ 660 static final class TickClock extends Clock implements Serializable { 661 private static final long serialVersionUID = 6504659149906368850L; 662 private final Clock baseClock; 663 private final long tickNanos; 664 665 TickClock(Clock baseClock, long tickNanos) { 666 this.baseClock = baseClock; 667 this.tickNanos = tickNanos; 668 } 669 @Override 670 public ZoneId getZone() { 671 return baseClock.getZone(); 672 } 673 @Override 674 public Clock withZone(ZoneId zone) { 675 if (zone.equals(baseClock.getZone())) { // intentional NPE 676 return this; 677 } 678 return new TickClock(baseClock.withZone(zone), tickNanos); 679 } 680 @Override 681 public long millis() { 682 long millis = baseClock.millis(); 683 return millis - Math.floorMod(millis, tickNanos / 1000_000L); 684 } 685 @Override 686 public Instant instant() { 687 if ((tickNanos % 1000_000) == 0) { 688 long millis = baseClock.millis(); 689 return Instant.ofEpochMilli(millis - Math.floorMod(millis, tickNanos / 1000_000L)); 690 } 691 Instant instant = baseClock.instant(); 692 long nanos = instant.getNano(); 693 long adjust = Math.floorMod(nanos, tickNanos); 694 return instant.minusNanos(adjust); 695 } 696 @Override 697 public boolean equals(Object obj) { 698 if (obj instanceof TickClock) { 699 TickClock other = (TickClock) obj; 700 return baseClock.equals(other.baseClock) && tickNanos == other.tickNanos; 701 } 702 return false; 703 } 704 @Override 705 public int hashCode() { 706 return baseClock.hashCode() ^ ((int) (tickNanos ^ (tickNanos >>> 32))); 707 } 708 @Override 709 public String toString() { 710 return "TickClock[" + baseClock + "," + Duration.ofNanos(tickNanos) + "]"; 711 } 712 } 713 714 }