[Kotlin]kotlinx-datetime v0.7.0の対応について
kotlinx.datetime v0.7.0
kotlinx-datetimeのv0.7.0がリリースされました。
リリースノートにある通り破壊的変更があるのでその対応方法についてメモします。
kotlinx.datetime.Instant
とkotlinx.datetime.Clock
のエイリアスが追加されているので、v0.7.0からv0.7.1と段階的に移行するより一気にv0.7.1にアップデートする方が移行しやすいかと思います。
この記事ではv0.7.1について記載していきます。
主な変更点は以下です。
-
kotlinx.datetime.Instant
とkotlinx.datetime.Clock
が非推奨になった -
kotlin.time.Instant
とkotlin.time.Clock
に変更する必要がある
kotlinx.datetime.Instantをゴリゴリに使っていたら変更点が多く移行は大変かと思いますが頑張っていきましょう。
注意点
kotlinx.serialization
を同一プロジェクトで使用しており、kotlinx.datetime.Instant
のJSONシリアライズなどをしている場合は、kotlinx.serialization
を1.9.0
以上にしないといけません。
また、Androidで使う場合、2025年8月13日現在では最新のAndroid Gradle Pluginのバージョンは8.12.0
となっており、対応するKotlinのバージョンは2.1.20
となっています。
plugins {
id("com.android.application") version "8.12.0" apply false
id("com.android.library") version "8.12.0" apply false
id("org.jetbrains.kotlin.android") version "2.1.20" apply false
}
kotlinx.serialization
の1.9.0
はKotlinのバージョンが2.2
以降が必須とされているので、KotlinやAGPのアップグレードが難しい場合はkotlinx-datetime
をv0.7.0
以上にはしない方がいいかもしれません。
対応内容
バージョン指定
kotlinx-datetime
のバージョンを0.7.1
にします。
VersionCatalog
[versions]
kotlinxDatetime = "0.7.1"
kotlinxSerializationJson = "1.9.0"
[libraries]
kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinxDatetime" }
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
Gradle
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0")
筆者の環境ではkotlinx.serialization
も使用しているためそちらも記載しました。
変更したら Sync Project with Gradle Files
をします。
importの移行
import kotlinx.datetime.Instant // これを kotlin.time.Instant にreplace
import kotlinx.datetime.Clock // これを kotlin.time.Clock にreplace
IDEにAndroidStudioを使用している方は一括でreplace可能かと思います。
その後 Build
→ Clean and Assemble Project with Tests
を実行するとオプトインのエラーがでるかと思います。
ExperimentalTimeアノテーションの対応
Kotlinではまだ安定版ではないAPIを使う場合はアノテーションをオプトインする必要があります。
kotlin.time.Instant
とkotlin.time.Clock
にはまだ安定版ではない時間関連のAPIとして@ExperimentalTime
がついています。
しかし、これらはすでに安定版としてリリースされており段階的に削除されるようです。
今はまだ残っているのでオプトインしないとコンパイルエラーになります。
設定方法としては以下の3種類があります。
// 1.ktファイル全体でオプトイン
@file:OptIn(ExperimentalTime::class) // .ktファイルの先頭1行目に書く
// 2. 関数レベルでオプトイン
@OptIn(ExperimentalTime::class)
fun someFunction(
time: kotlin.time.Instant
) {
val duration = measureTime {
// 何らかの処理
}
}
// 3. モジュール単位でオプトイン
// build.gradle.kts(ルート以外)
kotlinOptions {
jvmTarget = "17"
freeCompilerArgs += listOf(
"-opt-in=kotlin.time.ExperimentalTime"
)
}
実装箇所が少なければ1や2で済むかと思います。
たくさんある場合は3のモジュール単位でオプトインする方法が楽かと思います。
いずれKotlinのバージョンを上げたときにbuild.grale.kts
で非推奨の警告がでたら削除してください。
kotlinx.datetime.Instant
kotlinx.datetime.Instant
の関連処理はkotlin.time.Instant
には存在しないので移行する必要があります。
任意のパターンの文字列をInstant型に変換する処理で使われるFormatStringsInDatetimeFormats
を受け取るInstant.parse()
は以下のように変更します。
// Before
@OptIn(FormatStringsInDatetimeFormats::class)
fun toInstant(
time: String,
pattern: String,
): Instant {
val format = DateTimeComponents.Format { byUnicodePattern(pattern) }
return Instant.parse(time, format)
}
// After
@OptIn(FormatStringsInDatetimeFormats::class)
fun toInstant(
time: String,
pattern: String,
): Instant {
val format = LocalDateTime.Format { byUnicodePattern(pattern) } // DateTimeComponents を LocalDateTime に
val ldt = LocalDateTime.parse(time, format) // LocalDateTimeに変換してからInstantにする
return ldt.toInstant(TimeZone.currentSystemDefault())
}
String
はLocalDateTime
に変換してkotlin.time.Instant
に変換します。
kotlinx.datetime.LocalDate と LocalDateTime
fun toLocalDateTime(
localDate: LocalDate,
): LocalDateTime {
return LocalDateTime(
year = localDate.year,
monthNumber = localDate.monthNumber, // `month = localDate.month.number,` にする
dayOfMonth = localDate.dayOfMonth, // `day = localDate.day,` にする
hour = 0,
minute = 0,
second = 0,
nanosecond = 0,
)
}
kotlinx.serializationのkotlin.time.Instant対応
kotlinx.datetime
ライブラリはKotlin standard library(kotlin.time.Instant)
へ移行したのでkotlin.time.Instant
のシリアライザは存在しません。
そのためkotlinx.serialization
の@Serializable
が定義されているクラスのkotlin.time.Instant
はそのままではシリアライズできません。
このあたりの詳しい内容はリリースノートに記載されています。
例えば以下のようにkotlinx.serialization
を使ったHTTPレスポンスでJSONを受け取りKotlinオブジェクトに変換するクラスが定義されている場合はこのように変更しないとコンパイルエラーになります。
// Before
@Serializable
data class HttpResponseGet(
@SerialName(value = "id")
val id: Int,
@SerialName(value = "name")
val name: String,
@SerialName(value = "createdAt")
val createdAt: kotlin.time.Instant,
)
// After
@Serializable
data class HttpResponseGet(
@SerialName(value = "id")
val id: Int,
@SerialName(value = "name")
val name: String,
@SerialName(value = "createdAt")
@Serializable(with = InstantComponentSerializer::class) // ←を追加する
val createdAt: kotlin.time.Instant,
)
記事の最初の方でも記載してありますが、
AGP 8.12.0
に対応しているKotlinのバージョンは2.1.20
です。
しかし、kotlin.time.Instant
のシリアライザ(InstantComponentSerializer
)が含まれているのはkotlinx-serialization
の1.9.0
です。
これにはKotlinのバージョンは2.2
が必須とされています。
そのため現時点(2025年8月13日)のAndroidではまだこれらのライブラリのアップデートはしない方が無難かと思われます。
参考リンク
- https://github.com/Kotlin/kotlinx-datetime/releases
- https://github.com/Kotlin/kotlinx-datetime?tab=readme-ov-file#deprecation-of-instant
- https://github.com/Kotlin/kotlinx.serialization/releases
まとめ
以上でkotlinx-datetime
のアップデートはできるかと思います。
何か間違っているところやご意見などありましたらコメントいただけると助かります!
Discussion