Explain mark + Duration arithmetic and comparing two TimeMarks. What does (markB - markA) give, and what does hasPassedNow() mean?
answer
- mark +/- Duration -> shifted TimeMark
- markB - markA -> Duration between
- Marks are Comparable: <, >, maxOf
- hasPassedNow() == elapsedNow() >= 0
- Only compare marks from the SAME source
basics
~20 sYou can add or subtract a Duration to a mark to get a shifted mark, subtract two marks to get the Duration between them, and compare marks. hasPassedNow() returns true once the current time is at or past that mark.
solid answer
~40 sA TimeMark from Monotonic is a ComparableTimeMark, so it supports operators. mark + duration and mark - duration return a new TimeMark shifted forward/backward in time. Subtracting two marks (markB - markA) yields the kotlin.time.Duration between them (positive if B is later). Because they are Comparable, you can use <, >, ==, and compareTo on marks from the same source. hasPassedNow() returns true when elapsedNow() >= zero — i.e., the instant the mark represents is now in the past (handy for a deadline mark created with markNow() + timeout). hasNotPassedNow() is the inverse. Mixing marks from different time sources is undefined; only compare/subtract marks from the same source.
code
kotlin · 13 linesimport kotlin.time.TimeSource
import kotlin.time.Duration.Companion.milliseconds
fun pollUntil(timeout: kotlin.time.Duration, action: () -> Boolean) {
val deadline = TimeSource.Monotonic.markNow() + timeout
while (deadline.hasNotPassedNow()) {
if (action()) return
Thread.sleep(10)
}
error("timed out after $timeout")
}
fun main() = pollUntil(200.milliseconds) { false }go deeper
Knows you can subtract two marks to get how much time passed.
Correctly states + / - with a Duration yields a new mark, mark-minus-mark yields a Duration, and uses hasPassedNow() for deadlines.
Notes ComparableTimeMark, the same-source constraint, and Duration.INFINITE for no-timeout marks.
Reasons about ordering guarantees, immutability of marks, and designing deadline/timeout abstractions on top of comparable marks.
## ComparableTimeMark Marks from `TimeSource.Monotonic` implement **`ComparableTimeMark`** (it is a `TimeSource.WithComparableMarks`). That gives marks full arithmetic and ordering on top of the basic `TimeMark` contract. ## Shifting a mark by a Duration ```kotlin import kotlin.time.TimeSource import kotlin.time.Duration.Companion.seconds val start = TimeSource.Monotonic.markNow() val deadline = start + 5.seconds // a TimeMark 5s after start val earlier = start - 2.seconds // a TimeMark 2s before start ``` `mark + Duration` and `mark - Duration` return **new `TimeMark`s** — marks are immutable points; you never mutate them. ## Subtracting two marks Subtracting one comparable mark from another yields the **`Duration`** between them: ```kotlin val a = TimeSource.Monotonic.markNow() doWork() val b = TimeSource.Monotonic.markNow() val between: kotlin.time.Duration = b - a // positive: b is later ``` ## Comparing marks Because they are `Comparable`, you can order marks directly: ```kotlin if (b > a) { /* b happened later */ } val latest = maxOf(a, b) ``` ## Deadlines: hasPassedNow / hasNotPassedNow `TimeMark` exposes **`hasPassedNow()`** and **`hasNotPassedNow()`**. A deadline pattern: ```kotlin val deadline = TimeSource.Monotonic.markNow() + 5.seconds while (deadline.hasNotPassedNow()) { poll() } ``` `hasPassedNow()` is true exactly when `elapsedNow() >= Duration.ZERO` for that mark — the represented instant is now in the past or present. ## Same-source rule Arithmetic and comparison are only meaningful for marks **from the same `TimeSource`**. Comparing a `Monotonic` mark with a `TestTimeSource` mark is undefined behavior — the platform may throw or give nonsense. Keep marks within one source. ## Infinity A `Duration` can be `Duration.INFINITE`; `mark + Duration.INFINITE` produces a mark in the infinite future, and `hasPassedNow()` on it is always false — useful for "no timeout."
- What happens if you subtract two marks from different time sources?It is undefined/unsupported. ComparableTimeMark operations are only meaningful within the same source; mixing sources may throw or yield meaningless results.
- How would you express 'no timeout' with a deadline mark?Add Duration.INFINITE: markNow() + Duration.INFINITE. hasPassedNow() on it is always false, so the loop never times out.
saying these in an interview costs you the question
- Claiming mark + Duration mutates the original mark
- Comparing marks from Monotonic and a TestTimeSource together
- Thinking markA - markB returns another mark instead of a Duration
- Confusing hasPassedNow() (deadline reached) with elapsedNow() (how long since)