skip to content

How do you convert a kotlin.time.Duration to a numeric value in a specific unit? Explain DurationUnit and the inWhole* accessors.

level: middleimportance: must knowfreq 45%

answer

  1. inWhole* => Long, truncates toward zero
  2. toDouble(DurationUnit.X) => fractional
  3. DurationUnit enum: NANO..DAYS
  4. toDuration(unit) builds the other direction
  5. INFINITE.inWholeSeconds == Long.MAX_VALUE

basics

~10 s

Use properties like inWholeMilliseconds or inWholeSeconds to get a whole Long count, or toDouble(unit) for a fractional value. DurationUnit is the enum (SECONDS, MILLISECONDS, etc.) you pass when you need to name the unit.

solid answer

~30 s

DurationUnit is an enum (NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS) used to name a unit. Two conversion families exist. The inWhole* properties — inWholeNanoseconds, inWholeMicroseconds, inWholeMilliseconds, inWholeSeconds, inWholeMinutes, inWholeHours, inWholeDays — return a Long, truncated toward zero (so 1500.milliseconds.inWholeSeconds == 1). For fractional precision use toDouble(unit), e.g. 1500.milliseconds.toDouble(DurationUnit.SECONDS) == 1.5. There is also toLong(unit) and toInt(unit) generic over the enum, and toDuration(unit) to go the other way from a number. Prefer inWholeMilliseconds for Java interop (it maps cleanly to APIs expecting a long). Note inWhole* on an INFINITE duration returns Long.MAX_VALUE/MIN_VALUE.

code

kotlin · 9 lines
kotlin
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.DurationUnit

fun main() {
    val d = 1500.milliseconds
    println(d.inWholeSeconds)               // 1   (truncated)
    println(d.toDouble(DurationUnit.SECONDS)) // 1.5 (fractional)
    println(d.inWholeMilliseconds)          // 1500 (Long, Java interop)
}

go deeper

for a junior

Can call inWholeMilliseconds / inWholeSeconds to get a number out of a Duration.

for a middle

Distinguishes truncating inWhole* (Long) from fractional toDouble(unit) and knows the DurationUnit enum.

for a senior

Handles infinity/overflow saturation and chooses the right accessor for Java interop boundaries.

for a principal

Sets a team convention to keep Duration internal and convert only at boundaries, reasoning about precision and saturation tradeoffs.

## DurationUnit `DurationUnit` is an `enum class` naming the time units used by the duration API: `NANOSECONDS`, `MICROSECONDS`, `MILLISECONDS`, `SECONDS`, `MINUTES`, `HOURS`, `DAYS`. You pass it wherever the API needs you to *name* a unit rather than hardcode one. ## Two conversion families ### 1. Whole-unit accessors (Long, truncating) These are **properties**, returning a `Long`, truncated toward zero (not rounded): ```kotlin val d = 1500.milliseconds d.inWholeSeconds // 1 (1.5s truncated) d.inWholeMilliseconds // 1500 d.inWholeNanoseconds // 1_500_000_000 ``` Full set: `inWholeNanoseconds`, `inWholeMicroseconds`, `inWholeMilliseconds`, `inWholeSeconds`, `inWholeMinutes`, `inWholeHours`, `inWholeDays`. ### 2. Generic-unit conversion (fractional or integer) ```kotlin import kotlin.time.DurationUnit val d = 1500.milliseconds d.toDouble(DurationUnit.SECONDS) // 1.5 (fractional, lossy-but-precise) d.toLong(DurationUnit.SECONDS) // 1 (truncating, like inWholeSeconds) d.toInt(DurationUnit.SECONDS) // 1 ``` Use `toDouble(unit)` when you need fractional precision; use `inWhole*`/`toLong(unit)` when you need an integer count. ## Going the other way `number.toDuration(unit)` builds a Duration from a count and a unit: ```kotlin 250.toDuration(DurationUnit.MILLISECONDS) // 250ms ``` ## Edge cases - **Truncation, not rounding:** `1999.milliseconds.inWholeSeconds == 1`. - **Infinity:** `Duration.INFINITE.inWholeSeconds == Long.MAX_VALUE`; negative infinite -> `Long.MIN_VALUE`. - **Overflow:** converting a huge duration to nanoseconds can saturate to `Long.MAX_VALUE`. ## Interop guidance For Java/Android APIs that accept a `long` of milliseconds or a `(long, TimeUnit)` pair, use `inWholeMilliseconds` (or `toLong(unit)`), keeping `Duration` in your Kotlin layer and converting only at the boundary.

  • Why might inWholeSeconds give a 'wrong' answer for 1500.milliseconds?
    It truncates toward zero and returns 1, not 1.5. inWhole* always yields a Long; use toDouble(DurationUnit.SECONDS) for the fractional 1.5.
  • What does Duration.INFINITE.inWholeMilliseconds return?
    Long.MAX_VALUE — infinite durations saturate to the Long extremes when converted to a whole count.

saying these in an interview costs you the question

  • Thinking inWholeSeconds rounds rather than truncates toward zero
  • Using toDouble when an integer count was needed (or vice versa)
  • Inventing accessor names like 'toMillis()' instead of inWholeMilliseconds
  • Not converting to a raw Long at the Java interop boundary

context