简短答案:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
说明:
(基于this question关于LocalDate)
尽管其名称,java.util.Date表示时间线上的即时,而不是“日期”。存储在对象内的实际数据是自1970-01-01T00:00Z(1970 GMT / UTC开始时的午夜)以来的长毫秒计数。
JSR-310中与java.util.Date等价的类是Instant,因此有很方便的方法来提供转换:
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
java.util.Date实例没有时区的概念。这可能看起来很奇怪,如果你调用toString()在java.util.Date,因为toString是相对于时区。然而,该方法实际上使用Java的默认时区即时提供字符串。时区不是java.util.Date的实际状态的一部分。
即时也不包含有关时区的任何信息。因此,为了从Instant转换为本地日期时间,需要指定时区。这可能是默认区域 – ZoneId.systemDefault() – 也可能是您的应用程序控制的时区,例如来自用户首选项的时区。 LocalDateTime有一个方便的工厂方法,同时接受即时和时区:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
相反,LocalDateTime的时区通过调用atZone(ZoneId)方法来指定。然后,ZonedDateTime可以直接转换为Instant:
LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());
请注意,从LocalDateTime到ZonedDateTime的转换有可能引入意想不到的行为。这是因为不是每个本地日期时间由于夏令时存在。在秋天/秋天,在本地时间线上存在重叠,其中相同的本地日期时间发生两次。在Spring,有一个差距,一小时消失。有关更多转换将做什么的定义,请参阅atZone(ZoneId)的Javadoc。
摘要,如果你将一个java.util.Date往返一个LocalDateTime并返回一个java.util.Date,你可能会因为夏令时而导致不同的时间。
附加信息:有另一个区别,将影响很老的日期。 java.util.Date使用一个日历,1582年10月15日,日期之前使用朱利安日历,而不是格里高利。相比之下,java.time。*始终使用ISO日历系统(等同于Gregorian)。在大多数使用情况下,ISO日历系统是你想要的,但是当比较1582年之前的日期时,可能会看到奇怪的效果。