在java.time.LocalDateTime和java.util.Date之间进行转换
在java.time.LocalDateTime和java.util.Date之间进行转换
本文翻译自:
Java 8 has a completely new API for date and time.
Java 8具有用于日期和时间的全新API。
One of the most useful classes in this API is
LocalDateTime
, for holding a timezone-independent date-with-time value.
此API中最有用的类之一是
LocalDateTime
,用于保存与时区无关的date-with-time值。
There are probably millions of lines of code using the legacy class
java.util.Date
for this purpose.
为此,可能使用遗留类
java.util.Date
数百万行代码。
As such, when interfacing old and new code there will be a need for converting between the two.
因此,当连接新旧代码时,将需要在两者之间进行转换。
As there seems to be no direct methods for accomplishing this, how can it be done?
由于似乎没有直接的方法可以完成此操作,因此该怎么办呢?
#1楼
参考:
#2楼
I’m not sure if this is the simplest or best way, or if there are any pitfalls, but it works: 我不确定这是最简单还是最好的方法,或者是否有任何陷阱,但是它可以工作:
static public LocalDateTime toLdt(Date date) {
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(date);
ZonedDateTime zdt = cal.toZonedDateTime();
return zdt.toLocalDateTime();
}
static public Date fromLdt(LocalDateTime ldt) {
ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
GregorianCalendar cal = GregorianCalendar.from(zdt);
return cal.getTime();
}
#3楼
Here is what I came up with ( and like all Date Time conundrums it is probably going to be disproved based on some weird timezone-leapyear-daylight adjustment :D ) 这是我想出的(和所有日期时间难题一样,它可能会根据一些奇怪的时区-ap年-日光调整:D来反证)
Round-tripping: Date
«-» LocalDateTime
往返: Date
«-» LocalDateTime
Given:
Date date = [some date]
给定:
Date date = [some date]
(1)
LocalDateTime
«
Instant
«
Date
(1)
LocalDateTime
«
Instant
«
Date
Instant instant = Instant.ofEpochMilli(date.getTime());
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
(2)
Date
«
Instant
«
LocalDateTime
(2)
Date
«
Instant
«
LocalDateTime
Instant instant = ldt.toInstant(ZoneOffset.UTC);
Date date = Date.from(instant);
Example: 例:
Given: 鉴于:
Date date = new Date();
System.out.println(date + " long: " + date.getTime());
(1) LocalDateTime
« Instant
« Date
: (1) LocalDateTime
« Instant
« Date
:
Create
Instant
from
Date
:
从
Date
创建
Instant
:
Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant from Date:\n" + instant);
Create
Date
from
Instant
(not necessary,but for illustration):
从
Instant
创建
Date
(不是必需的,但用于说明):
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
Create
LocalDateTime
from
Instant
从
Instant
创建
LocalDateTime
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime from Instant:\n" + ldt);
(2) Date
« Instant
« LocalDateTime
(2) Date
« Instant
« LocalDateTime
Create
Instant
from
LocalDateTime
:
从
LocalDateTime
创建
Instant
:
instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant from LocalDateTime:\n" + instant);
Create
Date
from
Instant
:
从
Instant
创建
Date
:
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
The output is: 输出为:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
Instant from Date:
2013-11-01T14:13:04.574Z
Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
LocalDateTime from Instant:
2013-11-01T14:13:04.574
Instant from LocalDateTime:
2013-11-01T14:13:04.574Z
Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
#4楼
Everything is here : 一切都在这里: :
The answer with “round-tripping” is not exact : when you do “往返”的答案并不确切:当您这样做时
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
if your system timezone is not UTC/GMT, you change the time ! 如果您的系统时区不是UTC / GMT,请更改时间!
#5楼
the following seems to work when converting from new API LocalDateTime into java.util.date: 从新的API LocalDateTime转换为java.util.date时,以下方法似乎起作用:
Date.from(ZonedDateTime.of({time as LocalDateTime}, ZoneId.systemDefault()).toInstant());
the reverse conversion can be (hopefully) achieved similar way… 反向转换可以(希望)以类似的方式实现…
hope it helps… 希望能帮助到你…
#6楼
Short answer: 简短答案:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
Explanation: (based on
about
LocalDate
)
说明:(基于有关
LocalDate
)
Despite its name,
java.util.Date
represents an instant on the time-line, not a “date”.
尽管其名称,
java.util.Date
表示时间轴上的一个瞬间,而不是“日期”。
The actual data stored within the object is a
long
count of milliseconds since 1970-01-01T00:00Z (midnight at the start of 1970 GMT/UTC).
自1970-01-01T00:00Z(1970 GMT / UTC开始的午夜)以来,存储在对象中的实际数据是很
long
的毫秒数。
The equivalent class to
java.util.Date
in JSR-310 is
Instant
, thus there are convenient methods to provide the conversion to and fro:
JSR-310中与
java.util.Date
等效的类是
Instant
,因此有方便的方法来回转换:
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
A
java.util.Date
instance has no concept of time-zone.
一个
java.util.Date
实例没有时区的概念。
This might seem strange if you call
toString()
on a
java.util.Date
, because the
toString
is relative to a time-zone.
如果在
java.util.Date
上调用
toString()
,这似乎很奇怪,因为
toString
是相对于时区的。
However that method actually uses Java’s default time-zone on the fly to provide the string.
但是,该方法实际上在运行时使用了Java的默认时区来提供字符串。
The time-zone is not part of the actual state of
java.util.Date
.
时区不是
java.util.Date
实际状态的一部分。
An
Instant
also does not contain any information about the time-zone.
Instant
也不包含有关时区的任何信息。
Thus, to convert from an
Instant
to a local date-time it is necessary to specify a time-zone.
因此,要将
Instant
时间转换为本地日期时间,必须指定一个时区。
*This might be the default zone -
ZoneId.systemDefault()
- or it might be a time-zone that your application controls, such as a time-zone from user preferences.*
这可能是默认区域
ZoneId.systemDefault()
-或可能是您的应用程序控制的时区,例如用户首选项中的时区。LocalDateTime
has a convenient factory method that takes both the instant and time-zone:LocalDateTime
有一个方便的工厂方法,该方法同时使用即时和时区:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
In reverse, the
LocalDateTime
the time-zone is specified by calling the
atZone(ZoneId)
method.
相反,可以通过调用
atZone(ZoneId)
方法来指定时区的
LocalDateTime
。
The
ZonedDateTime
can then be converted directly to an
Instant
:
然后可以将
ZonedDateTime
直接转换为
Instant
:
LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());
Note that the conversion from
LocalDateTime
to
ZonedDateTime
has the potential to introduce unexpected behaviour.
请注意,从
LocalDateTime
到
ZonedDateTime
的转换可能会引入意外的行为。
This is because not every local date-time exists due to Daylight Saving Time.
这是因为由于夏时制,并非每个本地日期时间都存在。
In autumn/fall, there is an overlap in the local time-line where the same local date-time occurs twice.
在秋季/秋季,本地时间线重叠,同一本地日期时间发生两次。
In spring, there is a gap, where an hour disappears.
在春天,有一个间隙,一个小时消失了。
See the Javadoc of
for more the definition of what the conversion will do.
有关转换功能的更多定义,请参见
的Javadoc。
Summary, if you round-trip a
java.util.Date
to a
LocalDateTime
and back to a
java.util.Date
you may end up with a different instant due to Daylight Saving Time.
总结,如果您将
java.util.Date
往返于
LocalDateTime
并返回到
java.util.Date
,则由于夏时制,最终结果可能会有所不同。
Additional info: There is another difference that will affect very old dates.
附加信息:还有另一个差异会影响非常旧的日期。
java.util.Date
uses a calendar that changes at October 15, 1582, with dates before that using the Julian calendar instead of the Gregorian one.
java.util.Date
使用一个日历,该日历在1582年10月15日更改,其日期之前使用儒略历而不是公历。
By contrast,
java.time.*
uses the ISO calendar system (equivalent to the Gregorian) for all time.
相比之下,
java.time.*
使用ISO日历系统(等同于公历)。
In most use cases, the ISO calendar system is what you want, but you may see odd effects when comparing dates before year 1582.
在大多数使用情况下,ISO日历系统是您所需要的,但是在比较1582年之前的日期时,您可能会看到奇怪的效果。