1 /* 2 * Copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * * Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * * Neither the name of JSR-310 nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package org.threeten.bp; 33 34 import static org.threeten.bp.LocalTime.NANOS_PER_MINUTE; 35 import static org.threeten.bp.LocalTime.NANOS_PER_SECOND; 36 37 import java.io.Serializable; 38 import java.util.TimeZone; 39 40 import org.threeten.bp.jdk8.Jdk8Methods; 41 42 /** 43 * A clock providing access to the current instant, date and time using a time-zone. 44 * <p> 45 * Instances of this class are used to find the current instant, which can be 46 * interpreted using the stored time-zone to find the current date and time. 47 * As such, a clock can be used instead of {@link System#currentTimeMillis()} 48 * and {@link TimeZone#getDefault()}. 49 * <p> 50 * Use of a {@code Clock} is optional. All key date-time classes also have a 51 * {@code now()} factory method that uses the system clock in the default time zone. 52 * The primary purpose of this abstraction is to allow alternate clocks to be 53 * plugged in as and when required. Applications use an object to obtain the 54 * current time rather than a static method. This can simplify testing. 55 * <p> 56 * Best practice for applications is to pass a {@code Clock} into any method 57 * that requires the current instant. A dependency injection framework is one 58 * way to achieve this: 59 * <pre> 60 * public class MyBean { 61 * private Clock clock; // dependency inject 62 * ... 63 * public void process(LocalDate eventDate) { 64 * if (eventDate.isBefore(LocalDate.now(clock)) { 65 * ... 66 * } 67 * } 68 * } 69 * </pre> 70 * This approach allows an alternate clock, such as {@link #fixed(Instant, ZoneId) fixed} 71 * or {@link #offset(Clock, Duration) offset} to be used during testing. 72 * <p> 73 * The {@code system} factory methods provide clocks based on the best available 74 * system clock This may use {@link System#currentTimeMillis()}, or a higher 75 * resolution clock if one is available. 76 * 77 * <h3>Specification for implementors</h3> 78 * This abstract class must be implemented with care to ensure other operate correctly. 79 * All implementations that can be instantiated must be final, immutable and thread-safe. 80 * <p> 81 * The principal methods are defined to allow the throwing of an exception. 82 * In normal use, no exceptions will be thrown, however one possible implementation would be to 83 * obtain the time from a central time server across the network. Obviously, in this case the 84 * lookup could fail, and so the method is permitted to throw an exception. 85 * <p> 86 * The returned instants from {@code Clock} work on a time-scale that ignores leap seconds. 87 * If the implementation wraps a source that provides leap second information, then a mechanism 88 * should be used to "smooth" the leap second, such as UTC-SLS. 89 * <p> 90 * Implementations should implement {@code Serializable} wherever possible and must 91 * document whether or not they do support serialization. 92 */ 93 public abstract class Clock { 94 95 /** 96 * Obtains a clock that returns the current instant using the best available 97 * system clock, converting to date and time using the UTC time-zone. 98 * <p> 99 * This clock, rather than {@link #systemDefaultZone()}, should be used when 100 * you need the current instant without the date or time. 101 * <p> 102 * This clock is based on the best available system clock. 103 * This may use {@link System#currentTimeMillis()}, or a higher resolution 104 * clock if one is available. 105 * <p> 106 * Conversion from instant to date or time uses the {@link ZoneOffset#UTC UTC time-zone}. 107 * <p> 108 * The returned implementation is immutable, thread-safe and {@code Serializable}. 109 * It is equivalent to {@code system(ZoneOffset.UTC)}. 110 * 111 * @return a clock that uses the best available system clock in the UTC zone, not null 112 */ systemUTC()113 public static Clock systemUTC() { 114 return new SystemClock(ZoneOffset.UTC); 115 } 116 117 /** 118 * Obtains a clock that returns the current instant using the best available 119 * system clock, converting to date and time using the default time-zone. 120 * <p> 121 * This clock is based on the best available system clock. 122 * This may use {@link System#currentTimeMillis()}, or a higher resolution 123 * clock if one is available. 124 * <p> 125 * Using this method hard codes a dependency to the default time-zone into your application. 126 * It is recommended to avoid this and use a specific time-zone whenever possible. 127 * The {@link #systemUTC() UTC clock} should be used when you need the current instant 128 * without the date or time. 129 * <p> 130 * The returned implementation is immutable, thread-safe and {@code Serializable}. 131 * It is equivalent to {@code system(ZoneId.systemDefault())}. 132 * 133 * @return a clock that uses the best available system clock in the default zone, not null 134 * @see ZoneId#systemDefault() 135 */ systemDefaultZone()136 public static Clock systemDefaultZone() { 137 return new SystemClock(ZoneId.systemDefault()); 138 } 139 140 /** 141 * Obtains a clock that returns the current instant using best available 142 * system clock. 143 * <p> 144 * This clock is based on the best available system clock. 145 * This may use {@link System#currentTimeMillis()}, or a higher resolution 146 * clock if one is available. 147 * <p> 148 * Conversion from instant to date or time uses the specified time-zone. 149 * <p> 150 * The returned implementation is immutable, thread-safe and {@code Serializable}. 151 * 152 * @param zone the time-zone to use to convert the instant to date-time, not null 153 * @return a clock that uses the best available system clock in the specified zone, not null 154 */ system(ZoneId zone)155 public static Clock system(ZoneId zone) { 156 Jdk8Methods.requireNonNull(zone, "zone"); 157 return new SystemClock(zone); 158 } 159 160 //------------------------------------------------------------------------- 161 /** 162 * Obtains a clock that returns the current instant ticking in whole seconds 163 * using best available system clock. 164 * <p> 165 * This clock will always have the nano-of-second field set to zero. 166 * This ensures that the visible time ticks in whole seconds. 167 * The underlying clock is the best available system clock, equivalent to 168 * using {@link #system(ZoneId)}. 169 * <p> 170 * Implementations may use a caching strategy for performance reasons. 171 * As such, it is possible that the start of the second observed via this 172 * clock will be later than that observed directly via the underlying clock. 173 * <p> 174 * The returned implementation is immutable, thread-safe and {@code Serializable}. 175 * It is equivalent to {@code tick(system(zone), Duration.ofSeconds(1))}. 176 * 177 * @param zone the time-zone to use to convert the instant to date-time, not null 178 * @return a clock that ticks in whole seconds using the specified zone, not null 179 */ tickSeconds(ZoneId zone)180 public static Clock tickSeconds(ZoneId zone) { 181 return new TickClock(system(zone), NANOS_PER_SECOND); 182 } 183 184 /** 185 * Obtains a clock that returns the current instant ticking in whole minutes 186 * using best available system clock. 187 * <p> 188 * This clock will always have the nano-of-second and second-of-minute fields set to zero. 189 * This ensures that the visible time ticks in whole minutes. 190 * The underlying clock is the best available system clock, equivalent to 191 * using {@link #system(ZoneId)}. 192 * <p> 193 * Implementations may use a caching strategy for performance reasons. 194 * As such, it is possible that the start of the minute observed via this 195 * clock will be later than that observed directly via the underlying clock. 196 * <p> 197 * The returned implementation is immutable, thread-safe and {@code Serializable}. 198 * It is equivalent to {@code tick(system(zone), Duration.ofMinutes(1))}. 199 * 200 * @param zone the time-zone to use to convert the instant to date-time, not null 201 * @return a clock that ticks in whole minutes using the specified zone, not null 202 */ tickMinutes(ZoneId zone)203 public static Clock tickMinutes(ZoneId zone) { 204 return new TickClock(system(zone), NANOS_PER_MINUTE); 205 } 206 207 /** 208 * Obtains a clock that returns instants from the specified clock truncated 209 * to the nearest occurrence of the specified duration. 210 * <p> 211 * This clock will only tick as per the specified duration. Thus, if the duration 212 * is half a second, the clock will return instants truncated to the half second. 213 * <p> 214 * The tick duration must be positive. If it has a part smaller than a whole 215 * millisecond, then the whole duration must divide into one second without 216 * leaving a remainder. All normal tick durations will match these criteria, 217 * including any multiple of hours, minutes, seconds and milliseconds, and 218 * sensible nanosecond durations, such as 20ns, 250,000ns and 500,000ns. 219 * <p> 220 * A duration of zero or one nanosecond would have no truncation effect. 221 * Passing one of these will return the underlying clock. 222 * <p> 223 * Implementations may use a caching strategy for performance reasons. 224 * As such, it is possible that the start of the requested duration observed 225 * via this clock will be later than that observed directly via the underlying clock. 226 * <p> 227 * The returned implementation is immutable, thread-safe and {@code Serializable} 228 * providing that the base clock is. 229 * 230 * @param baseClock the base clock to base the ticking clock on, not null 231 * @param tickDuration the duration of each visible tick, not negative, not null 232 * @return a clock that ticks in whole units of the duration, not null 233 * @throws IllegalArgumentException if the duration is negative, or has a 234 * part smaller than a whole millisecond such that the whole duration is not 235 * divisible into one second 236 * @throws ArithmeticException if the duration is too large to be represented as nanos 237 */ tick(Clock baseClock, Duration tickDuration)238 public static Clock tick(Clock baseClock, Duration tickDuration) { 239 Jdk8Methods.requireNonNull(baseClock, "baseClock"); 240 Jdk8Methods.requireNonNull(tickDuration, "tickDuration"); 241 if (tickDuration.isNegative()) { 242 throw new IllegalArgumentException("Tick duration must not be negative"); 243 } 244 long tickNanos = tickDuration.toNanos(); 245 if (tickNanos % 1000000 == 0) { 246 // ok, no fraction of millisecond 247 } else if (1000000000 % tickNanos == 0) { 248 // ok, divides into one second without remainder 249 } else { 250 throw new IllegalArgumentException("Invalid tick duration"); 251 } 252 if (tickNanos <= 1) { 253 return baseClock; 254 } 255 return new TickClock(baseClock, tickNanos); 256 } 257 258 //----------------------------------------------------------------------- 259 /** 260 * Obtains a clock that always returns the same instant. 261 * <p> 262 * This clock simply returns the specified instant. 263 * As such, it is not a clock in the conventional sense. 264 * The main use case for this is in testing, where the fixed clock ensures 265 * tests are not dependent on the current clock. 266 * <p> 267 * The returned implementation is immutable, thread-safe and {@code Serializable}. 268 * 269 * @param fixedInstant the instant to use as the clock, not null 270 * @param zone the time-zone to use to convert the instant to date-time, not null 271 * @return a clock that always returns the same instant, not null 272 */ fixed(Instant fixedInstant, ZoneId zone)273 public static Clock fixed(Instant fixedInstant, ZoneId zone) { 274 Jdk8Methods.requireNonNull(fixedInstant, "fixedInstant"); 275 Jdk8Methods.requireNonNull(zone, "zone"); 276 return new FixedClock(fixedInstant, zone); 277 } 278 279 //------------------------------------------------------------------------- 280 /** 281 * Obtains a clock that returns instants from the specified clock with the 282 * specified duration added 283 * <p> 284 * This clock wraps another clock, returning instants that are later by the 285 * specified duration. If the duration is negative, the instants will be 286 * earlier than the current date and time. 287 * The main use case for this is to simulate running in the future or in the past. 288 * <p> 289 * A duration of zero would have no offsetting effect. 290 * Passing zero will return the underlying clock. 291 * <p> 292 * The returned implementation is immutable, thread-safe and {@code Serializable} 293 * providing that the base clock is. 294 * 295 * @param baseClock the base clock to add the duration to, not null 296 * @param offsetDuration the duration to add, not null 297 * @return a clock based on the base clock with the duration added, not null 298 */ offset(Clock baseClock, Duration offsetDuration)299 public static Clock offset(Clock baseClock, Duration offsetDuration) { 300 Jdk8Methods.requireNonNull(baseClock, "baseClock"); 301 Jdk8Methods.requireNonNull(offsetDuration, "offsetDuration"); 302 if (offsetDuration.equals(Duration.ZERO)) { 303 return baseClock; 304 } 305 return new OffsetClock(baseClock, offsetDuration); 306 } 307 308 //----------------------------------------------------------------------- 309 /** 310 * Constructor accessible by subclasses. 311 */ Clock()312 protected Clock() { 313 } 314 315 //----------------------------------------------------------------------- 316 /** 317 * Gets the time-zone being used to create dates and times. 318 * <p> 319 * A clock will typically obtain the current instant and then convert that 320 * to a date or time using a time-zone. This method returns the time-zone used. 321 * 322 * @return the time-zone being used to interpret instants, not null 323 */ getZone()324 public abstract ZoneId getZone(); 325 326 /** 327 * Returns a copy of this clock with a different time-zone. 328 * <p> 329 * A clock will typically obtain the current instant and then convert that 330 * to a date or time using a time-zone. This method returns a clock with 331 * similar properties but using a different time-zone. 332 * 333 * @param zone the time-zone to change to, not null 334 * @return a clock based on this clock with the specified time-zone, not null 335 */ withZone(ZoneId zone)336 public abstract Clock withZone(ZoneId zone); 337 338 //------------------------------------------------------------------------- 339 /** 340 * Gets the current millisecond instant of the clock. 341 * <p> 342 * This returns the millisecond-based instant, measured from 1970-01-01T00:00 UTC. 343 * This is equivalent to the definition of {@link System#currentTimeMillis()}. 344 * <p> 345 * Most applications should avoid this method and use {@link Instant} to represent 346 * an instant on the time-line rather than a raw millisecond value. 347 * This method is provided to allow the use of the clock in high performance use cases 348 * where the creation of an object would be unacceptable. 349 * The default implementation currently calls {@link #instant()}. 350 * <p> 351 * 352 * @return the current millisecond instant from this clock, measured from 353 * the Java epoch of 1970-01-01T00:00 UTC, not null 354 * @throws DateTimeException if the instant cannot be obtained, not thrown by most implementations 355 */ millis()356 public long millis() { 357 return instant().toEpochMilli(); 358 } 359 360 /** 361 * Gets the current instant of the clock. 362 * <p> 363 * This returns an instant representing the current instant as defined by the clock. 364 * 365 * @return the current instant from this clock, not null 366 * @throws DateTimeException if the instant cannot be obtained, not thrown by most implementations 367 */ instant()368 public abstract Instant instant(); 369 370 //----------------------------------------------------------------------- 371 /** 372 * Checks if this clock is equal to another clock. 373 * <p> 374 * Clocks must compare equal based on their state and behavior. 375 * 376 * @param obj the object to check, null returns false 377 * @return true if this is equal to the other clock 378 */ 379 @Override equals(Object obj)380 public boolean equals(Object obj) { 381 return super.equals(obj); 382 } 383 384 /** 385 * A hash code for this clock. 386 * 387 * @return a suitable hash code 388 */ 389 @Override hashCode()390 public int hashCode() { 391 return super.hashCode(); 392 } 393 394 //----------------------------------------------------------------------- 395 /** 396 * Implementation of a clock that always returns the latest time from 397 * {@link System#currentTimeMillis()}. 398 */ 399 static final class SystemClock extends Clock implements Serializable { 400 private static final long serialVersionUID = 6740630888130243051L; 401 private final ZoneId zone; 402 SystemClock(ZoneId zone)403 SystemClock(ZoneId zone) { 404 this.zone = zone; 405 } 406 @Override getZone()407 public ZoneId getZone() { 408 return zone; 409 } 410 @Override withZone(ZoneId zone)411 public Clock withZone(ZoneId zone) { 412 if (zone.equals(this.zone)) { // intentional NPE 413 return this; 414 } 415 return new SystemClock(zone); 416 } 417 @Override millis()418 public long millis() { 419 return System.currentTimeMillis(); 420 } 421 @Override instant()422 public Instant instant() { 423 return Instant.ofEpochMilli(millis()); 424 } 425 @Override equals(Object obj)426 public boolean equals(Object obj) { 427 if (obj instanceof SystemClock) { 428 return zone.equals(((SystemClock) obj).zone); 429 } 430 return false; 431 } 432 @Override hashCode()433 public int hashCode() { 434 return zone.hashCode() + 1; 435 } 436 @Override toString()437 public String toString() { 438 return "SystemClock[" + zone + "]"; 439 } 440 } 441 442 //----------------------------------------------------------------------- 443 /** 444 * Implementation of a clock that always returns the same instant. 445 * This is typically used for testing. 446 */ 447 static final class FixedClock extends Clock implements Serializable { 448 private static final long serialVersionUID = 7430389292664866958L; 449 private final Instant instant; 450 private final ZoneId zone; 451 FixedClock(Instant fixedInstant, ZoneId zone)452 FixedClock(Instant fixedInstant, ZoneId zone) { 453 this.instant = fixedInstant; 454 this.zone = zone; 455 } 456 @Override getZone()457 public ZoneId getZone() { 458 return zone; 459 } 460 @Override withZone(ZoneId zone)461 public Clock withZone(ZoneId zone) { 462 if (zone.equals(this.zone)) { // intentional NPE 463 return this; 464 } 465 return new FixedClock(instant, zone); 466 } 467 @Override millis()468 public long millis() { 469 return instant.toEpochMilli(); 470 } 471 @Override instant()472 public Instant instant() { 473 return instant; 474 } 475 @Override equals(Object obj)476 public boolean equals(Object obj) { 477 if (obj instanceof FixedClock) { 478 FixedClock other = (FixedClock) obj; 479 return instant.equals(other.instant) && zone.equals(other.zone); 480 } 481 return false; 482 } 483 @Override hashCode()484 public int hashCode() { 485 return instant.hashCode() ^ zone.hashCode(); 486 } 487 @Override toString()488 public String toString() { 489 return "FixedClock[" + instant + "," + zone + "]"; 490 } 491 } 492 493 //----------------------------------------------------------------------- 494 /** 495 * Implementation of a clock that adds an offset to an underlying clock. 496 */ 497 static final class OffsetClock extends Clock implements Serializable { 498 private static final long serialVersionUID = 2007484719125426256L; 499 private final Clock baseClock; 500 private final Duration offset; 501 OffsetClock(Clock baseClock, Duration offset)502 OffsetClock(Clock baseClock, Duration offset) { 503 this.baseClock = baseClock; 504 this.offset = offset; 505 } 506 @Override getZone()507 public ZoneId getZone() { 508 return baseClock.getZone(); 509 } 510 @Override withZone(ZoneId zone)511 public Clock withZone(ZoneId zone) { 512 if (zone.equals(baseClock.getZone())) { // intentional NPE 513 return this; 514 } 515 return new OffsetClock(baseClock.withZone(zone), offset); 516 } 517 @Override millis()518 public long millis() { 519 return Jdk8Methods.safeAdd(baseClock.millis(), offset.toMillis()); 520 } 521 @Override instant()522 public Instant instant() { 523 return baseClock.instant().plus(offset); 524 } 525 @Override equals(Object obj)526 public boolean equals(Object obj) { 527 if (obj instanceof OffsetClock) { 528 OffsetClock other = (OffsetClock) obj; 529 return baseClock.equals(other.baseClock) && offset.equals(other.offset); 530 } 531 return false; 532 } 533 @Override hashCode()534 public int hashCode() { 535 return baseClock.hashCode() ^ offset.hashCode(); 536 } 537 @Override toString()538 public String toString() { 539 return "OffsetClock[" + baseClock + "," + offset + "]"; 540 } 541 } 542 543 //----------------------------------------------------------------------- 544 /** 545 * Implementation of a clock that adds an offset to an underlying clock. 546 */ 547 static final class TickClock extends Clock implements Serializable { 548 private static final long serialVersionUID = 6504659149906368850L; 549 private final Clock baseClock; 550 private final long tickNanos; 551 TickClock(Clock baseClock, long tickNanos)552 TickClock(Clock baseClock, long tickNanos) { 553 this.baseClock = baseClock; 554 this.tickNanos = tickNanos; 555 } 556 @Override getZone()557 public ZoneId getZone() { 558 return baseClock.getZone(); 559 } 560 @Override withZone(ZoneId zone)561 public Clock withZone(ZoneId zone) { 562 if (zone.equals(baseClock.getZone())) { // intentional NPE 563 return this; 564 } 565 return new TickClock(baseClock.withZone(zone), tickNanos); 566 } 567 @Override millis()568 public long millis() { 569 long millis = baseClock.millis(); 570 return millis - Jdk8Methods.floorMod(millis, tickNanos / 1000000L); 571 } 572 @Override instant()573 public Instant instant() { 574 if ((tickNanos % 1000000) == 0) { 575 long millis = baseClock.millis(); 576 return Instant.ofEpochMilli(millis - Jdk8Methods.floorMod(millis, tickNanos / 1000000L)); 577 } 578 Instant instant = baseClock.instant(); 579 long nanos = instant.getNano(); 580 long adjust = Jdk8Methods.floorMod(nanos, tickNanos); 581 return instant.minusNanos(adjust); 582 } 583 @Override equals(Object obj)584 public boolean equals(Object obj) { 585 if (obj instanceof TickClock) { 586 TickClock other = (TickClock) obj; 587 return baseClock.equals(other.baseClock) && tickNanos == other.tickNanos; 588 } 589 return false; 590 } 591 @Override hashCode()592 public int hashCode() { 593 return baseClock.hashCode() ^ ((int) (tickNanos ^ (tickNanos >>> 32))); 594 } 595 @Override toString()596 public String toString() { 597 return "TickClock[" + baseClock + "," + Duration.ofNanos(tickNanos) + "]"; 598 } 599 } 600 601 } 602