Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TimeSource asClock converter #164

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions core/common/src/Clock.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,19 @@ private class InstantTimeMark(private val instant: Instant, private val clock: C
override fun minus(duration: Duration): TimeMark = InstantTimeMark(instant - duration, clock)
}

/**
* Returns the [Clock] by storing an initial [TimeMark] using [TimeSource.markNow] and [returns][Clock.now] the elapsed
* time using [TimeMark.elapsedNow] plus the provided [offset].
hfhbd marked this conversation as resolved.
Show resolved Hide resolved
*
* This clock stores the initial [TimeMark], so repeatedly creating [Clock]s from the same [TimeSource] results
hfhbd marked this conversation as resolved.
Show resolved Hide resolved
* into different [Instant]s iff the time of the [TimeSource] was increased. To sync different [Clock]s, use the [offset]
hfhbd marked this conversation as resolved.
Show resolved Hide resolved
* parameter.
*/
hfhbd marked this conversation as resolved.
Show resolved Hide resolved
@ExperimentalTime
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like, after all this time, this is no longer needed!

hfhbd marked this conversation as resolved.
Show resolved Hide resolved
public fun TimeSource.asClock(offset: Instant = Instant.fromEpochSeconds(0)): Clock = object : Clock {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've deliberated internally about this function, and it does seem useful. A couple of notes:

  • The name offset leaves the impression that it's somehow related to UtcOffset, but it's not. We arrived at the name origin instead.
  • Having a default parameter here leaves the wrong impression. TimeSource.Monotonic.asClock() seems benign, but starts returning dates far in the past. Clock.System.now() would be less surprising, but it's nondeterministic, which is a bad fit for tests (which we'd expect to be the most common use case).

private val startMark: TimeMark = markNow()
override fun now() = offset + startMark.elapsedNow()
}

@Deprecated("Use Clock.todayIn instead", ReplaceWith("this.todayIn(timeZone)"), DeprecationLevel.WARNING)
public fun Clock.todayAt(timeZone: TimeZone): LocalDate = todayIn(timeZone)
51 changes: 51 additions & 0 deletions core/common/test/ClockTest.kt
hfhbd marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2019-2021 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

package kotlinx.datetime.test

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

@ExperimentalTime
hfhbd marked this conversation as resolved.
Show resolved Hide resolved
class ClockTest {
@Test
fun timeSourceAsClock() {
val timeSource = TestTimeSource()
val clock = timeSource.asClock()

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

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

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

val clock2 = timeSource.asClock(offset = 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(offset = clock2.now())
timeSource += 1.seconds
assertEquals(3, clock3.now().epochSeconds)
assertEquals(clock1.now(), clock2.now())
assertEquals(clock1.now(), clock3.now())
}
}