LocalDate到java.util.Date,反之亦然最简单的转换?

Geo*_*rge 115 java date java-8 java-time

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

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

Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
Run Code Online (Sandbox Code Playgroud)

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

由于我们只对日期部分感兴趣,并且两个对象中都没有时区信息,为什么要明确引入时区?应该隐式采用午夜时间和系统默认时区进行转换.

Geo*_*rge 119

实际上有.在对象中有一个静态方法valueOf就是java.sql.Date这样做的.所以我们有

java.util.Date date = java.sql.Date.valueOf(localDate);
Run Code Online (Sandbox Code Playgroud)

就是这样.没有明确设置时区,因为隐式采用了本地时区.

来自docs:

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

java.sql.Date子类java.util.Date这样的结果是java.util.Date也.

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

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

  • 作为`java.time.*`库的作者,我感到很难过,有40多人认为适合这一点.正确的答案是[这里](http://stackoverflow.com/a/21242111/38896)和Basil的下面.使用`java.sql.Date`是一个可怕的黑客,如其他评论所表达的,这种方法隐藏了时区转换,这是一件坏事.多年来人们也知道`java.sql.Date`永远不应该扩展`java.util.Date`.最后,当在Java 9中使用模块时,`java.sql`类将是一个单独的依赖项,因此使用此hack会产生后果. (56认同)
  • 不建议这样的答案,因为a)它缺乏对不同时区的支持,b)混合两种不同的类型,其中继承关系仅表示实现驱动的依赖.类型`java.sql.Date`应该只在JDBC的上下文中应用.最佳答案见@Basil Bourque (14认同)
  • 它充其量只是一个黑客.请忽略这个答案.而是看@ BasilBourque的[回答](/sf/answers/2810058121/) (5认同)
  • 原始问题日期也在系统时区中.使用java.sql.Date实际的日期并不是那么遥远,恕我直言. (4认同)
  • 正如Hochschild所说,类doc告诉我们忽略java.util.Date和java.sql.Date之间的继承子类关系,告诉我们*不*做这个答案所做的.此外,`valueOf`方法确实*不*避开时区问题,它只是*隐藏*问题,同时默默应用JVM的当前默认区域将时间设置为午夜.因此,"没有时区,没有并发症"的说法是错误的**:*涉及*时区,并且*有*并发症,您只是选择忽略它们.java.time类是出于某种原因而发明的; 使用它们. (4认同)

Bas*_*que 86

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.
)
Run Code Online (Sandbox Code Playgroud)

请阅读下面的问题,然后再考虑一下.怎么会更简单?如果你问我约会的时间是什么时候开始的,我怎么回答却问你"哪里?"?新的一天在巴黎FR早些时候比在加利福尼亚州的蒙特利尔,早些时候在加尔各答IN,甚至早些时候在新西兰奥克兰,所有不同的时刻.

因此,在将date-only(LocalDate)转换为日期时,我们必须应用时区(ZoneId)来获取分区值(ZonedDateTime),然后移入UTC(Instant)以匹配a的定义java.util.Date.

细节

首先,java.util.Date尽可能避免旧的遗留日期时间类.它们的设计很糟糕,令人困惑,也很麻烦.他们被java.time类是有原因的取代,其实,对于很多原因.

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

java.util.Datejava.time.LocalDate

请记住,a java.util.Date是一个误称,因为它代表一个日期加上一个时间,以UTC为单位.相反,LocalDate该类表示没有时间且没有时区的仅日期值.

java.util.Datejava.time开始意味着转换为等效的类java.time.Instant.该Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多9个(9)小数的位数).

Instant instant = myUtilDate.toInstant();
Run Code Online (Sandbox Code Playgroud)

LocalDate级表示没有时间一天和不同时区的日期,唯一的价值.

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

所以我们需要把它Instant移到一个时区.我们申请ZoneId获得ZonedDateTime.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
Run Code Online (Sandbox Code Playgroud)

从那里,要求仅限日期,a LocalDate.

LocalDate ld = zdt.toLocalDate();
Run Code Online (Sandbox Code Playgroud)

java.time.LocalDatejava.util.Date

要移动另一个方向,从a java.time.LocalDate到a java.util.Date意味着我们将从仅日期转到日期时间.所以我们必须指定一个时间.你可能想要一天中的第一时间.难道认为是00:00:00.夏令时(DST)等异常意味着第一时刻可能是另一个时间,例如01:00:00.让java.time通过调用确定的值atStartOfDayLocalDate.

ZonedDateTime zdt = myLocalDate.atStartOfDay( z );
Run Code Online (Sandbox Code Playgroud)

现在提取一个Instant.

Instant instant = zdt.toInstant();
Run Code Online (Sandbox Code Playgroud)

通过调用将其转换Instant为.java.util.Datefrom( Instant )

java.util.Date d = java.util.Date.from( instant );
Run Code Online (Sandbox Code Playgroud)

更多信息


关于java.time

java.time框架是建立在Java 8和更高版本.这些类取代麻烦的老传统日期时间类,如java.util.Date,Calendar,和SimpleDateFormat.

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

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

您可以直接与数据库交换java.time对象.使用符合JDBC 4.2或更高版本的JDBC驱动程序.不需要字符串,不需要课程.java.sql.*

从哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval,YearWeek,YearQuarter,和更多.

  • 我喜欢这个答案,因为它包含了tl和dr部分,谢谢 (3认同)

Hai*_*yen 16

日期 - > LocalDate:

LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
Run Code Online (Sandbox Code Playgroud)

LocalDate - >日期:

Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
Run Code Online (Sandbox Code Playgroud)

  • 如果你的`java.util.Date`实际上是一个`java.sql.Date`,那么这将给你一个`UnsupportedOperationException` (3认同)

小智 5

将 LocalDateTime 转换为 java.util.Date

    LocalDateTime localDateTime = LocalDateTime.now();

    ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneOffset.systemDefault());

    Instant instant = zonedDateTime.toInstant();

    Date date = Date.from(instant);

System.out.println("Result Date is : "+date);
Run Code Online (Sandbox Code Playgroud)