将 java.util.Date
对象转换为新的 JDK 8/JSR-310 java.time.LocalDate
的最佳方法是什么?
Date input = new Date();
LocalDate date = ???
简答
Date input = new Date();
LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
说明
尽管有它的名字,java.util.Date
代表时间线上的一个瞬间,而不是“日期”。对象中存储的实际数据是自 1970-01-01T00:00Z(1970 GMT/UTC 开始时的午夜)以来的 long
毫秒计数。
JSR-310 中 java.util.Date
的等价类是 Instant
,因此有一个方便的方法 toInstant()
提供转换:
Date input = new Date();
Instant instant = input.toInstant();
java.util.Date
实例没有时区的概念。如果您在 java.util.Date
上调用 toString()
,这可能看起来很奇怪,因为 toString
是相对于时区的。然而,该方法实际上使用 Java 的默认时区来提供字符串。时区不是 java.util.Date
实际状态的一部分。
Instant
也不包含任何有关时区的信息。因此,要将 Instant
转换为本地日期,必须指定时区。这可能是默认区域 - ZoneId.systemDefault()
- 也可能是您的应用程序控制的时区,例如用户偏好设置的时区。使用 atZone()
方法应用时区:
Date input = new Date();
Instant instant = input.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
ZonedDateTime
包含由本地日期和时间、时区和与 GMT/UTC 的偏移量组成的状态。因此日期 - LocalDate
- 可以使用 toLocalDate()
轻松提取:
Date input = new Date();
Instant instant = input.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
LocalDate date = zdt.toLocalDate();
Java 9 答案
在 Java SE 9 中,new method已添加以稍微简化此任务:
Date input = new Date();
LocalDate date = LocalDate.ofInstant(input.toInstant(), ZoneId.systemDefault());
这种新的替代方案更直接,产生的垃圾更少,因此性能应该更好。
我是一名优秀的程序员,十分优秀!