Joda- java.time迁移时间'fromDateFields()'

时间:2018-01-31 17:25:14

标签: java jodatime java-time localdate java.time.instant

我们目前正在从Joda-Time迁移到java.time。我对fromDateFields()方法有以下疑问。老joda代码:

Date date = new Date(); //some java Date
LocalDateTime lt = LocalDateTime.fromDateFields(date);

一位同事将其迁移到以下行(java.time代码):

lt = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();

这是对的吗? Joda-Time docs像这样描述方法fromeDateFields

  

使用完全相同的方法从java.util.Date构造一个LocalDateTime   相同的字段值。

     

从日期查询每个字段并将其分配给LocalDateTime。   如果您一直使用日期作为本地日期,这非常有用,   忽略区域

达到相同结果的正确方法是什么?

更新(刚刚找到以下解决方案):

lt= LocalDateTime.from(date.toInstant());

1 个答案:

答案 0 :(得分:3)

我查看了Joda-Time来源,fromDateFields方法使用getXXX中的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 source code,所有获取者都会调用normalize(),这是一种使用默认时区转换字段的方法。

你说就我个人而言,我不喜欢区域部分,但在Joda-Time中,它隐含/间接使用默认时区。

使用区域是有意义的,因为java.util.Date represents a point in the timeline (a specific instant)没有任何时区信息。同一时刻可以对应世界不同地区的不同日期和时间,因此您需要一个时区来进行此转换。

Joda-Time使用Date::getXXX方法,其中隐含使用默认时区。但在java.time中,事情必须更明确,因此您必须使用ZoneId对象。

顺便说一下,你的解决方案(LocalDateTime.from(date.toInstant()))对我没用。在Java 8中,它给出了一个错误:

  

java.time.DateTimeException:无法从TemporalAccessor获取LocalDateTime:2018-02-01T10:50:16.882Z类型为java.time.Instant

因此,您需要将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的默认设置,它也是一个有道理的选择 - 理想情况下,因为有些人只是使用默认值而不考虑它。