Migrate Instant to kotlin.time

This commit is contained in:
Sergey Chernov 2026-02-18 21:13:21 +03:00
parent 79a541b148
commit 6d943c5e1e
5 changed files with 38 additions and 20 deletions

View File

@ -4,7 +4,7 @@
Before kotlin 2.0, there was an excellent library, kotlinx.datetime, which was widely used everywhere, also in Lyng and its dependencies.
When kotlin 2.0 was released, or soon after, JetBrains made an exptic decision to remove `Instant` and `Clock` from kotlinx.datetime and replace it with _yet experimental_ analogs in `kotlin.time`.
When Kotlin 2.0 was released, or soon after, JetBrains made a perplexing decision to remove `Instant` and `Clock` from kotlinx.datetime and replace it with _yet experimental_ analogs in `kotlin.time`.
The problem is, these were not quite the same (these weren't `@Serializable`!), so people didn't migrate with ease. Okay, then JetBrains decided to not only deprecate it but also make them unusable on Apple targets. It sort of split auditories of many published libraries to those who hate JetBrains and Apple and continue to use 1.9-2.0 compatible versions that no longer work with Kotlin 2.2 on Apple targets (but work pretty well with earlier Kotlin or on other platforms).
@ -12,14 +12,14 @@ Later JetBrains added serializers for their new `Instant` and `Clock` types, but
## Solution
We hereby publish a new version of Lyng, 1.0.8-SNAPSHOT, which uses `ktlin.time.Instant` and `kotlin.time.Clock` instead of `kotlinx.datetime.Instant` and `kotlinx.datetime.Clock; it is in other aspects compatible also with Lynon encoded binaries. Still you might need to migrate your code to use `kotlinx.datetime` types.
We hereby publish a new version of Lyng, 1.0.8-SNAPSHOT, which uses `kotlin.time.Instant` and `kotlin.time.Clock` instead of `kotlinx.datetime.Instant` and `kotlinx.datetime.Clock`. It is in other aspects compatible also with Lynon encoded binaries. You might need to migrate your code to use `kotlin.time` types. (LocalDateTime/TimeZone still come from `kotlinx.datetime`.)
So, if you are getting errors with new version, plase do:
So, if you are getting errors with new version, please do:
- upgrade to Kotlin 2.2
- upgrade to Lyng 1.0.8-SNAPSHOT
- replace in your code imports (or other uses) of`kotlinx.datetime.Clock` to `kotlin.time.Clock` and `kotlinx.datetime.Instant` to `kotlin.time.Instant`.
- replace in your code imports (or other uses) of `kotlinx.datetime.Clock` to `kotlin.time.Clock` and `kotlinx.datetime.Instant` to `kotlin.time.Instant`.
This should solve the problem and hopefully we'll see no more suh a brillant ideas from IDEA ideologspersons.
This should solve the problem and hopefully we'll see no more such "brilliant" ideas from IDEA ideologspersons.
Sorry for inconvenicence and send a ray of hate to JetBrains ;)
Sorry for inconvenience and send a ray of hate to JetBrains ;)

View File

@ -191,7 +191,7 @@ private suspend fun buildFsModule(module: ModuleScope, policy: FsAccessPolicy) {
fsGuard {
val self = this.thisObj as ObjPath
val m = self.ensureMetadata()
m.modifiedAtMillis?.let { ObjInstant(kotlinx.datetime.Instant.fromEpochMilliseconds(it)) } ?: ObjNull
m.modifiedAtMillis?.let { ObjInstant(kotlin.time.Instant.fromEpochMilliseconds(it)) } ?: ObjNull
}
}
// modifiedAtMillis(): Int? — milliseconds since epoch or null

View File

@ -17,7 +17,16 @@
package net.sergeych.lyng.obj
import kotlinx.datetime.*
import kotlinx.datetime.DateTimeUnit
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.UtcOffset
import kotlinx.datetime.asTimeZone
import kotlinx.datetime.isoDayNumber
import kotlinx.datetime.number
import kotlinx.datetime.plus
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonPrimitive
import net.sergeych.lyng.Scope
@ -28,12 +37,13 @@ import net.sergeych.lyng.miniast.type
import net.sergeych.lynon.LynonDecoder
import net.sergeych.lynon.LynonEncoder
import net.sergeych.lynon.LynonType
import kotlin.time.Instant
class ObjDateTime(val instant: Instant, val timeZone: TimeZone) : Obj() {
override val objClass: ObjClass get() = type
val localDateTime: LocalDateTime by lazy {
instant.toLocalDateTime(timeZone)
with(timeZone) { instant.toLocalDateTime() }
}
override fun toString(): String {
@ -177,11 +187,11 @@ class ObjDateTime(val instant: Instant, val timeZone: TimeZone) : Obj() {
addPropertyDoc("year", "The year component.", type("lyng.Int"), moduleName = "lyng.time",
getter = { thisAs<ObjDateTime>().localDateTime.year.toObj() })
addPropertyDoc("month", "The month component (1..12).", type("lyng.Int"), moduleName = "lyng.time",
getter = { thisAs<ObjDateTime>().localDateTime.monthNumber.toObj() })
getter = { thisAs<ObjDateTime>().localDateTime.month.number.toObj() })
addPropertyDoc("dayOfMonth", "The day of month component.", type("lyng.Int"), moduleName = "lyng.time",
getter = { thisAs<ObjDateTime>().localDateTime.dayOfMonth.toObj() })
getter = { thisAs<ObjDateTime>().localDateTime.day.toObj() })
addPropertyDoc("day", "Alias to dayOfMonth.", type("lyng.Int"), moduleName = "lyng.time",
getter = { thisAs<ObjDateTime>().localDateTime.dayOfMonth.toObj() })
getter = { thisAs<ObjDateTime>().localDateTime.day.toObj() })
addPropertyDoc("hour", "The hour component (0..23).", type("lyng.Int"), moduleName = "lyng.time",
getter = { thisAs<ObjDateTime>().localDateTime.hour.toObj() })
addPropertyDoc("minute", "The minute component (0..59).", type("lyng.Int"), moduleName = "lyng.time",
@ -257,7 +267,7 @@ class ObjDateTime(val instant: Instant, val timeZone: TimeZone) : Obj() {
returns = type("lyng.DateTime"),
moduleName = "lyng.time") {
val s = (args.firstAndOnly() as ObjString).value
// kotlinx-datetime's Instant.parse handles RFC3339
// kotlin.time's Instant.parse handles RFC3339
// But we want to preserve the offset if present for DateTime.
// However, Instant.parse("...") always gives an Instant.
// If we want the specific offset from the string, we might need a more complex parse.

View File

@ -17,7 +17,13 @@
package net.sergeych.lyng.obj
import kotlinx.datetime.*
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.UtcOffset
import kotlinx.datetime.asTimeZone
import kotlinx.datetime.number
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonPrimitive
import net.sergeych.lyng.Scope
@ -27,6 +33,7 @@ import net.sergeych.lynon.LynonEncoder
import net.sergeych.lynon.LynonSettings
import net.sergeych.lynon.LynonType
import kotlin.time.Clock
import kotlin.time.Instant
import kotlin.time.isDistantFuture
import kotlin.time.isDistantPast
@ -196,8 +203,8 @@ class ObjInstant(val instant: Instant,val truncateMode: LynonSettings.InstantTru
) {
val t = thisAs<ObjInstant>().instant
val tz = TimeZone.UTC
val dt = t.toLocalDateTime(tz)
val truncated = LocalDateTime(dt.year, dt.month, dt.dayOfMonth, dt.hour, dt.minute, 0, 0)
val dt = with(tz) { t.toLocalDateTime() }
val truncated = LocalDateTime(dt.year, dt.month.number, dt.day, dt.hour, dt.minute, 0, 0)
ObjInstant(truncated.toInstant(tz), LynonSettings.InstantTruncateMode.Second)
}
addFnDoc(

View File

@ -25,6 +25,7 @@ import net.sergeych.lyng.obj.*
import net.sergeych.lynon.*
import java.nio.file.Files
import java.nio.file.Path
import kotlin.time.Instant
import kotlin.test.Ignore
import kotlin.test.Test
import kotlin.test.assertContentEquals
@ -368,11 +369,11 @@ class LynonTests {
roundTrip(ObjReal(1.22345))
roundTrip(ObjReal(-Math.PI))
val now = kotlinx.datetime.Instant.fromEpochMilliseconds(System.currentTimeMillis())
roundTrip(ObjInstant(kotlinx.datetime.Instant.fromEpochSeconds(now.epochSeconds), LynonSettings.InstantTruncateMode.Second))
val now = Instant.fromEpochMilliseconds(System.currentTimeMillis())
roundTrip(ObjInstant(Instant.fromEpochSeconds(now.epochSeconds), LynonSettings.InstantTruncateMode.Second))
roundTrip(
ObjInstant(
kotlinx.datetime.Instant.fromEpochSeconds(
Instant.fromEpochSeconds(
now.epochSeconds,
now.nanosecondsOfSecond / 1_000_000 * 1_000_000
),
@ -381,7 +382,7 @@ class LynonTests {
)
roundTrip(
ObjInstant(
kotlinx.datetime.Instant.fromEpochSeconds(
Instant.fromEpochSeconds(
now.epochSeconds,
now.nanosecondsOfSecond / 1_000 * 1_000
),