将java.time.LocalDate转换为java.util.Date类型

457

1
你读过 https://dev59.com/7WEi5IYBdhLWcg3wfsMj 吗? - Daksh Shah
2
LGoodDatePicker原生使用java.time包(又称Java 8时间或JSR-310)。具体来说,LGoodDatePicker使用“java.time.LocalDate”来存储日期值。屏幕截图和演示可在项目主页中查看。 - BlakeTNC
更多答案可以在以下链接找到:LocalDate转换为java.util.Date以及最简单的相反转换? - Basil Bourque
13个回答

670
Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());

这假定你的日期选择器使用系统默认时区将日期转换为字符串。


6
有没有可能避免使用 atStartOfDay() 函数,因为据我了解它会改变日期的值。 - yegor256
2
@yegor256,你的评论对我来说没什么意义。为什么不提出自己的问题,而是在很旧的问题上发表评论呢? - JB Nizet
5
@JBNizet您的回答对我来说不是很有意义,这就是为什么我决定澄清的原因。为什么您不澄清一下,而是发表无用的评论呢? - yegor256
15
因为我不明白为什么需要澄清它的方式和原因。这个答案有232个赞,因此人们认为它很清晰明了。你说atStartOfDay改变了日期的值,这是没有意义的。atStartOfDay做的就是它在javadoc中所描述的:将一个LocalDate转换为一个LocalDateTime,仍然是同一天,在这一天的开始时间。 - JB Nizet
3
你确定你的结果是错误的吗?如果你在德国,那么可能与1893年4月德国时间出现了6分32秒的故障有关。请参阅https://www.timeanddate.com/time/zone/germany/berlin?syear=1850 获取一些详细信息。 - Dawood ibn Kareem
显示剩余2条评论

136

这是一种我用来将较新的 java.time 类转换为 java.util.Date 对象以及反过来的实用工具类:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

public class DateUtils {

  public static Date asDate(LocalDate localDate) {
    return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
  }

  public static Date asDate(LocalDateTime localDateTime) {
    return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
  }

  public static LocalDate asLocalDate(Date date) {
    return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
  }

  public static LocalDateTime asLocalDateTime(Date date) {
    return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
  }
}

根据@Oliv的评论进行了编辑。


1
使用ZoneId.systemDefault()不是有问题吗?因为时区在一年中会发生变化。例如,如果在1月1日我处于时区-05:00(中央时区),但是在7月1日我处于时区-06:00(中央夏令时),那么由于夏令时的原因,这样做不会导致不准确的结果吗? - jhilden

109

免责声明: 仅用于说明现有的Java API。不应在生产代码中使用。

您可以使用java.sql.Date.valueOf()方法,如下所示:

Date date = java.sql.Date.valueOf(localDate);

无需在此处添加时间和时区信息,因为它们被隐式地采取。
请参见LocalDate to java.util.Date and vice versa simplest conversion?


12
java.sql.Date 是用于数据库层、JDBC 和 JPA 的。Web 层(或任何客户端应用程序)应完全不依赖于 java.sql.* - Tiny
2
@Tiny java.sql.Date 存在于 rt.jar 中。 没有任何外部依赖。您只需使用语言特性即可。 - George
2
java.sql.Date 就是 java.util.Date,只不过时间被设置为 00:00:00。但从设计角度来看,java.sql.* 不适用于客户端交互的前端层,例如 Servlets / JSP。在 Java 端使用 java.util.Date,在 JDBC 端使用 java.sql.Timestamp 或其他适用的类。 - Tiny
5
根据java.time.*的作者所说,这是一个“可怕的hack”:https://dev59.com/31wY5IYBdhLWcg3wD0LG#trGiEYcBWogLw_1bAdXX。在Java 9中,java.sql.*类将成为一个单独的依赖项。 - Dherik
7
如果这是可怕的黑客攻击,为什么Java不在java.util中包含这个简单的东西呢?Java变得比以前更加疯狂。 - Aadam
显示剩余3条评论

19

java.time库中有Temporal接口,你可以使用它从大多数时间类中创建Instant对象。Instant表示Epoch时间轴上的毫秒数,这是其他所有日期和时间的基准参考。

我们需要将Date转换为一个带有时间和时区信息的ZonedDateTime对象以进行转换:

LocalDate ldate = ...;
Instant instant = Instant.from(ldate.atStartOfDay(ZoneId.of("GMT")));
Date date = Date.from(instant);

14

为了从java.time.LocalDate创建一个java.util.Date,你需要:

  • LocalDate添加时间
  • 在时区内解释日期和时间
  • 获取自epoch以来的秒数/毫秒数
  • 创建一个java.util.Date

代码可能如下所示:

LocalDate localDate = LocalDate.now();
Date date = new Date(localDate.atStartOfDay(ZoneId.of("America/New_York")).toEpochSecond() * 1000);

1
区域 ID(ZoneIf)中有错别字。 - assylias
localDate.atStartOfDay() 会创建一个 ZonedDateTime,但是 ZonedDateTime 没有 toEpochSecond() 方法。 - Kevin Sadler
@KevinSadler:方法toEpochSecond是从java.time.chrono.ChronoZonedDateTime继承而来的。请参阅http://docs.oracle.com/javase/8/docs/api/java/time/chrono/ChronoZonedDateTime.html#toEpochSecond-- - nosid
@nosid 谢谢您的纠正。当我在Eclipse中使用代码自动完成时,它(和toInstance)并不是一个选项。但如果我完整地输入它,似乎可以被接受。我错误地得出结论认为它不是一个方法,因为这个事实以及我在ZonedDateTime的Javadoc上没有看到它,正如您所说,它被列为继承的方法。抱歉,请接受我的赞扬 :) - Kevin Sadler

14

8
这相当低效。 - AndresQ
2
转换为Instant可能会冗长,但构建和解析String就像通过东京从纽约到墨西哥城一样... - ehecatl
2
@ehecatl 注意了...将来纽约->东京->墨西哥城可能在几个小时内完成 ;) - Stephan
1
当我在转换时不再拥有时区信息时,这对我的用例更有效。例如,使用Freemaker打印日期。 - Weishi Z
这是错误的解决方案,因为SimpleDateFormat不是线程安全的。 - Oleg Ushakov
@OlegUshakov 如果像这样内联,那么线程安全就不会失败。 - EpicPandaForce

11

Kotlin解决方案:

1)将此扩展函数粘贴到某个位置。

fun LocalDate.toDate(): Date = Date.from(this.atStartOfDay(ZoneId.systemDefault()).toInstant())

2) 使用它,不要再谷歌这个问题了。

val myDate = myLocalDate.toDate()

20
“转换到 Kotlin”有多简单?这是一个关于 Java 的问题。 - ehecatl
8
将 Java 的 LocalDate 转换为 Date 是任何 JVM 开发人员经常遇到的麻烦问题。这是 Kotlin 开发人员的解决方案。 - gyoder
1
谢谢!我一直在寻找 Kotlin 的解决方案。 - meekash55

-1
public static Date convertToTimeZone(Date date, String tzFrom, String tzTo) {
    return Date.from(LocalDateTime.ofInstant(date.toInstant(), ZoneId.of(tzTo)).atZone(ZoneId.of(tzFrom)).toInstant());
} 

2
请解释一下你的解决方案。 - Martin Zabel

-1
    LocalDate date = LocalDate.now();
    DateFormat formatter = new SimpleDateFormat("dd-mm-yyyy");
    try {
        Date utilDate= formatter.parse(date.toString());
    } catch (ParseException e) {
        // handle exception
    }

-2

试试这个:

public Date convertFrom(LocalDate date) {
    return Date.valueOf(date);
}

2
valueOf方法是java.sql.Date的成员,而问题指定了java.util.Date。 - nasch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接