1 /* 2 * Copyright (c) 2012, 2021, 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 java.io.ObjectStreamException; 67 68 import static java.time.LocalTime.NANOS_PER_MINUTE; 69 import static java.time.LocalTime.NANOS_PER_SECOND; 70 import static java.time.LocalTime.NANOS_PER_MILLI; 71 import java.io.Serializable; 72 import java.util.Objects; 73 import java.util.TimeZone; 74 import jdk.internal.misc.VM; 75 76 /** 77 * A clock providing access to the current instant, date and time using a time-zone. 78 * <p> 79 * Instances of this abstract class are used to access a pluggable representation of the 80 * current instant, which can be interpreted using the stored time-zone to find the 81 * current date and time. 82 * For example, {@code Clock} can be used instead of {@link System#currentTimeMillis()} 83 * and {@link TimeZone#getDefault()}. 84 * <p> 85 * Use of a {@code Clock} is optional. All key date-time classes also have a 86 * {@code now()} factory method that uses the system clock in the default time zone. 87 * The primary purpose of this abstraction is to allow alternate clocks to be 88 * plugged in as and when required. Applications use an object to obtain the 89 * current time rather than a static method. This can simplify testing. 90 * <p> 91 * As such, this abstract class does not guarantee the result actually represents the current instant 92 * on the time-line. Instead, it allows the application to provide a controlled view as to what 93 * the current instant and time-zone are. 94 * <p> 95 * Best practice for applications is to pass a {@code Clock} into any method 96 * that requires the current instant and time-zone. A dependency injection framework 97 * is one way to achieve this: 98 * <pre> 99 * public class MyBean { 100 * private Clock clock; // dependency inject 101 * ... 102 * public void process(LocalDate eventDate) { 103 * if (eventDate.isBefore(LocalDate.now(clock)) { 104 * ... 105 * } 106 * } 107 * } 108 * </pre> 109 * This approach allows an alternative clock, such as {@link #fixed(Instant, ZoneId) fixed} 110 * or {@link #offset(Clock, Duration) offset} to be used during testing. 111 * <p> 112 * The {@code system} factory methods provide clocks based on the best available 113 * system clock. This may use {@link System#currentTimeMillis()}, or a higher 114 * resolution clock if one is available. 115 * 116 * @implSpec 117 * This abstract class must be implemented with care to ensure other classes operate correctly. 118 * All implementations must be thread-safe - a single instance must be capable of be invoked 119 * from multiple threads without negative consequences such as race conditions. 120 * <p> 121 * The principal methods are defined to allow the throwing of an exception. 122 * In normal use, no exceptions will be thrown, however one possible implementation would be to 123 * obtain the time from a central time server across the network. Obviously, in this case the 124 * lookup could fail, and so the method is permitted to throw an exception. 125 * <p> 126 * The returned instants from {@code Clock} work on a time-scale that ignores leap seconds, 127 * as described in {@link Instant}. If the implementation wraps a source that provides leap 128 * second information, then a mechanism should be used to "smooth" the leap second. 129 * The Java Time-Scale mandates the use of UTC-SLS, however clock implementations may choose 130 * how accurate they are with the time-scale so long as they document how they work. 131 * Implementations are therefore not required to actually perform the UTC-SLS slew or to 132 * otherwise be aware of leap seconds. 133 * <p> 134 * Implementations should implement {@code Serializable} wherever possible and must 135 * document whether or not they do support serialization. 136 * 137 * @since 1.8 138 */ 139 public abstract class Clock implements InstantSource { 140 141 /** 142 * Obtains a clock that returns the current instant using the best available 143 * system clock, converting to date and time using the UTC time-zone. 144 * <p> 145 * This clock, rather than {@link #systemDefaultZone()}, should be used when 146 * you need the current instant without the date or time. 147 * <p> 148 * This clock is based on the best available system clock. 149 * This may use {@link System#currentTimeMillis()}, or a higher resolution 150 * clock if one is available. 151 * <p> 152 * Conversion from instant to date or time uses the {@linkplain ZoneOffset#UTC UTC time-zone}. 153 * <p> 154 * The returned implementation is immutable, thread-safe and {@code Serializable}. 155 * It is equivalent to {@code system(ZoneOffset.UTC)}. 156 * 157 * @return a clock that uses the best available system clock in the UTC zone, not null 158 */ systemUTC()159 public static Clock systemUTC() { 160 return SystemClock.UTC; 161 } 162 163 /** 164 * Obtains a clock that returns the current instant using the best available 165 * system clock, converting to date and time using the default time-zone. 166 * <p> 167 * This clock is based on the best available system clock. 168 * This may use {@link System#currentTimeMillis()}, or a higher resolution 169 * clock if one is available. 170 * <p> 171 * Using this method hard codes a dependency to the default time-zone into your application. 172 * It is recommended to avoid this and use a specific time-zone whenever possible. 173 * The {@link #systemUTC() UTC clock} should be used when you need the current instant 174 * without the date or time. 175 * <p> 176 * The returned implementation is immutable, thread-safe and {@code Serializable}. 177 * It is equivalent to {@code system(ZoneId.systemDefault())}. 178 * 179 * @return a clock that uses the best available system clock in the default zone, not null 180 * @see ZoneId#systemDefault() 181 */ systemDefaultZone()182 public static Clock systemDefaultZone() { 183 return new SystemClock(ZoneId.systemDefault()); 184 } 185 186 /** 187 * Obtains a clock that returns the current instant using the best available 188 * system clock. 189 * <p> 190 * This clock is based on the best available system clock. 191 * This may use {@link System#currentTimeMillis()}, or a higher resolution 192 * clock if one is available. 193 * <p> 194 * Conversion from instant to date or time uses the specified time-zone. 195 * <p> 196 * The returned implementation is immutable, thread-safe and {@code Serializable}. 197 * 198 * @param zone the time-zone to use to convert the instant to date-time, not null 199 * @return a clock that uses the best available system clock in the specified zone, not null 200 */ system(ZoneId zone)201 public static Clock system(ZoneId zone) { 202 Objects.requireNonNull(zone, "zone"); 203 if (zone == ZoneOffset.UTC) { 204 return SystemClock.UTC; 205 } 206 return new SystemClock(zone); 207 } 208 209 //------------------------------------------------------------------------- 210 /** 211 * Obtains a clock that returns the current instant ticking in whole milliseconds 212 * using the best available system clock. 213 * <p> 214 * This clock will always have the nano-of-second field truncated to milliseconds. 215 * This ensures that the visible time ticks in whole milliseconds. 216 * The underlying clock is the best available system clock, equivalent to 217 * using {@link #system(ZoneId)}. 218 * <p> 219 * Implementations may use a caching strategy for performance reasons. 220 * As such, it is possible that the start of the millisecond observed via this 221 * clock will be later than that observed directly via the underlying clock. 222 * <p> 223 * The returned implementation is immutable, thread-safe and {@code Serializable}. 224 * It is equivalent to {@code tick(system(zone), Duration.ofMillis(1))}. 225 * 226 * @param zone the time-zone to use to convert the instant to date-time, not null 227 * @return a clock that ticks in whole milliseconds using the specified zone, not null 228 * @since 9 229 */ tickMillis(ZoneId zone)230 public static Clock tickMillis(ZoneId zone) { 231 return new TickClock(system(zone), NANOS_PER_MILLI); 232 } 233 234 //------------------------------------------------------------------------- 235 /** 236 * Obtains a clock that returns the current instant ticking in whole seconds 237 * using the best available system clock. 238 * <p> 239 * This clock will always have the nano-of-second field set to zero. 240 * This ensures that the visible time ticks in whole seconds. 241 * The underlying clock is the best available system clock, equivalent to 242 * using {@link #system(ZoneId)}. 243 * <p> 244 * Implementations may use a caching strategy for performance reasons. 245 * As such, it is possible that the start of the second observed via this 246 * clock will be later than that observed directly via the underlying clock. 247 * <p> 248 * The returned implementation is immutable, thread-safe and {@code Serializable}. 249 * It is equivalent to {@code tick(system(zone), Duration.ofSeconds(1))}. 250 * 251 * @param zone the time-zone to use to convert the instant to date-time, not null 252 * @return a clock that ticks in whole seconds using the specified zone, not null 253 */ tickSeconds(ZoneId zone)254 public static Clock tickSeconds(ZoneId zone) { 255 return new TickClock(system(zone), NANOS_PER_SECOND); 256 } 257 258 /** 259 * Obtains a clock that returns the current instant ticking in whole minutes 260 * using the best available system clock. 261 * <p> 262 * This clock will always have the nano-of-second and second-of-minute fields set to zero. 263 * This ensures that the visible time ticks in whole minutes. 264 * The underlying clock is the best available system clock, equivalent to 265 * using {@link #system(ZoneId)}. 266 * <p> 267 * Implementations may use a caching strategy for performance reasons. 268 * As such, it is possible that the start of the minute observed via this 269 * clock will be later than that observed directly via the underlying clock. 270 * <p> 271 * The returned implementation is immutable, thread-safe and {@code Serializable}. 272 * It is equivalent to {@code tick(system(zone), Duration.ofMinutes(1))}. 273 * 274 * @param zone the time-zone to use to convert the instant to date-time, not null 275 * @return a clock that ticks in whole minutes using the specified zone, not null 276 */ tickMinutes(ZoneId zone)277 public static Clock tickMinutes(ZoneId zone) { 278 return new TickClock(system(zone), NANOS_PER_MINUTE); 279 } 280 281 /** 282 * Obtains a clock that returns instants from the specified clock truncated 283 * to the nearest occurrence of the specified duration. 284 * <p> 285 * This clock will only tick as per the specified duration. Thus, if the duration 286 * is half a second, the clock will return instants truncated to the half second. 287 * <p> 288 * The tick duration must be positive. If it has a part smaller than a whole 289 * millisecond, then the whole duration must divide into one second without 290 * leaving a remainder. All normal tick durations will match these criteria, 291 * including any multiple of hours, minutes, seconds and milliseconds, and 292 * sensible nanosecond durations, such as 20ns, 250,000ns and 500,000ns. 293 * <p> 294 * A duration of zero or one nanosecond would have no truncation effect. 295 * Passing one of these will return the underlying clock. 296 * <p> 297 * Implementations may use a caching strategy for performance reasons. 298 * As such, it is possible that the start of the requested duration observed 299 * via this clock will be later than that observed directly via the underlying clock. 300 * <p> 301 * The returned implementation is immutable, thread-safe and {@code Serializable} 302 * providing that the base clock is. 303 * 304 * @param baseClock the base clock to base the ticking clock on, not null 305 * @param tickDuration the duration of each visible tick, not negative, not null 306 * @return a clock that ticks in whole units of the duration, not null 307 * @throws IllegalArgumentException if the duration is negative, or has a 308 * part smaller than a whole millisecond such that the whole duration is not 309 * divisible into one second 310 * @throws ArithmeticException if the duration is too large to be represented as nanos 311 */ tick(Clock baseClock, Duration tickDuration)312 public static Clock tick(Clock baseClock, Duration tickDuration) { 313 Objects.requireNonNull(baseClock, "baseClock"); 314 Objects.requireNonNull(tickDuration, "tickDuration"); 315 if (tickDuration.isNegative()) { 316 throw new IllegalArgumentException("Tick duration must not be negative"); 317 } 318 long tickNanos = tickDuration.toNanos(); 319 if (tickNanos % 1000_000 == 0) { 320 // ok, no fraction of millisecond 321 } else if (1000_000_000 % tickNanos == 0) { 322 // ok, divides into one second without remainder 323 } else { 324 throw new IllegalArgumentException("Invalid tick duration"); 325 } 326 if (tickNanos <= 1) { 327 return baseClock; 328 } 329 return new TickClock(baseClock, tickNanos); 330 } 331 332 //----------------------------------------------------------------------- 333 /** 334 * Obtains a clock that always returns the same instant. 335 * <p> 336 * This clock simply returns the specified instant. 337 * As such, it is not a clock in the conventional sense. 338 * The main use case for this is in testing, where the fixed clock ensures 339 * tests are not dependent on the current clock. 340 * <p> 341 * The returned implementation is immutable, thread-safe and {@code Serializable}. 342 * 343 * @param fixedInstant the instant to use as the clock, not null 344 * @param zone the time-zone to use to convert the instant to date-time, not null 345 * @return a clock that always returns the same instant, not null 346 */ fixed(Instant fixedInstant, ZoneId zone)347 public static Clock fixed(Instant fixedInstant, ZoneId zone) { 348 Objects.requireNonNull(fixedInstant, "fixedInstant"); 349 Objects.requireNonNull(zone, "zone"); 350 return new FixedClock(fixedInstant, zone); 351 } 352 353 //------------------------------------------------------------------------- 354 /** 355 * Obtains a clock that returns instants from the specified clock with the 356 * specified duration added. 357 * <p> 358 * This clock wraps another clock, returning instants that are later by the 359 * specified duration. If the duration is negative, the instants will be 360 * earlier than the current date and time. 361 * The main use case for this is to simulate running in the future or in the past. 362 * <p> 363 * A duration of zero would have no offsetting effect. 364 * Passing zero will return the underlying clock. 365 * <p> 366 * The returned implementation is immutable, thread-safe and {@code Serializable} 367 * providing that the base clock is. 368 * 369 * @param baseClock the base clock to add the duration to, not null 370 * @param offsetDuration the duration to add, not null 371 * @return a clock based on the base clock with the duration added, not null 372 */ offset(Clock baseClock, Duration offsetDuration)373 public static Clock offset(Clock baseClock, Duration offsetDuration) { 374 Objects.requireNonNull(baseClock, "baseClock"); 375 Objects.requireNonNull(offsetDuration, "offsetDuration"); 376 if (offsetDuration.equals(Duration.ZERO)) { 377 return baseClock; 378 } 379 return new OffsetClock(baseClock, offsetDuration); 380 } 381 382 //----------------------------------------------------------------------- 383 /** 384 * Constructor accessible by subclasses. 385 */ Clock()386 protected Clock() { 387 } 388 389 //----------------------------------------------------------------------- 390 /** 391 * Gets the time-zone being used to create dates and times. 392 * <p> 393 * A clock will typically obtain the current instant and then convert that 394 * to a date or time using a time-zone. This method returns the time-zone used. 395 * 396 * @return the time-zone being used to interpret instants, not null 397 */ getZone()398 public abstract ZoneId getZone(); 399 400 /** 401 * Returns a copy of this clock with a different time-zone. 402 * <p> 403 * A clock will typically obtain the current instant and then convert that 404 * to a date or time using a time-zone. This method returns a clock with 405 * similar properties but using a different time-zone. 406 * 407 * @param zone the time-zone to change to, not null 408 * @return a clock based on this clock with the specified time-zone, not null 409 */ 410 @Override withZone(ZoneId zone)411 public abstract Clock withZone(ZoneId zone); 412 413 //------------------------------------------------------------------------- 414 /** 415 * Gets the current millisecond instant of the clock. 416 * <p> 417 * This returns the millisecond-based instant, measured from 1970-01-01T00:00Z (UTC). 418 * This is equivalent to the definition of {@link System#currentTimeMillis()}. 419 * <p> 420 * Most applications should avoid this method and use {@link Instant} to represent 421 * an instant on the time-line rather than a raw millisecond value. 422 * This method is provided to allow the use of the clock in high performance use cases 423 * where the creation of an object would be unacceptable. 424 * <p> 425 * The default implementation currently calls {@link #instant}. 426 * 427 * @return the current millisecond instant from this clock, measured from 428 * the Java epoch of 1970-01-01T00:00Z (UTC), not null 429 * @throws DateTimeException if the instant cannot be obtained, not thrown by most implementations 430 */ 431 @Override millis()432 public long millis() { 433 return instant().toEpochMilli(); 434 } 435 436 //----------------------------------------------------------------------- 437 /** 438 * Gets the current instant of the clock. 439 * <p> 440 * This returns an instant representing the current instant as defined by the clock. 441 * 442 * @return the current instant from this clock, not null 443 * @throws DateTimeException if the instant cannot be obtained, not thrown by most implementations 444 */ 445 @Override instant()446 public abstract Instant instant(); 447 448 //----------------------------------------------------------------------- 449 /** 450 * Checks if this clock is equal to another clock. 451 * <p> 452 * Clocks should override this method to compare equals based on 453 * their state and to meet the contract of {@link Object#equals}. 454 * If not overridden, the behavior is defined by {@link Object#equals} 455 * 456 * @param obj the object to check, null returns false 457 * @return true if this is equal to the other clock 458 */ 459 @Override equals(Object obj)460 public boolean equals(Object obj) { 461 return super.equals(obj); 462 } 463 464 /** 465 * A hash code for this clock. 466 * <p> 467 * Clocks should override this method based on 468 * their state and to meet the contract of {@link Object#hashCode}. 469 * If not overridden, the behavior is defined by {@link Object#hashCode} 470 * 471 * @return a suitable hash code 472 */ 473 @Override hashCode()474 public int hashCode() { 475 return super.hashCode(); 476 } 477 478 //----------------------------------------------------------------------- 479 // initial offset 480 private static final long OFFSET_SEED = System.currentTimeMillis() / 1000 - 1024; 481 // We don't actually need a volatile here. 482 // We don't care if offset is set or read concurrently by multiple 483 // threads - we just need a value which is 'recent enough' - in other 484 // words something that has been updated at least once in the last 485 // 2^32 secs (~136 years). And even if we by chance see an invalid 486 // offset, the worst that can happen is that we will get a -1 value 487 // from getNanoTimeAdjustment, forcing us to update the offset 488 // once again. 489 private static long offset = OFFSET_SEED; 490 currentInstant()491 static Instant currentInstant() { 492 // Take a local copy of offset. offset can be updated concurrently 493 // by other threads (even if we haven't made it volatile) so we will 494 // work with a local copy. 495 long localOffset = offset; 496 long adjustment = VM.getNanoTimeAdjustment(localOffset); 497 498 if (adjustment == -1) { 499 // -1 is a sentinel value returned by VM.getNanoTimeAdjustment 500 // when the offset it is given is too far off the current UTC 501 // time. In principle, this should not happen unless the 502 // JVM has run for more than ~136 years (not likely) or 503 // someone is fiddling with the system time, or the offset is 504 // by chance at 1ns in the future (very unlikely). 505 // We can easily recover from all these conditions by bringing 506 // back the offset in range and retry. 507 508 // bring back the offset in range. We use -1024 to make 509 // it more unlikely to hit the 1ns in the future condition. 510 localOffset = System.currentTimeMillis() / 1000 - 1024; 511 512 // retry 513 adjustment = VM.getNanoTimeAdjustment(localOffset); 514 515 if (adjustment == -1) { 516 // Should not happen: we just recomputed a new offset. 517 // It should have fixed the issue. 518 throw new InternalError("Offset " + localOffset + " is not in range"); 519 } else { 520 // OK - recovery succeeded. Update the offset for the 521 // next call... 522 offset = localOffset; 523 } 524 } 525 return Instant.ofEpochSecond(localOffset, adjustment); 526 } 527 528 //----------------------------------------------------------------------- 529 /** 530 * An instant source that always returns the latest time from 531 * {@link System#currentTimeMillis()} or equivalent. 532 */ 533 static final class SystemInstantSource implements InstantSource, Serializable { 534 @java.io.Serial 535 private static final long serialVersionUID = 3232399674412L; 536 // this is a singleton, but the class is coded such that it is not a 537 // problem if someone hacks around and creates another instance 538 static final SystemInstantSource INSTANCE = new SystemInstantSource(); 539 SystemInstantSource()540 SystemInstantSource() { 541 } 542 @Override withZone(ZoneId zone)543 public Clock withZone(ZoneId zone) { 544 return Clock.system(zone); 545 } 546 @Override millis()547 public long millis() { 548 // System.currentTimeMillis() and VM.getNanoTimeAdjustment(offset) 549 // use the same time source - System.currentTimeMillis() simply 550 // limits the resolution to milliseconds. 551 // So we take the faster path and call System.currentTimeMillis() 552 // directly - in order to avoid the performance penalty of 553 // VM.getNanoTimeAdjustment(offset) which is less efficient. 554 return System.currentTimeMillis(); 555 } 556 @Override instant()557 public Instant instant() { 558 return currentInstant(); 559 } 560 @Override equals(Object obj)561 public boolean equals(Object obj) { 562 return obj instanceof SystemInstantSource; 563 } 564 @Override hashCode()565 public int hashCode() { 566 return SystemInstantSource.class.hashCode(); 567 } 568 @Override toString()569 public String toString() { 570 return "SystemInstantSource"; 571 } 572 @java.io.Serial readResolve()573 private Object readResolve() throws ObjectStreamException { 574 return SystemInstantSource.INSTANCE; 575 } 576 } 577 578 //----------------------------------------------------------------------- 579 /** 580 * Implementation of a clock that always returns the latest time from 581 * {@code SystemInstantSource.INSTANCE}. 582 */ 583 static final class SystemClock extends Clock implements Serializable { 584 @java.io.Serial 585 private static final long serialVersionUID = 6740630888130243051L; 586 static final SystemClock UTC = new SystemClock(ZoneOffset.UTC); 587 588 private final ZoneId zone; 589 SystemClock(ZoneId zone)590 SystemClock(ZoneId zone) { 591 this.zone = zone; 592 } 593 @Override getZone()594 public ZoneId getZone() { 595 return zone; 596 } 597 @Override withZone(ZoneId zone)598 public Clock withZone(ZoneId zone) { 599 if (zone.equals(this.zone)) { // intentional NPE 600 return this; 601 } 602 return new SystemClock(zone); 603 } 604 @Override millis()605 public long millis() { 606 // inline of SystemInstantSource.INSTANCE.millis() 607 return System.currentTimeMillis(); 608 } 609 @Override instant()610 public Instant instant() { 611 // inline of SystemInstantSource.INSTANCE.instant() 612 return currentInstant(); 613 } 614 @Override equals(Object obj)615 public boolean equals(Object obj) { 616 if (obj instanceof SystemClock) { 617 return zone.equals(((SystemClock) obj).zone); 618 } 619 return false; 620 } 621 @Override hashCode()622 public int hashCode() { 623 return zone.hashCode() + 1; 624 } 625 @Override toString()626 public String toString() { 627 return "SystemClock[" + zone + "]"; 628 } 629 } 630 631 //----------------------------------------------------------------------- 632 /** 633 * Implementation of a clock that always returns the same instant. 634 * This is typically used for testing. 635 */ 636 static final class FixedClock extends Clock implements Serializable { 637 @java.io.Serial 638 private static final long serialVersionUID = 7430389292664866958L; 639 private final Instant instant; 640 private final ZoneId zone; 641 FixedClock(Instant fixedInstant, ZoneId zone)642 FixedClock(Instant fixedInstant, ZoneId zone) { 643 this.instant = fixedInstant; 644 this.zone = zone; 645 } 646 @Override getZone()647 public ZoneId getZone() { 648 return zone; 649 } 650 @Override withZone(ZoneId zone)651 public Clock withZone(ZoneId zone) { 652 if (zone.equals(this.zone)) { // intentional NPE 653 return this; 654 } 655 return new FixedClock(instant, zone); 656 } 657 @Override millis()658 public long millis() { 659 return instant.toEpochMilli(); 660 } 661 @Override instant()662 public Instant instant() { 663 return instant; 664 } 665 @Override equals(Object obj)666 public boolean equals(Object obj) { 667 return obj instanceof FixedClock other 668 && instant.equals(other.instant) 669 && zone.equals(other.zone); 670 } 671 @Override hashCode()672 public int hashCode() { 673 return instant.hashCode() ^ zone.hashCode(); 674 } 675 @Override toString()676 public String toString() { 677 return "FixedClock[" + instant + "," + zone + "]"; 678 } 679 } 680 681 //----------------------------------------------------------------------- 682 /** 683 * Implementation of a clock that adds an offset to an underlying clock. 684 */ 685 static final class OffsetClock extends Clock implements Serializable { 686 @java.io.Serial 687 private static final long serialVersionUID = 2007484719125426256L; 688 @SuppressWarnings("serial") // Not statically typed as Serializable 689 private final Clock baseClock; 690 private final Duration offset; 691 OffsetClock(Clock baseClock, Duration offset)692 OffsetClock(Clock baseClock, Duration offset) { 693 this.baseClock = baseClock; 694 this.offset = offset; 695 } 696 @Override getZone()697 public ZoneId getZone() { 698 return baseClock.getZone(); 699 } 700 @Override withZone(ZoneId zone)701 public Clock withZone(ZoneId zone) { 702 if (zone.equals(baseClock.getZone())) { // intentional NPE 703 return this; 704 } 705 return new OffsetClock(baseClock.withZone(zone), offset); 706 } 707 @Override millis()708 public long millis() { 709 return Math.addExact(baseClock.millis(), offset.toMillis()); 710 } 711 @Override instant()712 public Instant instant() { 713 return baseClock.instant().plus(offset); 714 } 715 @Override equals(Object obj)716 public boolean equals(Object obj) { 717 return obj instanceof OffsetClock other 718 && baseClock.equals(other.baseClock) 719 && offset.equals(other.offset); 720 } 721 @Override hashCode()722 public int hashCode() { 723 return baseClock.hashCode() ^ offset.hashCode(); 724 } 725 @Override toString()726 public String toString() { 727 return "OffsetClock[" + baseClock + "," + offset + "]"; 728 } 729 } 730 731 //----------------------------------------------------------------------- 732 /** 733 * Implementation of a clock that reduces the tick frequency of an underlying clock. 734 */ 735 static final class TickClock extends Clock implements Serializable { 736 @java.io.Serial 737 private static final long serialVersionUID = 6504659149906368850L; 738 @SuppressWarnings("serial") // Not statically typed as Serializable 739 private final Clock baseClock; 740 private final long tickNanos; 741 TickClock(Clock baseClock, long tickNanos)742 TickClock(Clock baseClock, long tickNanos) { 743 this.baseClock = baseClock; 744 this.tickNanos = tickNanos; 745 } 746 @Override getZone()747 public ZoneId getZone() { 748 return baseClock.getZone(); 749 } 750 @Override withZone(ZoneId zone)751 public Clock withZone(ZoneId zone) { 752 if (zone.equals(baseClock.getZone())) { // intentional NPE 753 return this; 754 } 755 return new TickClock(baseClock.withZone(zone), tickNanos); 756 } 757 @Override millis()758 public long millis() { 759 long millis = baseClock.millis(); 760 return millis - Math.floorMod(millis, tickNanos / 1000_000L); 761 } 762 @Override instant()763 public Instant instant() { 764 if ((tickNanos % 1000_000) == 0) { 765 long millis = baseClock.millis(); 766 return Instant.ofEpochMilli(millis - Math.floorMod(millis, tickNanos / 1000_000L)); 767 } 768 Instant instant = baseClock.instant(); 769 long nanos = instant.getNano(); 770 long adjust = Math.floorMod(nanos, tickNanos); 771 return instant.minusNanos(adjust); 772 } 773 @Override equals(Object obj)774 public boolean equals(Object obj) { 775 return (obj instanceof TickClock other) 776 && tickNanos == other.tickNanos 777 && baseClock.equals(other.baseClock); 778 } 779 @Override hashCode()780 public int hashCode() { 781 return baseClock.hashCode() ^ ((int) (tickNanos ^ (tickNanos >>> 32))); 782 } 783 @Override toString()784 public String toString() { 785 return "TickClock[" + baseClock + "," + Duration.ofNanos(tickNanos) + "]"; 786 } 787 } 788 789 //----------------------------------------------------------------------- 790 /** 791 * Implementation of a clock based on an {@code InstantSource}. 792 */ 793 static final class SourceClock extends Clock implements Serializable { 794 @java.io.Serial 795 private static final long serialVersionUID = 235386528762398L; 796 @SuppressWarnings("serial") // Not statically typed as Serializable 797 private final InstantSource baseSource; 798 private final ZoneId zone; 799 SourceClock(InstantSource baseSource, ZoneId zone)800 SourceClock(InstantSource baseSource, ZoneId zone) { 801 this.baseSource = baseSource; 802 this.zone = zone; 803 } 804 @Override getZone()805 public ZoneId getZone() { 806 return zone; 807 } 808 @Override withZone(ZoneId zone)809 public Clock withZone(ZoneId zone) { 810 if (zone.equals(this.zone)) { // intentional NPE 811 return this; 812 } 813 return new SourceClock(baseSource, zone); 814 } 815 @Override millis()816 public long millis() { 817 return baseSource.millis(); 818 } 819 @Override instant()820 public Instant instant() { 821 return baseSource.instant(); 822 } 823 @Override equals(Object obj)824 public boolean equals(Object obj) { 825 return (obj instanceof SourceClock other) 826 && zone.equals(other.zone) 827 && baseSource.equals(other.baseSource); 828 } 829 @Override hashCode()830 public int hashCode() { 831 return baseSource.hashCode() ^ zone.hashCode(); 832 } 833 @Override toString()834 public String toString() { 835 return "SourceClock[" + baseSource + "," + zone + "]"; 836 } 837 } 838 839 } 840