Skip to content

Commit

Permalink
Add TimeSource.asClock converter (#164)
Browse files Browse the repository at this point in the history
  • Loading branch information
hfhbd authored Nov 13, 2024
1 parent fbb2187 commit 73aad58
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 0 deletions.
15 changes: 15 additions & 0 deletions core/common/src/Clock.kt
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,20 @@ private class InstantTimeMark(private val instant: Instant, private val clock: C
}
}

/**
* Creates a [Clock] that uses the [time mark at the moment of creation][TimeMark.markNow] to determine how [far][TimeMark.elapsedNow]
* the [current moment][Clock.now] is from the [origin].
*
* This clock stores the [TimeMark] at the moment of creation, so repeatedly creating [Clock]s from the same [TimeSource] results
* in different [Instant]s iff the time of the [TimeSource] was increased. To sync different [Clock]s, use the [origin]
* parameter.
*
* @sample kotlinx.datetime.test.samples.ClockSamples.timeSourceAsClock
*/
public fun TimeSource.asClock(origin: Instant): Clock = object : Clock {
private val startMark: TimeMark = markNow()
override fun now() = origin + startMark.elapsedNow()
}

@Deprecated("Use Clock.todayIn instead", ReplaceWith("this.todayIn(timeZone)"), DeprecationLevel.WARNING)
public fun Clock.todayAt(timeZone: TimeZone): LocalDate = todayIn(timeZone)
38 changes: 38 additions & 0 deletions core/common/test/ClockTimeSourceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import kotlin.test.*
import kotlin.time.*
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.nanoseconds
import kotlin.time.Duration.Companion.seconds

@OptIn(ExperimentalTime::class)
class ClockTimeSourceTest {
Expand Down Expand Up @@ -83,4 +84,41 @@ class ClockTimeSourceTest {
assertFailsWith<IllegalArgumentException> { markFuture - Duration.INFINITE }
assertFailsWith<IllegalArgumentException> { markPast + Duration.INFINITE }
}

@Test
fun timeSourceAsClock() {
val timeSource = TestTimeSource()
val clock = timeSource.asClock(origin = Instant.fromEpochSeconds(0))

assertEquals(Instant.fromEpochSeconds(0), clock.now())
assertEquals(Instant.fromEpochSeconds(0), clock.now())

timeSource += 1.seconds
assertEquals(Instant.fromEpochSeconds(1), clock.now())
assertEquals(Instant.fromEpochSeconds(1), clock.now())
}

@Test
fun syncMultipleClocksFromTimeSource() {
val timeSource = TestTimeSource()
val clock1 = timeSource.asClock(origin = Instant.fromEpochSeconds(0))

assertEquals(0, clock1.now().epochSeconds)

timeSource += 1.seconds
assertEquals(1, clock1.now().epochSeconds)

val clock2 = timeSource.asClock(origin = Instant.fromEpochSeconds(1))
assertEquals(clock1.now(), clock2.now())

timeSource += 1.seconds
assertEquals(2, clock1.now().epochSeconds)
assertEquals(clock1.now(), clock2.now())

val clock3 = timeSource.asClock(origin = clock2.now())
timeSource += 1.seconds
assertEquals(3, clock3.now().epochSeconds)
assertEquals(clock1.now(), clock2.now())
assertEquals(clock1.now(), clock3.now())
}
}
17 changes: 17 additions & 0 deletions core/common/test/samples/ClockSamples.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package kotlinx.datetime.test.samples

import kotlinx.datetime.*
import kotlin.test.*
import kotlin.time.Duration.Companion.seconds
import kotlin.time.TestTimeSource

class ClockSamples {
@Test
Expand Down Expand Up @@ -45,4 +47,19 @@ class ClockSamples {
check(clock.todayIn(TimeZone.UTC) == LocalDate(2020, 1, 1))
check(clock.todayIn(TimeZone.of("America/New_York")) == LocalDate(2019, 12, 31))
}

@Test
fun timeSourceAsClock() {
// Creating a TimeSource
// When testing a Clock in combination of kotlinx-coroutines-test, use the testTimeSource of the TestDispatcher.
val timeSource = TestTimeSource()
// Creating a clock by setting the origin, here the epoch start
val clock = timeSource.asClock(origin = Instant.fromEpochSeconds(0))

check(Instant.fromEpochSeconds(0) == clock.now())

// Increasing the timeSource
timeSource += 1.seconds
check(Instant.fromEpochSeconds(1) == clock.now())
}
}

0 comments on commit 73aad58

Please sign in to comment.