or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-types.mdformatting.mdindex.mdjvm-interop.mdperiods-units.mdserialization.md

jvm-interop.mddocs/

0

# JVM Interoperability

1

2

This document covers the bidirectional converter functions for seamless integration with existing Java codebases using `java.time` types. All converters provide zero-overhead conversion between kotlinx-datetime and java.time.

3

4

## Overview

5

6

kotlinx-datetime provides extension functions for converting between kotlinx-datetime types and their corresponding `java.time` equivalents. This enables:

7

8

- **Gradual Migration**: Incrementally adopt kotlinx-datetime in existing Java/Kotlin codebases

9

- **Library Interoperability**: Use kotlinx-datetime with libraries that expect java.time types

10

- **Legacy Integration**: Integrate with existing APIs and databases using java.time

11

- **Zero Overhead**: Direct conversion without data loss or performance penalty

12

13

## LocalDate Converters

14

15

Convert between `kotlinx.datetime.LocalDate` and `java.time.LocalDate`.

16

17

```kotlin { .api }

18

// kotlinx-datetime to java.time

19

fun LocalDate.toJavaLocalDate(): java.time.LocalDate

20

21

// java.time to kotlinx-datetime

22

fun java.time.LocalDate.toKotlinLocalDate(): LocalDate

23

```

24

25

### Usage Examples

26

27

```kotlin

28

import kotlinx.datetime.LocalDate

29

import kotlinx.datetime.toJavaLocalDate

30

import kotlinx.datetime.toKotlinLocalDate

31

32

// Convert kotlinx-datetime to java.time

33

val kotlinxDate = LocalDate(2023, 12, 25)

34

val javaDate = kotlinxDate.toJavaLocalDate()

35

36

// Use with java.time APIs

37

val daysInMonth = javaDate.lengthOfMonth()

38

val isLeapYear = javaDate.isLeapYear

39

40

// Convert java.time to kotlinx-datetime

41

val javaDateFromDb = java.time.LocalDate.of(2023, 6, 15)

42

val kotlinxDate2 = javaDateFromDb.toKotlinLocalDate()

43

44

// Interoperability with existing APIs

45

fun processJavaDate(date: java.time.LocalDate) {

46

val kotlinxDate = date.toKotlinLocalDate()

47

// Use kotlinx-datetime operations

48

val futureDate = kotlinxDate.plus(30, DateTimeUnit.DAY)

49

println("30 days later: ${futureDate.toJavaLocalDate()}")

50

}

51

```

52

53

## LocalTime Converters

54

55

Convert between `kotlinx.datetime.LocalTime` and `java.time.LocalTime`.

56

57

```kotlin { .api }

58

// kotlinx-datetime to java.time

59

fun LocalTime.toJavaLocalTime(): java.time.LocalTime

60

61

// java.time to kotlinx-datetime

62

fun java.time.LocalTime.toKotlinLocalTime(): LocalTime

63

```

64

65

### Usage Examples

66

67

```kotlin

68

import kotlinx.datetime.LocalTime

69

import kotlinx.datetime.toJavaLocalTime

70

import kotlinx.datetime.toKotlinLocalTime

71

72

// Convert kotlinx-datetime to java.time

73

val kotlinxTime = LocalTime(14, 30, 45, 123_456_789)

74

val javaTime = kotlinxTime.toJavaLocalTime()

75

76

// Use with java.time APIs

77

val hourOfDay = javaTime.hour

78

val truncatedToMinutes = javaTime.truncatedTo(java.time.temporal.ChronoUnit.MINUTES)

79

80

// Convert java.time to kotlinx-datetime

81

val javaTimeFromSystem = java.time.LocalTime.now()

82

val kotlinxTime2 = javaTimeFromSystem.toKotlinLocalTime()

83

84

// Database integration example

85

fun saveTimeToDatabase(time: LocalTime) {

86

val javaTime = time.toJavaLocalTime()

87

// Use with JPA/Hibernate that expects java.time.LocalTime

88

entityManager.persist(TimeEntity(scheduledAt = javaTime))

89

}

90

```

91

92

## LocalDateTime Converters

93

94

Convert between `kotlinx.datetime.LocalDateTime` and `java.time.LocalDateTime`.

95

96

```kotlin { .api }

97

// kotlinx-datetime to java.time

98

fun LocalDateTime.toJavaLocalDateTime(): java.time.LocalDateTime

99

100

// java.time to kotlinx-datetime

101

fun java.time.LocalDateTime.toKotlinLocalDateTime(): LocalDateTime

102

```

103

104

### Usage Examples

105

106

```kotlin

107

import kotlinx.datetime.LocalDateTime

108

import kotlinx.datetime.toJavaLocalDateTime

109

import kotlinx.datetime.toKotlinLocalDateTime

110

111

// Convert kotlinx-datetime to java.time

112

val kotlinxDateTime = LocalDateTime(2023, 12, 25, 14, 30, 45)

113

val javaDateTime = kotlinxDateTime.toJavaLocalDateTime()

114

115

// Use with java.time APIs

116

val year = javaDateTime.year

117

val withNano = javaDateTime.withNano(123_456_789)

118

119

// Convert java.time to kotlinx-datetime

120

val javaDateTimeFromApi = java.time.LocalDateTime.parse("2023-12-25T14:30:45")

121

val kotlinxDateTime2 = javaDateTimeFromApi.toKotlinLocalDateTime()

122

123

// API integration example

124

fun handleApiResponse(javaDateTime: java.time.LocalDateTime) {

125

val kotlinxDateTime = javaDateTime.toKotlinLocalDateTime()

126

val timeZone = TimeZone.currentSystemDefault()

127

val instant = kotlinxDateTime.toInstant(timeZone)

128

println("Instant: $instant")

129

}

130

```

131

132

## Instant Converters

133

134

Convert between `kotlin.time.Instant` and `java.time.Instant`.

135

136

```kotlin { .api }

137

// kotlin.time to java.time

138

fun Instant.toJavaInstant(): java.time.Instant

139

140

// java.time to kotlin.time

141

fun java.time.Instant.toKotlinInstant(): Instant

142

```

143

144

### Usage Examples

145

146

```kotlin

147

import kotlin.time.Instant

148

import kotlinx.datetime.toJavaInstant

149

import kotlinx.datetime.toKotlinInstant

150

import kotlinx.datetime.Clock

151

152

// Convert kotlin.time to java.time

153

val kotlinInstant = Clock.System.now()

154

val javaInstant = kotlinInstant.toJavaInstant()

155

156

// Use with java.time APIs

157

val epochMilli = javaInstant.toEpochMilli()

158

val plusSeconds = javaInstant.plusSeconds(3600)

159

160

// Convert java.time to kotlin.time

161

val javaInstantFromSystem = java.time.Instant.now()

162

val kotlinInstant2 = javaInstantFromSystem.toKotlinInstant()

163

164

// Database timestamp example

165

fun logEvent(event: String) {

166

val instant = Clock.System.now()

167

val javaInstant = instant.toJavaInstant()

168

// Use with database APIs expecting java.time.Instant

169

val timestamp = java.sql.Timestamp.from(javaInstant)

170

logRepository.save(LogEntry(event, timestamp))

171

}

172

```

173

174

## TimeZone Converters

175

176

Convert between `kotlinx.datetime.TimeZone` and `java.time.ZoneId`.

177

178

```kotlin { .api }

179

// kotlinx-datetime to java.time

180

fun TimeZone.toJavaZoneId(): java.time.ZoneId

181

182

// java.time to kotlinx-datetime

183

fun java.time.ZoneId.toKotlinTimeZone(): TimeZone

184

```

185

186

### Usage Examples

187

188

```kotlin

189

import kotlinx.datetime.TimeZone

190

import kotlinx.datetime.toJavaZoneId

191

import kotlinx.datetime.toKotlinTimeZone

192

193

// Convert kotlinx-datetime to java.time

194

val kotlinxTimeZone = TimeZone.of("America/New_York")

195

val javaZoneId = kotlinxTimeZone.toJavaZoneId()

196

197

// Use with java.time APIs

198

val zoneRules = javaZoneId.rules

199

val displayName = javaZoneId.getDisplayName(

200

java.time.format.TextStyle.FULL,

201

java.util.Locale.US

202

)

203

204

// Convert java.time to kotlinx-datetime

205

val javaZoneFromSystem = java.time.ZoneId.systemDefault()

206

val kotlinxTimeZone2 = javaZoneFromSystem.toKotlinTimeZone()

207

208

// Scheduling system integration

209

fun scheduleTask(dateTime: LocalDateTime, timeZone: TimeZone) {

210

val javaDateTime = dateTime.toJavaLocalDateTime()

211

val javaZone = timeZone.toJavaZoneId()

212

val zonedDateTime = java.time.ZonedDateTime.of(javaDateTime, javaZone)

213

214

// Use with scheduling library expecting java.time types

215

scheduler.schedule(task, zonedDateTime)

216

}

217

```

218

219

## UtcOffset Converters

220

221

Convert between `kotlinx.datetime.UtcOffset` and `java.time.ZoneOffset`.

222

223

```kotlin { .api }

224

// kotlinx-datetime to java.time

225

fun UtcOffset.toJavaZoneOffset(): java.time.ZoneOffset

226

227

// java.time to kotlinx-datetime

228

fun java.time.ZoneOffset.toKotlinUtcOffset(): UtcOffset

229

```

230

231

### Usage Examples

232

233

```kotlin

234

import kotlinx.datetime.UtcOffset

235

import kotlinx.datetime.toJavaZoneOffset

236

import kotlinx.datetime.toKotlinUtcOffset

237

238

// Convert kotlinx-datetime to java.time

239

val kotlinxOffset = UtcOffset(hours = -5, minutes = 30)

240

val javaOffset = kotlinxOffset.toJavaZoneOffset()

241

242

// Use with java.time APIs

243

val totalSeconds = javaOffset.totalSeconds

244

val offsetTime = java.time.OffsetTime.of(14, 30, 0, 0, javaOffset)

245

246

// Convert java.time to kotlinx-datetime

247

val javaOffsetFromApi = java.time.ZoneOffset.ofHours(2)

248

val kotlinxOffset2 = javaOffsetFromApi.toKotlinUtcOffset()

249

```

250

251

## Month Converters

252

253

Convert between `kotlinx.datetime.Month` and `java.time.Month`.

254

255

```kotlin { .api }

256

// kotlinx-datetime to java.time

257

fun Month.toJavaMonth(): java.time.Month

258

259

// java.time to kotlinx-datetime

260

fun java.time.Month.toKotlinMonth(): Month

261

```

262

263

### Usage Examples

264

265

```kotlin

266

import kotlinx.datetime.Month

267

import kotlinx.datetime.toJavaMonth

268

import kotlinx.datetime.toKotlinMonth

269

270

// Convert kotlinx-datetime to java.time

271

val kotlinxMonth = Month.DECEMBER

272

val javaMonth = kotlinxMonth.toJavaMonth()

273

274

// Use with java.time APIs

275

val monthValue = javaMonth.value // 12

276

val displayName = javaMonth.getDisplayName(

277

java.time.format.TextStyle.FULL,

278

java.util.Locale.US

279

) // "December"

280

281

// Convert java.time to kotlinx-datetime

282

val javaMonthFromApi = java.time.Month.JUNE

283

val kotlinxMonth2 = javaMonthFromApi.toKotlinMonth()

284

285

// Business logic example

286

fun getSeasonForMonth(month: Month): String {

287

val javaMonth = month.toJavaMonth()

288

return when (javaMonth) {

289

java.time.Month.DECEMBER, java.time.Month.JANUARY, java.time.Month.FEBRUARY -> "Winter"

290

java.time.Month.MARCH, java.time.Month.APRIL, java.time.Month.MAY -> "Spring"

291

java.time.Month.JUNE, java.time.Month.JULY, java.time.Month.AUGUST -> "Summer"

292

else -> "Fall"

293

}

294

}

295

```

296

297

## YearMonth Converters

298

299

Convert between `kotlinx.datetime.YearMonth` and `java.time.YearMonth`.

300

301

```kotlin { .api }

302

// kotlinx-datetime to java.time

303

fun YearMonth.toJavaYearMonth(): java.time.YearMonth

304

305

// java.time to kotlinx-datetime

306

fun java.time.YearMonth.toKotlinYearMonth(): YearMonth

307

```

308

309

### Usage Examples

310

311

```kotlin

312

import kotlinx.datetime.YearMonth

313

import kotlinx.datetime.toJavaYearMonth

314

import kotlinx.datetime.toKotlinYearMonth

315

316

// Convert kotlinx-datetime to java.time

317

val kotlinxYearMonth = YearMonth(2023, 12)

318

val javaYearMonth = kotlinxYearMonth.toJavaYearMonth()

319

320

// Use with java.time APIs

321

val lengthOfMonth = javaYearMonth.lengthOfMonth() // 31

322

val isLeapYear = javaYearMonth.isLeapYear

323

324

// Convert java.time to kotlinx-datetime

325

val javaYearMonthFromDb = java.time.YearMonth.of(2023, 6)

326

val kotlinxYearMonth2 = javaYearMonthFromDb.toKotlinYearMonth()

327

328

// Reporting system example

329

fun generateMonthlyReport(yearMonth: YearMonth): Report {

330

val javaYearMonth = yearMonth.toJavaYearMonth()

331

val startOfMonth = javaYearMonth.atDay(1)

332

val endOfMonth = javaYearMonth.atEndOfMonth()

333

334

return Report(

335

period = yearMonth,

336

startDate = startOfMonth.toKotlinLocalDate(),

337

endDate = endOfMonth.toKotlinLocalDate()

338

)

339

}

340

```

341

342

## DayOfWeek Converters

343

344

Convert between `kotlinx.datetime.DayOfWeek` and `java.time.DayOfWeek`.

345

346

```kotlin { .api }

347

// kotlinx-datetime to java.time

348

fun DayOfWeek.toJavaDayOfWeek(): java.time.DayOfWeek

349

350

// java.time to kotlinx-datetime

351

fun java.time.DayOfWeek.toKotlinDayOfWeek(): DayOfWeek

352

```

353

354

### Usage Examples

355

356

```kotlin

357

import kotlinx.datetime.DayOfWeek

358

import kotlinx.datetime.toJavaDayOfWeek

359

import kotlinx.datetime.toKotlinDayOfWeek

360

361

// Convert kotlinx-datetime to java.time

362

val kotlinxDayOfWeek = DayOfWeek.FRIDAY

363

val javaDayOfWeek = kotlinxDayOfWeek.toJavaDayOfWeek()

364

365

// Use with java.time APIs

366

val dayValue = javaDayOfWeek.value // 5

367

val displayName = javaDayOfWeek.getDisplayName(

368

java.time.format.TextStyle.FULL,

369

java.util.Locale.US

370

) // "Friday"

371

372

// Convert java.time to kotlinx-datetime

373

val javaDayFromTemporal = java.time.LocalDate.now().dayOfWeek

374

val kotlinxDayOfWeek2 = javaDayFromTemporal.toKotlinDayOfWeek()

375

376

// Business hours calculation example

377

fun isBusinessDay(dayOfWeek: DayOfWeek): Boolean {

378

val javaDayOfWeek = dayOfWeek.toJavaDayOfWeek()

379

return javaDayOfWeek != java.time.DayOfWeek.SATURDAY &&

380

javaDayOfWeek != java.time.DayOfWeek.SUNDAY

381

}

382

```

383

384

## Duration Converters

385

386

Convert between `kotlin.time.Duration` and `java.time.Duration`.

387

388

```kotlin { .api }

389

// kotlin.time to java.time

390

fun Duration.toJavaDuration(): java.time.Duration

391

392

// java.time to kotlin.time

393

fun java.time.Duration.toKotlinDuration(): Duration

394

```

395

396

### Usage Examples

397

398

```kotlin

399

import kotlin.time.Duration

400

import kotlin.time.Duration.Companion.hours

401

import kotlin.time.Duration.Companion.minutes

402

import kotlinx.datetime.toJavaDuration

403

import kotlinx.datetime.toKotlinDuration

404

405

// Convert kotlin.time to java.time

406

val kotlinDuration = 2.hours + 30.minutes

407

val javaDuration = kotlinDuration.toJavaDuration()

408

409

// Use with java.time APIs

410

val seconds = javaDuration.seconds

411

val nanos = javaDuration.nano

412

413

// Convert java.time to kotlin.time

414

val javaDurationFromApi = java.time.Duration.ofHours(8)

415

val kotlinDuration2 = javaDurationFromApi.toKotlinDuration()

416

417

// Task scheduling example

418

fun schedulePeriodicTask(interval: Duration) {

419

val javaDuration = interval.toJavaDuration()

420

// Use with Java scheduling APIs

421

scheduledExecutor.scheduleAtFixedRate(

422

task,

423

0,

424

javaDuration.toMillis(),

425

java.util.concurrent.TimeUnit.MILLISECONDS

426

)

427

}

428

```

429

430

## Common Integration Patterns

431

432

### Database Integration

433

434

```kotlin

435

// JPA Entity with java.time types

436

@Entity

437

data class EventEntity(

438

@Id val id: String,

439

val title: String,

440

val startTime: java.time.Instant,

441

val date: java.time.LocalDate,

442

val timeZone: String

443

)

444

445

// Service layer with kotlinx-datetime

446

class EventService {

447

fun createEvent(title: String, dateTime: LocalDateTime, timeZone: TimeZone): String {

448

val instant = dateTime.toInstant(timeZone)

449

val entity = EventEntity(

450

id = UUID.randomUUID().toString(),

451

title = title,

452

startTime = instant.toJavaInstant(), // Convert for database

453

date = dateTime.date.toJavaLocalDate(), // Convert for database

454

timeZone = timeZone.id

455

)

456

return repository.save(entity).id

457

}

458

459

fun getEvent(id: String): Event? {

460

val entity = repository.findById(id) ?: return null

461

return Event(

462

id = entity.id,

463

title = entity.title,

464

instant = entity.startTime.toKotlinInstant(), // Convert from database

465

date = entity.date.toKotlinLocalDate(), // Convert from database

466

timeZone = TimeZone.of(entity.timeZone)

467

)

468

}

469

}

470

```

471

472

### API Integration

473

474

```kotlin

475

// External API client expecting java.time types

476

class ExternalCalendarClient {

477

fun scheduleEvent(

478

title: String,

479

startTime: java.time.ZonedDateTime,

480

duration: java.time.Duration

481

): CompletableFuture<String>

482

}

483

484

// Internal service using kotlinx-datetime

485

class CalendarService(private val client: ExternalCalendarClient) {

486

suspend fun scheduleEvent(

487

title: String,

488

dateTime: LocalDateTime,

489

timeZone: TimeZone,

490

duration: DateTimePeriod

491

): String {

492

// Convert kotlinx-datetime types to java.time for external API

493

val javaDateTime = dateTime.toJavaLocalDateTime()

494

val javaZoneId = timeZone.toJavaZoneId()

495

val zonedDateTime = java.time.ZonedDateTime.of(javaDateTime, javaZoneId)

496

497

// Convert period to duration (simplified for time-based components)

498

val javaDuration = java.time.Duration.ofHours(duration.hours.toLong())

499

.plusMinutes(duration.minutes.toLong())

500

.plusSeconds(duration.seconds.toLong())

501

502

return client.scheduleEvent(title, zonedDateTime, javaDuration).await()

503

}

504

}

505

```

506

507

### Legacy Code Migration

508

509

```kotlin

510

// Legacy code using java.time

511

class LegacyDateUtils {

512

companion object {

513

@JvmStatic

514

fun addBusinessDays(date: java.time.LocalDate, days: Int): java.time.LocalDate {

515

// Existing java.time-based logic

516

var result = date

517

var addedDays = 0

518

while (addedDays < days) {

519

result = result.plusDays(1)

520

if (result.dayOfWeek != java.time.DayOfWeek.SATURDAY &&

521

result.dayOfWeek != java.time.DayOfWeek.SUNDAY) {

522

addedDays++

523

}

524

}

525

return result

526

}

527

}

528

}

529

530

// New code using kotlinx-datetime with legacy integration

531

class ModernDateService {

532

fun addBusinessDays(date: LocalDate, days: Int): LocalDate {

533

val javaDate = date.toJavaLocalDate()

534

val resultJavaDate = LegacyDateUtils.addBusinessDays(javaDate, days)

535

return resultJavaDate.toKotlinLocalDate()

536

}

537

}

538

```

539

540

## Performance Considerations

541

542

- **Zero Overhead**: All conversions are direct mappings with no additional allocations

543

- **Nullable Handling**: java.time types are non-nullable, kotlinx-datetime types are also non-nullable

544

- **Precision**: All conversions preserve full precision (nanoseconds for time, exact values for dates)

545

- **Timezone Data**: Both libraries use the same underlying timezone database, ensuring consistency

546

- **Memory**: No additional memory overhead beyond the objects themselves

547

548

## Best Practices

549

550

1. **Conversion Boundaries**: Convert at system boundaries (database, API, legacy code)

551

2. **Internal Consistency**: Use one datetime library consistently within modules

552

3. **Gradual Migration**: Convert incrementally, starting with new code

553

4. **Testing**: Test conversion roundtrips to ensure data integrity

554

5. **Documentation**: Document which library is used in which parts of the codebase