在 java.time.LocalDateTime 和 java.util.Date 之间转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19431234/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 17:05:25  来源:igfitidea点击:

Converting between java.time.LocalDateTime and java.util.Date

javadatetimejava-8java-time

提问by Knut Arne Vedaa

Java 8 has a completely new API for date and time. One of the most useful classes in this API is LocalDateTime, for holding a timezone-independent date-with-time value.

Java 8 有一个全新的日期和时间 API。此 API 中最有用的类之一是LocalDateTime,用于保存与时区无关的日期时间值。

There are probably millions of lines of code using the legacy class java.util.Datefor this purpose. 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?

java.util.Date为此目的,可能有数百万行代码使用遗留类。因此,当连接新旧代码时,需要在两者之间进行转换。由于似乎没有直接的方法来实现这一点,如何做到这一点?

采纳答案by JodaStephen

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 this questionabout LocalDate)

解释:(基于这个关于 的问题LocalDate

Despite its name, java.util.Daterepresents an instant on the time-line, not a "date". The actual data stored within the object is a longcount of milliseconds since 1970-01-01T00:00Z (midnight at the start of 1970 GMT/UTC).

尽管它的名字,java.util.Date代表时间线上的一个瞬间,而不是“日期”。对象中存储的实际数据是long自 1970-01-01T00:00Z(格林威治标准时间/世界协调时间 1970 开始时的午夜)以来的毫秒计数。

The equivalent class to java.util.Datein JSR-310 is Instant, thus there are convenient methods to provide the conversion to and fro:

java.util.DateJSR-310 中的等价类是Instant,因此有方便的方法来提供来回转换:

Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);

A java.util.Dateinstance has no concept of time-zone. This might seem strange if you call toString()on a java.util.Date, because the toStringis relative to a time-zone. However that method actually uses Java's default time-zone on the fly to provide the string. The time-zone is not part of the actual state of java.util.Date.

一个java.util.Date实例没有时区的概念。如果您调用toString()a java.util.Date,这可能看起来很奇怪,因为atoString是相对于时区的。然而,该方法实际上使用 Java 的默认时区即时提供字符串。时区不是 的实际状态的一部分java.util.Date

An Instantalso does not contain any information about the time-zone. Thus, to convert from an Instantto a local date-time it is necessary to specify a time-zone. 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. LocalDateTimehas a convenient factory method that takes both the instant and time-zone:

AnInstant也不包含有关时区的任何信息。因此,要从Instant本地日期时间转换为本地日期时间,必须指定时区。这可能是默认区域——ZoneId.systemDefault()或者它可能是您的应用程序控制的时区,例如来自用户首选项的时区。LocalDateTime有一个方便的工厂方法,可以同时使用即时和时区:

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());

In reverse, the LocalDateTimethe time-zone is specified by calling the atZone(ZoneId)method. The ZonedDateTimecan then be converted directly to an Instant:

反过来,LocalDateTime时区是通过调用atZone(ZoneId)方法指定的。所述ZonedDateTime然后可以直接转化为Instant

LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());

Note that the conversion from LocalDateTimeto ZonedDateTimehas the potential to introduce unexpected behaviour. 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 atZone(ZoneId)for more the definition of what the conversion will do.

请注意,从LocalDateTimeto的转换ZonedDateTime可能会引入意外行为。这是因为由于夏令时,并非每个本地日期时间都存在。在秋季/秋季,本地时间线重叠,同一本地日期时间出现两次。在春天,有一个缺口,一个小时消失了。有关atZone(ZoneId)转换将执行的操作的更多定义,请参阅的 Javadoc 。

Summary, if you round-trip a java.util.Dateto a LocalDateTimeand back to a java.util.Dateyou may end up with a different instant due to Daylight Saving Time.

总结,如果您从 ajava.util.Date到 aLocalDateTime再返回到 a java.util.Date,由于夏令时,您可能会得到不同的时刻。

Additional info: There is another difference that will affect very old dates. java.util.Dateuses a calendar that changes at October 15, 1582, with dates before that using the Julian calendar instead of the Gregorian one. By contrast, java.time.*uses the ISO calendar system (equivalent to the Gregorian) for all time. In most use cases, the ISO calendar system is what you want, but you may see odd effects when comparing dates before year 1582.

附加信息:还有另一个差异会影响非常旧的日期。java.util.Date使用在 1582 年 10 月 15 日更改的日历,在此之前的日期使用儒略历而不是公历。相比之下,一直java.time.*使用 ISO 日历系统(相当于公历)。在大多数用例中,ISO 日历系统正是您想要的,但在比较 1582 年之前的日期时,您可能会看到奇怪的效果。

回答by Knut Arne Vedaa

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();
}

回答by The Coordinator

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 )

这是我想出的(和所有日期时间难题一样,它可能会根据一些奇怪的时区-闰年-日光调整而被否定: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 Instantfrom Date:

创建InstantDate

Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant from Date:\n" + instant);

Create Datefrom Instant(not necessary,but for illustration):

创建DateInstant(不是必需的,但为了说明):

date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());

Create LocalDateTimefrom Instant

创建LocalDateTimeInstant

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime from Instant:\n" + ldt);

(2) Date<< Instant<< LocalDateTime

(2)Date<< Instant<<LocalDateTime

Create Instantfrom LocalDateTime:

创建InstantLocalDateTime

instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant from LocalDateTime:\n" + instant);

Create Datefrom Instant:

创建DateInstant

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

回答by joe-mojo

Everything is here : http://blog.progs.be/542/date-to-java-time

一切都在这里:http: //blog.progs.be/542/date-to-java-time

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,请更改时间!

回答by dizzy

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...

希望能帮助到你...

回答by Petrychenko

Much more convenient way if you are sure you need a default timezone :

如果您确定需要默认时区,则使用更方便的方法:

Date d = java.sql.Timestamp.valueOf( myLocalDateTime );

回答by humazed

If you are on android and using threetenbpyou can use DateTimeUtilsinstead.

如果您使用的是 android 并使用Threetenbp,则可以DateTimeUtils改用。

ex:

前任:

Date date = DateTimeUtils.toDate(localDateTime.atZone(ZoneId.systemDefault()).toInstant());

you can't use Date.fromsince it's only supported on api 26+

您无法使用,Date.from因为它仅在 api 26+ 上受支持

回答by Lukasz Czerwinski

The fastest way for LocalDateTime-> Dateis:

LocalDateTime->的最快方法Date是:

Date.from(ldt.toInstant(ZoneOffset.UTC))

Date.from(ldt.toInstant(ZoneOffset.UTC))