Skip to content

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()