LocalDate 到 java.util.Date,反之亦然 最简单的转换?tl;博士详 java.util.Date→java.time.LocalDate java.time.LocalDate→java.util.Date 更多信息关于 java.time

2022-08-31 07:02:44

有没有一种简单的方法可以将(Java 8引入的)转换为对象?LocalDatejava.util.Date

通过“简单”,我的意思是比这更简单:

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

这对我来说似乎有点尴尬。

既然我们只对日期部分感兴趣,而这两个对象都没有时区信息,那么为什么要明确引入时区呢?午夜时间和系统默认时区应隐式进行转换。


答案 1

tl;博士

有没有一种简单的方法可以将LocalDate(Java 8引入)转换为java.util.Date对象?通过“简单”,我的意思是比这更简单

不。你做得正确,尽可能简洁。

java.util.Date.from(                     // Convert from modern java.time class to troublesome old legacy class.  DO NOT DO THIS unless you must, to inter operate with old code not yet updated for java.time.
    myLocalDate                          // `LocalDate` class represents a date-only, without time-of-day and without time zone nor offset-from-UTC. 
    .atStartOfDay(                       // Let java.time determine the first moment of the day on that date in that zone. Never assume the day starts at 00:00:00.
        ZoneId.of( "America/Montreal" )  // Specify time zone using proper name in `continent/region` format, never 3-4 letter pseudo-zones such as “PST”, “CST”, “IST”. 
    )                                    // Produce a `ZonedDateTime` object. 
    .toInstant()                         // Extract an `Instant` object, a moment always in UTC.
)

阅读下面的问题,然后考虑一下。它怎么可能更简单?如果你问我约会开始的时间,我还能回答,但问你“在哪里?”?在巴黎,新的一天比在蒙特利尔CA更早,在加尔各答更早,在奥克兰新西兰,所有不同的时刻。

因此,在将仅日期 () 转换为日期时间时,我们必须应用时区 () 来获取分区值 (),然后移入 UTC () 以匹配 .LocalDateZoneIdZonedDateTimeInstantjava.util.Date

首先,尽可能避免旧的旧日期时间类。它们设计不佳,令人困惑且麻烦。它们被java.time类所取代是有原因的,实际上,原因有很多java.util.Date

但是,如果必须,您可以将 java.time 类型转换为旧类型。查找添加到旧类的新转换方法。

Table of all date-time types in Java, both modern and legacy

java.util.Datejava.time.LocalDate

请记住,a 是用词不当,因为它以 UTC 格式表示日期加上一天中的时间。相反,LocalDate 类表示一个仅日期值,不带一天中的时间和时区。java.util.Date

从 到 java.time 意味着转换为 等效的类 。Instant 类以 UTC 格式表示时间轴上的某个时刻,分辨率为纳秒(最多九 (9) 位小数)。java.util.Datejava.time.Instant

Instant instant = myUtilDate.toInstant();

LocalDate 类表示一个仅日期值,不带时间,也不带时区。

时区对于确定日期至关重要。在任何给定的时刻,日期在全球范围内因区域而异。例如,法国巴黎午夜后几分钟是新的一天,而在魁北克蒙特利尔仍然是“昨天”。

因此,我们需要将其移动到时区。我们申请获得.InstantZoneIdZonedDateTime

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

从那里,请求一个仅限日期的 .LocalDate

LocalDate ld = zdt.toLocalDate();

java.time.LocalDatejava.util.Date

要将另一个方向移动,从 a 移动到 a 意味着我们将从仅日期移动到日期时间。因此,我们必须指定一天中的时间。你可能想去一天中的第一刻。不要假定为 。异常(如夏令时 (DST))表示第一个时刻可能是另一个时间,例如 。让 java.time 通过调用 .java.time.LocalDatejava.util.Date00:00:0001:00:00atStartOfDayLocalDate

ZonedDateTime zdt = myLocalDate.atStartOfDay( z );

现在提取一个 .Instant

Instant instant = zdt.toInstant();

通过调用从( 即时 )将其转换为。Instantjava.util.Date

java.util.Date d = java.util.Date.from( instant );

更多信息


关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧日期时间类,如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要类。Hibernate 5 & JPA 2.2 支持 java.timejava.sql.*

从哪里获取 java.time 类?

Table of which java.time library to use with which version of Java or Android

ThreeTen-Extra 项目通过其他类扩展了 java.time。这个项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuarter


答案 2

免責聲明:虽然下面的答案有效,但不建议在生产代码中使用。在这种情况下,应该遵循罗勒答案中的方法。

其实有。对象中有一个静态方法值Of正是这样做的。所以我们有java.sql.Date

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

仅此而已。没有显式设置时区,因为本地时区是隐式获取的。

来自文档:

提供的 LocalDate 被解释为本地时区的本地日期。

子类因此结果是也是。java.sql.Datejava.util.Datejava.util.Date

对于反向操作,java.sql.Date类中有一个toLocalDate方法。所以我们有:

LocalDate ld = new java.sql.Date(date.getTime()).toLocalDate();