目录

在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. 请注意,从 LocalDateTimeZonedDateTime 的转换可能会引入意外的行为。 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年之前的日期时,您可能会看到奇怪的效果。