我查看了 Joda-Time 源,该fromDateFields
方法使用getXXX
from 的方法java.util.Date
来获取日期/时间字段的值。类似的东西(我使用的是 Joda-Time 2.9.9):
return new LocalDateTime(
date.getYear() + 1900,
date.getMonth() + 1,
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
(((int) (date.getTime() % 1000)) + 1000) % 1000
);
如果您查看javadoc,您会看到所有这些方法都返回以本地时区解释的对应值。这意味着使用 JVM 默认时区是隐含的。
实际上,查看Date
源代码,所有的 getter 调用normalize()
,这是一个使用默认时区转换字段的方法。
你说我个人不喜欢区域部分,但在 Joda-Time 中,它隐式/间接地使用默认时区。
使用区域是有意义的,因为 ajava.util.Date
代表时间线中的一个点(特定时刻),没有任何时区信息。同一时刻可以对应世界不同地区的不同日期和时间,因此您需要一个时区来进行此转换。
Joda-Time 使用Date::getXXX
隐含使用默认时区的方法。但是在 中java.time
,事情必须更加明确,所以你必须使用一个ZoneId
对象。
顺便说一句,您的解决方案 ( LocalDateTime.from(date.toInstant())
) 对我不起作用。在 Java 8 中,它给出了一个错误:
java.time.DateTimeException:无法从 TemporalAccessor 获取 LocalDateTime:java.time.Instant 类型的 2018-02-01T10:50:16.882Z
因此,您需要将 to 转换Date
为Instant
,然后告诉您想要的时区,然后获取本地部分,就像您已经在做的那样:
LocalDateTime dt = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
或者:
// the result is the same
LocalDateTime dt = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
虽然java.time
强迫你使用时区,但我相信这是一件好事,因为它让你思考它,而不是在幕后做一些“魔术”。
如果需要,您甚至可以将其更改为其他时区(例如ZoneId.of("America/New_York")
)。即使您最终使用 JVM 的默认值,这也是一个明智的选择 - 理想情况下,因为有些人只是使用默认值而不考虑它。