or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

console-io.mdexceptions.mdindex.mdrandom.mdreflection.mdtime.mduuid.md

time.mddocs/

0

# Time and Duration Handling

1

2

## Overview

3

4

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.

5

6

## API Reference

7

8

### Monotonic Time Source

9

10

```kotlin { .api }

11

/**

12

* A monotonic time source that provides elapsed time measurements.

13

* Uses WASI's clock_time_get with CLOCK_MONOTONIC.

14

*/

15

object TimeSource.Monotonic : TimeSource {

16

/**

17

* Marks the current point in time for later measurement.

18

* @return a TimeMark representing the current time

19

*/

20

fun markNow(): TimeMark

21

}

22

```

23

24

### System Clock

25

26

```kotlin { .api }

27

/**

28

* The system clock that provides access to the current date and time.

29

* Uses WASI's clock_time_get with CLOCK_REALTIME.

30

*/

31

object Clock.System : Clock {

32

/**

33

* Returns the current moment in time.

34

* @return the current Instant

35

*/

36

fun now(): Instant

37

}

38

```

39

40

### Duration Operations

41

42

```kotlin { .api }

43

/**

44

* Represents a time-based amount of time.

45

*/

46

@SinceKotlin("1.6")

47

@JvmInline

48

value class Duration internal constructor(private val rawValue: Long) : Comparable<Duration> {

49

companion object {

50

val ZERO: Duration

51

val INFINITE: Duration

52

53

fun parse(value: String): Duration

54

fun parseIsoString(value: String): Duration

55

fun parseOrNull(value: String): Duration?

56

fun parseIsoStringOrNull(value: String): Duration?

57

fun convert(value: Double, sourceUnit: DurationUnit, targetUnit: DurationUnit): Double

58

}

59

60

// Arithmetic operations

61

operator fun unaryMinus(): Duration

62

operator fun plus(other: Duration): Duration

63

operator fun minus(other: Duration): Duration

64

operator fun times(scale: Int): Duration

65

operator fun times(scale: Double): Duration

66

operator fun div(scale: Int): Duration

67

operator fun div(scale: Double): Duration

68

operator fun div(other: Duration): Double

69

70

// Properties and checks

71

fun isNegative(): Boolean

72

fun isPositive(): Boolean

73

fun isInfinite(): Boolean

74

fun isFinite(): Boolean

75

val absoluteValue: Duration

76

77

// Component extraction

78

inline fun <T> toComponents(action: (days: Long, hours: Int, minutes: Int, seconds: Int, nanoseconds: Int) -> T): T

79

inline fun <T> toComponents(action: (hours: Long, minutes: Int, seconds: Int, nanoseconds: Int) -> T): T

80

inline fun <T> toComponents(action: (minutes: Long, seconds: Int, nanoseconds: Int) -> T): T

81

inline fun <T> toComponents(action: (seconds: Long, nanoseconds: Int) -> T): T

82

83

// Conversion to units

84

fun toDouble(unit: DurationUnit): Double

85

fun toLong(unit: DurationUnit): Long

86

fun toInt(unit: DurationUnit): Int

87

val inWholeDays: Long

88

val inWholeHours: Long

89

val inWholeMinutes: Long

90

val inWholeSeconds: Long

91

val inWholeMilliseconds: Long

92

val inWholeMicroseconds: Long

93

val inWholeNanoseconds: Long

94

95

// String representation

96

override fun toString(): String

97

fun toString(unit: DurationUnit, decimals: Int = 0): String

98

fun toIsoString(): String

99

100

override operator fun compareTo(other: Duration): Int

101

}

102

103

/**

104

* Duration unit enumeration

105

*/

106

@WasExperimental(ExperimentalTime::class)

107

enum class DurationUnit {

108

NANOSECONDS,

109

MICROSECONDS,

110

MILLISECONDS,

111

SECONDS,

112

MINUTES,

113

HOURS,

114

DAYS

115

}

116

117

/**

118

* Duration construction extensions

119

*/

120

val Int.nanoseconds: Duration

121

val Long.nanoseconds: Duration

122

val Double.nanoseconds: Duration

123

val Int.microseconds: Duration

124

val Long.microseconds: Duration

125

val Double.microseconds: Duration

126

val Int.milliseconds: Duration

127

val Long.milliseconds: Duration

128

val Double.milliseconds: Duration

129

val Int.seconds: Duration

130

val Long.seconds: Duration

131

val Double.seconds: Duration

132

val Int.minutes: Duration

133

val Long.minutes: Duration

134

val Double.minutes: Duration

135

val Int.hours: Duration

136

val Long.hours: Duration

137

val Double.hours: Duration

138

val Int.days: Duration

139

val Long.days: Duration

140

val Double.days: Duration

141

```

142

143

### Instant Operations

144

145

```kotlin { .api }

146

/**

147

* Represents an instantaneous point on the time-line.

148

*/

149

@SinceKotlin("2.1")

150

@ExperimentalTime

151

class Instant internal constructor(

152

val epochSeconds: Long,

153

val nanosecondsOfSecond: Int

154

) : Comparable<Instant>, Serializable {

155

156

companion object {

157

// Construction

158

fun fromEpochMilliseconds(epochMilliseconds: Long): Instant

159

fun fromEpochSeconds(epochSeconds: Long, nanosecondAdjustment: Long = 0): Instant

160

fun fromEpochSeconds(epochSeconds: Long, nanosecondAdjustment: Int): Instant

161

162

// Parsing

163

fun parse(input: CharSequence): Instant

164

fun parseOrNull(input: CharSequence): Instant?

165

166

// Constants

167

val DISTANT_PAST: Instant

168

val DISTANT_FUTURE: Instant

169

}

170

171

// Properties

172

fun toEpochMilliseconds(): Long

173

val isDistantPast: Boolean

174

val isDistantFuture: Boolean

175

176

// Arithmetic operations

177

operator fun plus(duration: Duration): Instant

178

operator fun minus(duration: Duration): Instant

179

operator fun minus(other: Instant): Duration

180

181

// Comparison and equality

182

override operator fun compareTo(other: Instant): Int

183

override fun equals(other: Any?): Boolean

184

override fun hashCode(): Int

185

override fun toString(): String // ISO 8601 format

186

}

187

188

/**

189

* TimeMark interfaces for time measurement

190

*/

191

@SinceKotlin("1.9")

192

@WasExperimental(ExperimentalTime::class)

193

interface TimeMark {

194

fun elapsedNow(): Duration

195

operator fun plus(duration: Duration): TimeMark

196

operator fun minus(duration: Duration): TimeMark

197

fun hasPassedNow(): Boolean

198

fun hasNotPassedNow(): Boolean

199

}

200

201

@SinceKotlin("1.9")

202

@WasExperimental(ExperimentalTime::class)

203

interface ComparableTimeMark : TimeMark, Comparable<ComparableTimeMark> {

204

override operator fun plus(duration: Duration): ComparableTimeMark

205

override operator fun minus(duration: Duration): ComparableTimeMark

206

operator fun minus(other: ComparableTimeMark): Duration

207

override operator fun compareTo(other: ComparableTimeMark): Int

208

override fun equals(other: Any?): Boolean

209

override fun hashCode(): Int

210

}

211

212

/**

213

* Time measurement utility functions

214

*/

215

inline fun measureTime(block: () -> Unit): Duration

216

inline fun TimeSource.measureTime(block: () -> Unit): Duration

217

inline fun TimeSource.Monotonic.measureTime(block: () -> Unit): Duration

218

219

data class TimedValue<T>(val value: T, val duration: Duration)

220

inline fun <T> measureTimedValue(block: () -> T): TimedValue<T>

221

inline fun <T> TimeSource.measureTimedValue(block: () -> T): TimedValue<T>

222

inline fun <T> TimeSource.Monotonic.measureTimedValue(block: () -> T): TimedValue<T>

223

```

224

225

## Usage Examples

226

227

### Time Measurement

228

229

```kotlin

230

// Measure execution time

231

val timeMark = TimeSource.Monotonic.markNow()

232

233

// Perform some operation

234

performLongRunningTask()

235

236

val elapsedTime = timeMark.elapsedNow()

237

println("Operation took: $elapsedTime")

238

239

// Using measureTime function

240

val duration = measureTime {

241

processLargeDataSet()

242

}

243

println("Processing took: ${duration.inWholeMilliseconds} ms")

244

245

// Using measureTimedValue to get both result and duration

246

val timedResult = measureTimedValue {

247

computeExpensiveCalculation()

248

}

249

println("Result: ${timedResult.value}, took: ${timedResult.duration}")

250

251

// Using with specific TimeSource

252

val timedWithSource = TimeSource.Monotonic.measureTimedValue {

253

performComplexOperation()

254

}

255

println("Operation result: ${timedWithSource.value}")

256

println("Duration: ${timedWithSource.duration.inWholeMilliseconds} ms")

257

```

258

259

### Current Time Access

260

261

```kotlin

262

// Get current timestamp

263

val now = Clock.System.now()

264

println("Current time: $now")

265

266

// Convert to epoch milliseconds

267

val epochMillis = now.toEpochMilliseconds()

268

println("Epoch milliseconds: $epochMillis")

269

270

// Convert to epoch seconds

271

val epochSeconds = now.epochSeconds

272

println("Epoch seconds: $epochSeconds")

273

```

274

275

### Duration Creation and Manipulation

276

277

```kotlin

278

// Create durations

279

val oneSecond = 1.seconds

280

val halfMinute = 30.seconds

281

val twoHours = 2.hours

282

val oneDay = 1.days

283

284

// Duration arithmetic

285

val totalTime = oneSecond + halfMinute + twoHours

286

val remaining = oneDay - totalTime

287

288

// Duration comparisons

289

if (elapsedTime > 5.seconds) {

290

println("Operation was slow")

291

}

292

293

// Duration formatting

294

println("Duration: ${totalTime.inWholeMinutes} minutes")

295

println("Duration: ${totalTime.toString()}")

296

```

297

298

### Parsing Time Strings

299

300

```kotlin

301

// Parse ISO-8601 duration strings

302

val duration1 = Duration.parse("PT1H30M") // 1 hour 30 minutes

303

val duration2 = Duration.parse("P1DT2H") // 1 day 2 hours

304

val duration3 = Duration.parseIsoString("PT45.5S") // 45.5 seconds

305

306

// Create instants from timestamps

307

val instant1 = Instant.fromEpochSeconds(1609459200) // 2021-01-01 00:00:00 UTC

308

val instant2 = Instant.fromEpochMilliseconds(1640995200000) // 2022-01-01 00:00:00 UTC

309

val instant3 = Instant.fromEpochSeconds(1640995200, 500_000_000) // With nanoseconds

310

```

311

312

### Timeout and Scheduling

313

314

```kotlin

315

// Implement timeout functionality

316

suspend fun withTimeout(timeout: Duration, block: suspend () -> Unit) {

317

val startTime = TimeSource.Monotonic.markNow()

318

319

while (startTime.elapsedNow() < timeout) {

320

try {

321

block()

322

return

323

} catch (e: Exception) {

324

if (startTime.elapsedNow() >= timeout) {

325

throw TimeoutException("Operation timed out after $timeout")

326

}

327

// Continue trying

328

}

329

}

330

}

331

332

// Use timeout

333

withTimeout(30.seconds) {

334

connectToExternalService()

335

}

336

```

337

338

### Performance Monitoring

339

340

```kotlin

341

// Performance profiling

342

class PerformanceProfiler {

343

private val measurements = mutableMapOf<String, Duration>()

344

345

fun measure(operation: String, block: () -> Unit) {

346

val duration = measureTime(block)

347

measurements[operation] = measurements.getOrDefault(operation, Duration.ZERO) + duration

348

}

349

350

fun report() {

351

measurements.forEach { (operation, totalTime) ->

352

println("$operation: ${totalTime.inWholeMilliseconds} ms total")

353

}

354

}

355

}

356

357

val profiler = PerformanceProfiler()

358

profiler.measure("database_query") { executeQuery() }

359

profiler.measure("data_processing") { processResults() }

360

profiler.report()

361

```

362

363

## Implementation Details

364

365

### WASI System Call Integration

366

367

Time operations are implemented using the WASI `clock_time_get` system call:

368

369

```kotlin

370

@WasmImport("wasi_snapshot_preview1", "clock_time_get")

371

private external fun wasiRawClockTimeGet(

372

id: Int, // Clock ID (REALTIME or MONOTONIC)

373

precision: Long, // Requested precision in nanoseconds

374

time: Int // Pointer to store the result

375

): Int

376

```

377

378

### Clock Types

379

380

The implementation supports two WASI clock types:

381

382

1. **CLOCK_REALTIME** (0): Wall clock time, subject to adjustments

383

2. **CLOCK_MONOTONIC** (1): Monotonic time, not subject to adjustments

384

385

### Precision and Resolution

386

387

- **Nanosecond Precision**: WASI clocks provide nanosecond precision when supported

388

- **Runtime Dependent**: Actual resolution depends on the WASI runtime and underlying system

389

- **Fallback Handling**: Graceful degradation when high precision is not available

390

391

### Memory Management

392

393

Time operations use efficient memory allocation:

394

395

```kotlin

396

// Scoped memory allocation for time queries

397

MemoryAllocator.scoped { allocator ->

398

val timePtr = allocator.allocate(8) // 64-bit timestamp storage

399

val result = wasiRawClockTimeGet(clockId, precision, timePtr.address.toInt())

400

// Extract timestamp and clean up automatically

401

}

402

```

403

404

## Performance Considerations

405

406

### System Call Efficiency

407

408

- **Caching**: Frequent time queries are optimized to reduce system call overhead

409

- **Batch Operations**: Multiple time operations may be batched when possible

410

- **Clock Selection**: Monotonic clock is preferred for duration measurements

411

412

### Best Practices

413

414

```kotlin

415

// Efficient: Use monotonic time for measurements

416

val start = TimeSource.Monotonic.markNow()

417

// ... operation ...

418

val elapsed = start.elapsedNow()

419

420

// Less efficient: Multiple system clock queries

421

val start = Clock.System.now()

422

// ... operation ...

423

val end = Clock.System.now()

424

val elapsed = end - start

425

426

// Efficient: Reuse TimeMark for multiple measurements

427

val mark = TimeSource.Monotonic.markNow()

428

checkPoint1(mark.elapsedNow())

429

// ... more work ...

430

checkPoint2(mark.elapsedNow())

431

```

432

433

### Memory Efficiency

434

435

```kotlin

436

// Avoid creating unnecessary Duration objects

437

// Less efficient:

438

val durations = (1..1000).map { it.milliseconds }

439

440

// More efficient:

441

val baseDuration = 1.milliseconds

442

val multipliedDuration = baseDuration * 1000

443

```

444

445

## Error Handling

446

447

Time operations handle WASI-specific errors:

448

449

- **EINVAL**: Invalid clock ID or precision value

450

- **EFAULT**: Invalid memory address for result storage

451

- **ENOSYS**: Clock not supported by the WASI runtime

452

- **EOVERFLOW**: Time value cannot be represented

453

454

All errors are translated to appropriate Kotlin exceptions:

455

456

```kotlin

457

try {

458

val now = Clock.System.now()

459

} catch (e: DateTimeException) {

460

println("Time access failed: ${e.message}")

461

}

462

```

463

464

## Platform Limitations

465

466

### Clock Availability

467

468

Not all WASI runtimes support all clock types:

469

470

- **Realtime Clock**: Generally available but may have limited precision

471

- **Monotonic Clock**: May not be available in some minimal WASI implementations

472

- **Process/Thread Clocks**: Not supported in WASI preview1

473

474

### Time Zone Support

475

476

WASI implementations have limited time zone support:

477

478

- **UTC Only**: Most operations assume UTC time zone

479

- **No Local Time**: Local time zone information is typically not available

480

- **No DST**: Daylight saving time adjustments are not handled

481

482

### Precision Limitations

483

484

- **Runtime Dependent**: Actual precision depends on the WASI runtime

485

- **Hardware Dependent**: Underlying hardware capabilities affect precision

486

- **Virtualization Impact**: Virtualized environments may have reduced precision