Skip to content

Commit e5c399d

Browse files
committed
feat(kotlinx-datetime): Unify time.set and time.delayUntil
The KotlinX.Coroutines team is considering removing advanceBy. Since our main use-case is to set the initial time in a test, which happens before any tasks are registered, the behavior is the same if using a regular delay instead. See Kotlin/kotlinx.coroutines#3919
1 parent f12a05c commit e5c399d

File tree

1 file changed

+53
-6
lines changed
  • compat/compat-kotlinx-datetime/src/commonMain/kotlin

1 file changed

+53
-6
lines changed

compat/compat-kotlinx-datetime/src/commonMain/kotlin/KotlinTime.kt

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import kotlinx.coroutines.test.TestCoroutineScheduler
66
import kotlinx.datetime.Clock
77
import kotlinx.datetime.Instant
88
import opensavvy.prepared.suite.Time
9-
import opensavvy.prepared.suite.advanceByMillis
109
import opensavvy.prepared.suite.nowMillis
1110

1211
@ExperimentalCoroutinesApi
@@ -53,13 +52,33 @@ val Time.now: Instant
5352
/**
5453
* Advances the virtual time until it reaches [instant].
5554
*
55+
* ### Comparison with delayUntil
56+
*
57+
* This function is identical in behavior to [delayUntil].
58+
* It exists because tests often read better when using it to set the initial date:
59+
* ```kotlin
60+
* test("Some test") {
61+
* // Given:
62+
* time.set(Instant.parse("2024-02-13T21:32:41Z"))
63+
*
64+
* // When:
65+
* // …
66+
* delayUntil(Instant.parse("2024-02-13T21:35:01Z"))
67+
* // …
68+
*
69+
* // Then:
70+
* // …
71+
* }
72+
* ```
73+
*
74+
* We recommend using [set] to set the initial date at the very start of a test, and using [delayUntil] inside the test
75+
* logic.
76+
*
5677
* It is not possible to set the time to a date in the past.
5778
*/
5879
@ExperimentalCoroutinesApi
59-
fun Time.set(instant: Instant) {
60-
val diff = instant.toEpochMilliseconds() - nowMillis
61-
require(diff >= 0) { "Cannot advance to $instant, which is in the past of the current virtual time, $now" }
62-
advanceByMillis(diff)
80+
suspend fun Time.set(instant: Instant) {
81+
delayUntil(instant)
6382
}
6483

6584
/**
@@ -77,17 +96,42 @@ fun Time.set(instant: Instant) {
7796
* }
7897
* ```
7998
*
99+
* ### Comparison with delayUntil
100+
*
101+
* This function is identical in behavior to [delayUntil].
102+
* It exists because tests often read better when using it to set the initial date:
103+
* ```kotlin
104+
* test("Some test") {
105+
* // Given:
106+
* time.set("2024-02-13T21:32:41Z")
107+
*
108+
* // When:
109+
* // …
110+
* delayUntil("2024-02-13T21:35:01Z")
111+
* // …
112+
*
113+
* // Then:
114+
* // …
115+
* }
116+
* ```
117+
*
118+
* We recommend using [set] to set the initial date at the very start of a test, and using [delayUntil] inside the test
119+
* logic.
120+
*
80121
* @see now Access the current time
81122
* @see delay Wait for some duration
82123
* @see delayUntil Wait for a specific time
83124
*/
84125
@ExperimentalCoroutinesApi
85-
fun Time.set(isoString: String) {
126+
suspend fun Time.set(isoString: String) {
86127
set(Instant.parse(isoString))
87128
}
88129

89130
/**
90131
* Delays until the virtual time reaches [instant], executing all enqueued tasks in order.
132+
*
133+
* `delayUntil` is useful to artificially trigger time-dependent algorithms.
134+
* To set the initial time at the start of the test, use [set].
91135
*/
92136
@ExperimentalCoroutinesApi
93137
suspend fun Time.delayUntil(instant: Instant) {
@@ -99,6 +143,9 @@ suspend fun Time.delayUntil(instant: Instant) {
99143
/**
100144
* Delays until the virtual time reaches [isoString], formatted as an ISO 8601 timestamp, executing all enqueued tasks in order.
101145
*
146+
* `delayUntil` is useful to artificially trigger time-dependent algorithms.
147+
* To set the initial time at the start of the test, use [set].
148+
*
102149
* @see set Set the current time
103150
* @see now Access the current time
104151
*/

0 commit comments

Comments
 (0)