Clocks¶
Island Time's Clock
interface abstracts access to the current time, easing testing and opening up a number of other possibilities, such as offsetting the current time or modifying the precision.
So while it's possible to retrieve the current system time like this:
val now = ZonedDateTime.now()
... It's generally better practice to supply a Clock
explicitly — ideally, via dependency injection.
val clock: Clock = SystemClock()
val now = ZonedDateTime.now(clock)
Two implementations are provided out of the box — SystemClock
, which accesses the current system time, and FixedClock
, which returns a fixed time that can be controlled, making it well-suited for testing.
Time Zones¶
Each Clock
has a time zone associated with it. The implementations included in Island Time treat it as an immutable property, requiring you to create a new clock if you wish to change it. Depending on the needs of your application, you may choose to respond to time zone change notifications generated by the system to do that.
System Clock Precision¶
Island Time's SystemClock
provides the highest precision time available on each platform. In practice, that usually looks like this:
Platform | Precision |
---|---|
Java 8 | millisecond |
Java 9+ | microsecond |
Android | millisecond |
Apple | microsecond |
Writing Tests with FixedClock
¶
The following example shows how FixedClock
can be used to add predictability when testing time-sensitive code.
Let's assume we have a class called ClassUnderTest
.
class ClassUnderTest(private val clock: Clock) {
val createdAt: Instant = Instant.now(clock)
var lastModified: Instant = createdAt
private set
// ...
fun performAction() {
// Do something
lastModified = Instant.now(clock)
}
}
And now to test it...
@Test
fun testClassUnderTest() {
val clock = FixedClock("2020-08-25T04:30Z".toInstant(), TimeZone.UTC)
val classUnderTest = ClassUnderTest(clock)
// Now, let's increment the clock by an hour
clock += 1.hours
classUnderTest.performAction()
assertEquals("2020-08-25T04:30Z".toInstant(), classUnderTest.createdAt)
assertEquals("2020-08-25T05:30Z".toInstant(), classUnderTest.lastModified)
}
Using a java.time.Clock
¶
On the JVM, it's possible to use a java.time Clock
instead of an Island Time Clock
when calling any of the now()
functions.
val javaClock = java.time.Clock.system()
val today = Date.now(javaClock)
You can also take an existing Java Clock
and make it compatible with Island Time's Clock
interface:
val javaClock = java.time.Clock.system()
val islandClock = javaClock.asIslandClock()