简短回答
Date input = new Date();
LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
解释
尽管它的名字,java.util.Date
代表时间线上的一个时刻,而不是“日期”。对象中存储的实际数据是long
自 1970-01-01T00:00Z(1970 GMT/UTC 开始时的午夜)以来的毫秒数。
相当于类java.util.Date
在 JSR-310 中是Instant
,因此有一个方便的方法toInstant()
提供转换:
Date input = new Date();
Instant instant = input.toInstant();
A java.util.Date
实例没有时区的概念。如果你打电话,这可能看起来很奇怪toString()
on a java.util.Date
,因为toString
是相对于时区的。然而,该方法实际上动态使用 Java 的默认时区来提供字符串。时区不属于实际状态的一部分java.util.Date
.
An Instant
也不包含任何有关时区的信息。因此,要从Instant
对于本地日期,需要指定时区。这可能是默认区域 -ZoneId.systemDefault()
- 或者它可能是您的应用程序控制的时区,例如用户首选项中的时区。使用atZone()
应用时区的方法:
Date input = new Date();
Instant instant = input.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
A 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 中,新方法 https://docs.oracle.com/javase/9/docs/api/java/time/LocalDate.html#ofInstant-java.time.Instant-java.time.ZoneId-已添加,稍微简化了此任务:
Date input = new Date();
LocalDate date = LocalDate.ofInstant(input.toInstant(), ZoneId.systemDefault());
这种新的替代方案更直接,产生的垃圾更少,因此应该表现更好。