Kotlin Standard Library implementation for WebAssembly System Interface (WASI) platform providing essential I/O, time, random, UUID, and reflection capabilities.
—
The Time and Duration capabilities provide WASI-specific implementations for time sources, clock access, and duration measurements. These implementations use the WASI clock_time_get system call to access both monotonic and real-time clocks available in the WASI environment.
/**
* A monotonic time source that provides elapsed time measurements.
* Uses WASI's clock_time_get with CLOCK_MONOTONIC.
*/
object TimeSource.Monotonic : TimeSource {
/**
* Marks the current point in time for later measurement.
* @return a TimeMark representing the current time
*/
fun markNow(): TimeMark
}/**
* The system clock that provides access to the current date and time.
* Uses WASI's clock_time_get with CLOCK_REALTIME.
*/
object Clock.System : Clock {
/**
* Returns the current moment in time.
* @return the current Instant
*/
fun now(): Instant
}/**
* Represents a time-based amount of time.
*/
@SinceKotlin("1.6")
@JvmInline
value class Duration internal constructor(private val rawValue: Long) : Comparable<Duration> {
companion object {
val ZERO: Duration
val INFINITE: Duration
fun parse(value: String): Duration
fun parseIsoString(value: String): Duration
fun parseOrNull(value: String): Duration?
fun parseIsoStringOrNull(value: String): Duration?
fun convert(value: Double, sourceUnit: DurationUnit, targetUnit: DurationUnit): Double
}
// Arithmetic operations
operator fun unaryMinus(): Duration
operator fun plus(other: Duration): Duration
operator fun minus(other: Duration): Duration
operator fun times(scale: Int): Duration
operator fun times(scale: Double): Duration
operator fun div(scale: Int): Duration
operator fun div(scale: Double): Duration
operator fun div(other: Duration): Double
// Properties and checks
fun isNegative(): Boolean
fun isPositive(): Boolean
fun isInfinite(): Boolean
fun isFinite(): Boolean
val absoluteValue: Duration
// Component extraction
inline fun <T> toComponents(action: (days: Long, hours: Int, minutes: Int, seconds: Int, nanoseconds: Int) -> T): T
inline fun <T> toComponents(action: (hours: Long, minutes: Int, seconds: Int, nanoseconds: Int) -> T): T
inline fun <T> toComponents(action: (minutes: Long, seconds: Int, nanoseconds: Int) -> T): T
inline fun <T> toComponents(action: (seconds: Long, nanoseconds: Int) -> T): T
// Conversion to units
fun toDouble(unit: DurationUnit): Double
fun toLong(unit: DurationUnit): Long
fun toInt(unit: DurationUnit): Int
val inWholeDays: Long
val inWholeHours: Long
val inWholeMinutes: Long
val inWholeSeconds: Long
val inWholeMilliseconds: Long
val inWholeMicroseconds: Long
val inWholeNanoseconds: Long
// String representation
override fun toString(): String
fun toString(unit: DurationUnit, decimals: Int = 0): String
fun toIsoString(): String
override operator fun compareTo(other: Duration): Int
}
/**
* Duration unit enumeration
*/
@WasExperimental(ExperimentalTime::class)
enum class DurationUnit {
NANOSECONDS,
MICROSECONDS,
MILLISECONDS,
SECONDS,
MINUTES,
HOURS,
DAYS
}
/**
* Duration construction extensions
*/
val Int.nanoseconds: Duration
val Long.nanoseconds: Duration
val Double.nanoseconds: Duration
val Int.microseconds: Duration
val Long.microseconds: Duration
val Double.microseconds: Duration
val Int.milliseconds: Duration
val Long.milliseconds: Duration
val Double.milliseconds: Duration
val Int.seconds: Duration
val Long.seconds: Duration
val Double.seconds: Duration
val Int.minutes: Duration
val Long.minutes: Duration
val Double.minutes: Duration
val Int.hours: Duration
val Long.hours: Duration
val Double.hours: Duration
val Int.days: Duration
val Long.days: Duration
val Double.days: Duration/**
* Represents an instantaneous point on the time-line.
*/
@SinceKotlin("2.1")
@ExperimentalTime
class Instant internal constructor(
val epochSeconds: Long,
val nanosecondsOfSecond: Int
) : Comparable<Instant>, Serializable {
companion object {
// Construction
fun fromEpochMilliseconds(epochMilliseconds: Long): Instant
fun fromEpochSeconds(epochSeconds: Long, nanosecondAdjustment: Long = 0): Instant
fun fromEpochSeconds(epochSeconds: Long, nanosecondAdjustment: Int): Instant
// Parsing
fun parse(input: CharSequence): Instant
fun parseOrNull(input: CharSequence): Instant?
// Constants
val DISTANT_PAST: Instant
val DISTANT_FUTURE: Instant
}
// Properties
fun toEpochMilliseconds(): Long
val isDistantPast: Boolean
val isDistantFuture: Boolean
// Arithmetic operations
operator fun plus(duration: Duration): Instant
operator fun minus(duration: Duration): Instant
operator fun minus(other: Instant): Duration
// Comparison and equality
override operator fun compareTo(other: Instant): Int
override fun equals(other: Any?): Boolean
override fun hashCode(): Int
override fun toString(): String // ISO 8601 format
}
/**
* TimeMark interfaces for time measurement
*/
@SinceKotlin("1.9")
@WasExperimental(ExperimentalTime::class)
interface TimeMark {
fun elapsedNow(): Duration
operator fun plus(duration: Duration): TimeMark
operator fun minus(duration: Duration): TimeMark
fun hasPassedNow(): Boolean
fun hasNotPassedNow(): Boolean
}
@SinceKotlin("1.9")
@WasExperimental(ExperimentalTime::class)
interface ComparableTimeMark : TimeMark, Comparable<ComparableTimeMark> {
override operator fun plus(duration: Duration): ComparableTimeMark
override operator fun minus(duration: Duration): ComparableTimeMark
operator fun minus(other: ComparableTimeMark): Duration
override operator fun compareTo(other: ComparableTimeMark): Int
override fun equals(other: Any?): Boolean
override fun hashCode(): Int
}
/**
* Time measurement utility functions
*/
inline fun measureTime(block: () -> Unit): Duration
inline fun TimeSource.measureTime(block: () -> Unit): Duration
inline fun TimeSource.Monotonic.measureTime(block: () -> Unit): Duration
data class TimedValue<T>(val value: T, val duration: Duration)
inline fun <T> measureTimedValue(block: () -> T): TimedValue<T>
inline fun <T> TimeSource.measureTimedValue(block: () -> T): TimedValue<T>
inline fun <T> TimeSource.Monotonic.measureTimedValue(block: () -> T): TimedValue<T>// Measure execution time
val timeMark = TimeSource.Monotonic.markNow()
// Perform some operation
performLongRunningTask()
val elapsedTime = timeMark.elapsedNow()
println("Operation took: $elapsedTime")
// Using measureTime function
val duration = measureTime {
processLargeDataSet()
}
println("Processing took: ${duration.inWholeMilliseconds} ms")
// Using measureTimedValue to get both result and duration
val timedResult = measureTimedValue {
computeExpensiveCalculation()
}
println("Result: ${timedResult.value}, took: ${timedResult.duration}")
// Using with specific TimeSource
val timedWithSource = TimeSource.Monotonic.measureTimedValue {
performComplexOperation()
}
println("Operation result: ${timedWithSource.value}")
println("Duration: ${timedWithSource.duration.inWholeMilliseconds} ms")// Get current timestamp
val now = Clock.System.now()
println("Current time: $now")
// Convert to epoch milliseconds
val epochMillis = now.toEpochMilliseconds()
println("Epoch milliseconds: $epochMillis")
// Convert to epoch seconds
val epochSeconds = now.epochSeconds
println("Epoch seconds: $epochSeconds")// Create durations
val oneSecond = 1.seconds
val halfMinute = 30.seconds
val twoHours = 2.hours
val oneDay = 1.days
// Duration arithmetic
val totalTime = oneSecond + halfMinute + twoHours
val remaining = oneDay - totalTime
// Duration comparisons
if (elapsedTime > 5.seconds) {
println("Operation was slow")
}
// Duration formatting
println("Duration: ${totalTime.inWholeMinutes} minutes")
println("Duration: ${totalTime.toString()}")// Parse ISO-8601 duration strings
val duration1 = Duration.parse("PT1H30M") // 1 hour 30 minutes
val duration2 = Duration.parse("P1DT2H") // 1 day 2 hours
val duration3 = Duration.parseIsoString("PT45.5S") // 45.5 seconds
// Create instants from timestamps
val instant1 = Instant.fromEpochSeconds(1609459200) // 2021-01-01 00:00:00 UTC
val instant2 = Instant.fromEpochMilliseconds(1640995200000) // 2022-01-01 00:00:00 UTC
val instant3 = Instant.fromEpochSeconds(1640995200, 500_000_000) // With nanoseconds// Implement timeout functionality
suspend fun withTimeout(timeout: Duration, block: suspend () -> Unit) {
val startTime = TimeSource.Monotonic.markNow()
while (startTime.elapsedNow() < timeout) {
try {
block()
return
} catch (e: Exception) {
if (startTime.elapsedNow() >= timeout) {
throw TimeoutException("Operation timed out after $timeout")
}
// Continue trying
}
}
}
// Use timeout
withTimeout(30.seconds) {
connectToExternalService()
}// Performance profiling
class PerformanceProfiler {
private val measurements = mutableMapOf<String, Duration>()
fun measure(operation: String, block: () -> Unit) {
val duration = measureTime(block)
measurements[operation] = measurements.getOrDefault(operation, Duration.ZERO) + duration
}
fun report() {
measurements.forEach { (operation, totalTime) ->
println("$operation: ${totalTime.inWholeMilliseconds} ms total")
}
}
}
val profiler = PerformanceProfiler()
profiler.measure("database_query") { executeQuery() }
profiler.measure("data_processing") { processResults() }
profiler.report()Time operations are implemented using the WASI clock_time_get system call:
@WasmImport("wasi_snapshot_preview1", "clock_time_get")
private external fun wasiRawClockTimeGet(
id: Int, // Clock ID (REALTIME or MONOTONIC)
precision: Long, // Requested precision in nanoseconds
time: Int // Pointer to store the result
): IntThe implementation supports two WASI clock types:
Time operations use efficient memory allocation:
// Scoped memory allocation for time queries
MemoryAllocator.scoped { allocator ->
val timePtr = allocator.allocate(8) // 64-bit timestamp storage
val result = wasiRawClockTimeGet(clockId, precision, timePtr.address.toInt())
// Extract timestamp and clean up automatically
}// Efficient: Use monotonic time for measurements
val start = TimeSource.Monotonic.markNow()
// ... operation ...
val elapsed = start.elapsedNow()
// Less efficient: Multiple system clock queries
val start = Clock.System.now()
// ... operation ...
val end = Clock.System.now()
val elapsed = end - start
// Efficient: Reuse TimeMark for multiple measurements
val mark = TimeSource.Monotonic.markNow()
checkPoint1(mark.elapsedNow())
// ... more work ...
checkPoint2(mark.elapsedNow())// Avoid creating unnecessary Duration objects
// Less efficient:
val durations = (1..1000).map { it.milliseconds }
// More efficient:
val baseDuration = 1.milliseconds
val multipliedDuration = baseDuration * 1000Time operations handle WASI-specific errors:
All errors are translated to appropriate Kotlin exceptions:
try {
val now = Clock.System.now()
} catch (e: DateTimeException) {
println("Time access failed: ${e.message}")
}Not all WASI runtimes support all clock types:
WASI implementations have limited time zone support:
Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-stdlib-wasm-wasi