Skip to content
RuaRuan
返回

Kotlinx Datetime 使用指南

https://github.com/Kotlin/kotlinx-datetime 根据 README 整理一份 kotlinx-datetime 的使用指南

以下是基于官方 README 整理的 kotlinx-datetime 使用指南。该库为 Kotlin 多平台提供了没有遗留负担的日期时间 API,完全基于 ISO 8601 并独立于平台(无 java.time 依赖)。


1. 简介

kotlinx-datetime 是 Kotlin 官方开发的跨平台日期时间库,支持 JVM、Android、Native、JS 等平台。它提供了一套清晰、不可变的数据类型,用于表示和处理日期、时间、时刻及时区。

2. 添加依赖

build.gradle.kts 中添加:

kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
        }
    }
}

(版本号请以 Maven Central 最新版为准)

3. 核心类型概览

类型描述示例值
Instant世界时间线上的一个点(UTC+0 时刻)2024-01-15T10:30:00Z
LocalDate不带时区的日期(年-月-日)2024-01-15
LocalTime不带日期的时间(时-分-秒-纳秒)10:30:00
LocalDateTime不带时区的日期+时间2024-01-15T10:30:00
TimeZone时区(如 Europe/Paris 或固定偏移)TimeZone.of("Asia/Tokyo")
DateTimePeriod日期与时间的组合跨度(年/月/日/时/分/秒/纳秒)DateTimePeriod(years=1, months=2, days=3, hours=4, minutes=5, seconds=6, nanoseconds=7)
DatePeriod仅日期部分(年/月/日)的跨度DatePeriod(years=1, months=2, days=3)

4. 创建实例

4.1 获取当前时刻

val now: Instant = Clock.System.now()

4.2 从字符串解析(ISO 8601 格式)

val instant = Instant.parse("2024-03-21T12:00:00Z")
val localDate = LocalDate.parse("2024-03-21")
val localTime = LocalTime.parse("14:30:15.5")
val localDateTime = LocalDateTime.parse("2024-03-21T14:30:00")

4.3 直接构造

val date = LocalDate(2024, 3, 21)                // 年,月,日
val time = LocalTime(14, 30, 15, 500_000_000)    // 时,分,秒,纳秒
val dateTime = LocalDateTime(date, time)

4.4 从 Instant 转换为本地日期时间(需指定时区)

val instant = Clock.System.now()
val timeZone = TimeZone.currentSystemDefault()
val localDateTime = instant.toLocalDateTime(timeZone)

5. 日期时间计算与区间

5.1 加减时间段

val date = LocalDate(2024, 3, 21)

// 使用 DatePeriod 仅改变日期部分
val nextMonth = date + DatePeriod(months = 1)   // 2024-04-21

// 使用 DateTimePeriod 同时改变日期和时间
val dateTime = LocalDateTime(2024, 3, 21, 10, 0)
val later = dateTime + DateTimePeriod(hours = 3, days = 1) // 2024-03-22T13:00

5.2 两个日期之间的差

val start = LocalDate(2024, 1, 1)
val end = LocalDate(2024, 3, 1)
val period: DatePeriod = end - start   // 得到 DatePeriod(months=2)

Instant 相减得到 Duration(仅时间跨度):

val duration: Duration = instant2 - instant1

5.3 区间与迭代

val from = LocalDate(2024, 1, 1)
val to = LocalDate(2024, 1, 5)

if (date in from..to) { /* 在区间内 */ }

// 按天迭代(需使用 plus 和条件)
var current = from
while (current <= to) {
    println(current)
    current = current.plus(DatePeriod(days = 1))
}

6. 格式化与解析

库内置了 ISO 8601 的默认格式。如需自定义格式,可配合 kotlinx-datetime 的扩展或使用字符串操作。官方推荐使用 toString()parse() 处理标准格式。

若需复杂格式(如 dd.MM.yyyy),可以转换后使用平台相关的工具(如 JVM 上的 DateTimeFormatter 但会破坏跨平台性)。跨平台格式化建议自行编写扩展函数或使用第三方库(如 kotlinx-datetime-format 实验性模块)。

示例:将 LocalDate 转为自定义字符串

fun LocalDate.formatToDMY(): String = "${dayOfMonth}.${monthNumber}.${year}"

7. 时区处理

7.1 获取时区

val defaultTz = TimeZone.currentSystemDefault()
val tokyoTz = TimeZone.of("Asia/Tokyo")
val utcTz = TimeZone.UTC

7.2 时区转换

val instant = Clock.System.now()
val parisTime = instant.toLocalDateTime(TimeZone.of("Europe/Paris"))
val tokyoTime = instant.toLocalDateTime(TimeZone.of("Asia/Tokyo"))

7.3 本地日期时间转为 Instant

val local = LocalDateTime(2024, 3, 21, 10, 0)
val instantInTokyo = local.toInstant(TimeZone.of("Asia/Tokyo")) // 东京时间10:00对应的UTC时刻

8. 常用操作速查表

目的代码示例
获取当前 UTC 时刻Clock.System.now()
当前系统时区的日期Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date
提取日期部分instant.toLocalDateTime(tz).date
提取时间部分localDateTime.time
修改某字段localDate.copy(month = 12)
比较两个时刻instant1 < instant2
计算两个日期的月份差(endDate - startDate).months
检查闰年localDate.year.isLeap

9. 与 java.time 的互操作(仅限 JVM)

虽然 kotlinx-datetime 不依赖 java.time,但在 JVM 上你可以轻松转换:

// kotlinx-datetime → java.time
val localDateKt: LocalDate = ...
val javaLocalDate = java.time.LocalDate.of(localDateKt.year, localDateKt.monthNumber, localDateKt.dayOfMonth)

// java.time → kotlinx-datetime
val javaInstant = java.time.Instant.now()
val kotlinInstant = Instant.fromEpochSeconds(javaInstant.epochSecond, javaInstant.nano)

注意:跨平台代码中应避免此类转换。

10. 最佳实践


以上内容覆盖了 kotlinx-datetime 的核心用法。更多细节请查阅官方仓库API 文档



上一篇
Kotlin Multiplatform (KMP) 中,如何实现跨平台权限请求?
下一篇
使用 Astro 和 AstroPaper 主题搭建博客