首页 > 解决方案 > 在 java.time API 和 java.util.Date 之间转换

问题描述

从 Android Studio 4 开始,出色的java.timeAPI 可用于 Android。

在我的项目中,我想逐渐迁移java.util.Date到新的 API。

如何在两种格式之间进行转换?

标签: androidjava.util.datejava-timeandroid-studio-4.0

解决方案


首先,我想指出严重的差异。

java.time

java.time API 在明确不同的时间概念方面做得很好,例如,如果您想表示某个时间点或Duration. 在第一种情况下,您可以选择是否要表示日期、时间或两者兼而有之,以及是否希望它能够感知时区,例如

  • LocalDate(日期,无时间,无时区)
  • LocalDateTime(日期、时间、无时区)
  • ZonedDateTime(日期、时间、时区)

AnInstant表示时间戳(自 UTC 时间 01.01.1970 以来的纳秒)。所以它是时间的机器表示,也是其他类的构建块。

要查看所有类,请参阅java.time API 文档

java.util.日期

建议它的方法Date表示日期和时间。在内部,它仅存储时间戳(自 01.01.1970 UTC 以来的毫秒数)并且没有时区。

创建它的推荐方法是使用时区感知Calendar类。但是,它Date本身是通过隐式使用计算机运行的时区生成的。调用toString()格式化输出可能会显示时区,但它是从Calendar实例外部获取的,这会导致混淆Date,会存储时区。

总而言之,API 设计不佳,可能会造成混淆。java.time远远优于,如果有的话应该使用。

旧代码适配器

那么这两个 API 是如何连接的呢?-> 通过Instant.

在 java 8java.util.Date中扩展了两种方法:

  • public static Date from(Instant instant)
  • public Instant toInstant()

这是两个 API 之间的内置桥梁!

我们可以在此基础上构建更多的适配器功能。这是一个示例(在 Kotlin 中),其中包含类LocalDate和的转换LocalDateTime

/**
 * java.util.Date has no explicit time zone but implicitly uses the system's time zone
 */
private val dateZoneId: ZoneId = ZoneId.systemDefault()

fun Date.toLocalDate(): LocalDate = toInstant().atZone(dateZoneId).toLocalDate()

fun LocalDate.toDate(): Date = Date.from(atStartOfDay(dateZoneId).toInstant())

fun Date.toLocalDateTime(): LocalDateTime = toInstant().atZone(dateZoneId).toLocalDateTime()

fun LocalDateTime.toDate(): Date = Date.from(atZone(dateZoneId).toInstant())

推荐阅读