Convert Date to LocalDate or LocalDateTime and Back – 将日期转换为LocalDate或LocalDateTime并返回

最后修改: 2017年 11月 28日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Starting with Java 8, we have a new Date API: java.time.

从Java 8开始,我们有了一个新的Date API。java.time

However, sometimes we still need to perform conversions between the new and old APIs, and work with date representations from both.

然而,有时我们仍然需要在新旧API之间进行转换,并使用两者的日期表示。

2. Converting java.util.Date to java.time.LocalDate

2.将java.util.Date转换为java.time.LocalDate

Let’s start with converting the old date representation to the new one.

让我们先把旧的日期表示法转换为新的表示法。

Here, we can take advantage of a new toInstant() method, which was added to java.util.Date in Java 8.

在这里,我们可以利用一个新的toInstant()方法,这个方法在Java 8中被添加到java.util.Date

When we’re converting an Instant object, it’s required to use a ZoneId because Instant objects are time-zone agnostic — just points on the timeline.

当我们转换一个Instant对象时,需要使用一个ZoneId,因为Instant对象是与时区无关的 – 只是时间线上的点。

The atZone(ZoneId zone) API from Instant object returns a ZonedDateTime, so we just need to extract LocalDate from it using the toLocalDate() method.

来自Instant对象的atZone(ZoneId zone) API返回一个ZonedDateTime,所以我们只需要使用toLocalDate()方法从中提取LocalDate

First, we’re using the default system ZoneId:

首先,我们使用默认的系统ZoneId

public LocalDate convertToLocalDateViaInstant(Date dateToConvert) {
    return dateToConvert.toInstant()
      .atZone(ZoneId.systemDefault())
      .toLocalDate();
}

And a similar solution but with a different way of creating an Instant object — using the ofEpochMilli() method:

还有一个类似的解决方案,但用不同的方式来创建Instant对象–使用ofEpochMilli()方法。

public LocalDate convertToLocalDateViaMilisecond(Date dateToConvert) {
    return Instant.ofEpochMilli(dateToConvert.getTime())
      .atZone(ZoneId.systemDefault())
      .toLocalDate();
}

Before we move on, let’s also have a quick look at the old java.sql.Date class and how that can be converted to a LocalDate as well.

在我们继续之前,让我们也快速看看java.sql.Date类,以及如何将其也转换为LocalDate

Starting with Java 8, we can find an additional toLocalDate() method on java.sql.Date, which also gives us an easy way of converting it to java.time.LocalDate.

从Java 8开始,我们可以在java.sql.Date上找到一个额外的toLocalDate()方法,这也给了我们一个将其转换为java.time.LocalDate的简便方法。

In this case, we don’t need to worry about the time zone:

在这种情况下,我们不需要担心时区的问题。

public LocalDate convertToLocalDateViaSqlDate(Date dateToConvert) {
    return new java.sql.Date(dateToConvert.getTime()).toLocalDate();
}

Very similarly, we can convert an old Date object into a LocalDateTime object as well. Let’s have a look at that next.

非常类似地,我们也可以将一个旧的Date对象转换成LocalDateTime对象。让我们接下来看看这个。

3. Converting java.util.Date to java.time.LocalDateTime

3.将java.util.Date转换为java.time.LocalDateTime

To get a LocalDateTime instance, we can similarly use an intermediary ZonedDateTime and then use the toLocalDateTime() API.

为了获得一个LocalDateTime实例,我们同样可以使用一个中介ZonedDateTime,然后使用toLocalDateTime() API。

Just like before, we can use two possible solutions to get an Instant object from java.util.Date:

就像以前一样,我们可以使用两种可能的解决方案来从java.util.Date中获取Instant对象。

public LocalDateTime convertToLocalDateTimeViaInstant(Date dateToConvert) {
    return dateToConvert.toInstant()
      .atZone(ZoneId.systemDefault())
      .toLocalDateTime();
}

public LocalDateTime convertToLocalDateTimeViaMilisecond(Date dateToConvert) {
    return Instant.ofEpochMilli(dateToConvert.getTime())
      .atZone(ZoneId.systemDefault())
      .toLocalDateTime();
}

Note that for dates before Oct 10, 1582, it’s necessary to set up Calendar as a Gregorian calendar and call method setGregorianChange():

注意,对于1582年10月10日之前的日期,有必要将Calendar设置为公历,并调用方法setGregorianChange():

GregorianCalendar calendar = new GregorianCalendar();
calendar.setGregorianChange(new Date(Long.MIN_VALUE));
Date dateToConvert = calendar.getTime();

And starting with Java 8, we can also use java.sql.Timestamp to obtain a LocalDateTime:

而从Java 8开始,我们也可以使用 java.sql.Timestamp来获取LocalDateTime

ocalDateTime convertToLocalDateTimeViaSqlTimestamp(Date dateToConvert) {
    return new java.sql.Timestamp(
      dateToConvert.getTime()).toLocalDateTime();
}

4. Convert java.time.LocalDate to java.util.Date

4.将java.time.LocalDate转换成java.util.Date

Now that we have a good understanding of how to convert from the old data representation to the new one, let’s have a look at converting in the other direction.

现在我们已经很好地理解了如何从旧的数据表示法转换到新的数据表示法,让我们看看在另一个方向的转换。

We’ll discuss two possible ways of converting LocalDate to Date.

我们将讨论将LocalDate转换为Date的两种可能方式。

In the first, we use a new valueOf(LocalDate date) method provided in java.sql.Date object, which takes LocalDate as a parameter:

在第一种情况下,我们使用valueOf(LocalDate date)方法,该方法在java.sql.Date对象中提供,它将LocalDate作为一个参数。

public Date convertToDateViaSqlDate(LocalDate dateToConvert) {
    return java.sql.Date.valueOf(dateToConvert);
}

As we can see, it is effortless and intuitive. It uses local time zone for conversion (all is done under the hood, so no need to worry).

正如我们所看到的,它毫不费力,而且很直观。它使用当地的时区进行转换(所有的工作都在引擎盖下完成,所以不必担心)。

In another Java 8 example, we use an Instant object that we pass to the from(Instant instant) method of java.util.Date object:

在另一个Java 8的例子中,我们使用一个Instant对象,并将其传递给from(Instant instant) java.util.Date对象的方法。

public Date convertToDateViaInstant(LocalDate dateToConvert) {
    return java.util.Date.from(dateToConvert.atStartOfDay()
      .atZone(ZoneId.systemDefault())
      .toInstant());
}

Notice we make use of an Instant object here and that we also need to care about time zones when doing this conversion.

请注意,我们在这里使用了一个Instant对象,而且在进行这种转换时,我们还需要关注时区。

Next, let’s use a very similar solution to convert a LocalDateTime to a Date object.

接下来,让我们使用一个非常类似的解决方案,将LocalDateTime转换为Date对象。

5. Convert java.time.LocalDateTime to java.util.Date

5.将java.time.LocalDateTime转换为java.util.Date

The easiest way of getting a java.util.Date from LocalDateTime is to use an extension to the java.sql.Timestamp — available with Java 8:

LocalDateTime获得java.util.Date的最简单方法是使用 java.sql.Timestamp的扩展–在Java 8中可用。

public Date convertToDateViaSqlTimestamp(LocalDateTime dateToConvert) {
    return java.sql.Timestamp.valueOf(dateToConvert);
}

But of course, an alternative solution is using an Instant object, which we obtain from ZonedDateTime:

但当然,另一个解决方案是使用一个Instant对象,我们从ZonedDateTime获得。

Date convertToDateViaInstant(LocalDateTime dateToConvert) {
    return java.util.Date
      .from(dateToConvert.atZone(ZoneId.systemDefault())
      .toInstant());
}

6. Java 9 Additions

6.Java 9的补充

In Java 9, there are new methods available that simplify conversion between java.util.Date and java.time.LocalDate or java.time.LocalDateTime.

在Java 9中,有一些新的方法可以简化java.util.Datejava.time.LocalDatejava.time.LocalDateTime之间的转换。

LocalDate.ofInstant(Instant instant, ZoneId zone) and LocalDateTime.ofInstant(Instant instant, ZoneId zone) provide handy shortcuts:

LocalDate.ofInstant(Instant instant, ZoneId zone)LocalDateTime.ofInstant(Instant instant, ZoneId zone)提供方便的快捷方式。

public LocalDate convertToLocalDate(Date dateToConvert) {
    return LocalDate.ofInstant(
      dateToConvert.toInstant(), ZoneId.systemDefault());
}

public LocalDateTime convertToLocalDateTime(Date dateToConvert) {
    return LocalDateTime.ofInstant(
      dateToConvert.toInstant(), ZoneId.systemDefault());
}

7. Conclusion

7.结论

In this article, we covered possible ways of converting old java.util.Date into new java.time.LocalDate and java.time.LocalDateTime, as well as the other way around.

在这篇文章中,我们介绍了将旧的java.util.Date转换为新的java.time.LocalDatejava.time.LocalDateTime的可能方式,以及其他方式。

The full implementation of this article is available over on GitHub.

本文的完整实现可在GitHub上获得