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