【问题标题】:LocalDate to java.util.Date and vice versa simplest conversion? [duplicate]LocalDate 到 java.util.Date 和反之最简单的转换? [复制]
【发布时间】:2016-01-09 02:13:38
【问题描述】:

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

“简单”是指比这更简单:

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

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

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

【问题讨论】:

  • 如果您使用的是 Java 8,您可能应该完全避免使用 java.util.Date
  • “因为我们只对日期部分感兴趣”的问题是java.util.Date 默认情况下不仅代表关于日期(年/月/日)的信息,而且还代表关于一天中的时间的信息所以我们需要以某种方式提供这些信息(这里有帮助atStartOfDay)。
  • 日期代表一个精确的瞬间。 LocalDate 没有。这只是一组字段。因此,您需要指定一个时区来将这组字段转换为瞬间:2015-10-11T00:00 在巴黎和纽约不是同一瞬间。
  • @Reimeus:如果他使用的是较旧的 API,那么他可能别无选择,只能使用 Date。例如,JPA 2.1 的@Basic 注释直接识别DateCalendar,但只能将Instant 作为可序列化类型使用。我会说他在他的新代码中使用新的日期时间 API 并使用Date 进行互操作是正确的。
  • @George:DateInstant 的通用合同都包含时间概念。因此,LocalDateDate 之间的相互转换意味着您必须处理时间概念,即使您不打算使用时间信息。在不知道“某个本地时区”是什么的情况下,您无法从“某个本地时区的 2015 年 9 月 7 日”(LocalDate)转换为“UTC 时间 1970 年 1 月 1 日午夜以来的毫秒数”(Date) .

标签: java date java-8 java-time


【解决方案1】:

免责声明:虽然以下答案有效,但不建议在生产代码中使用。在这种情况下,应遵循 Basil 答案中的方法。

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

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

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

来自文档:

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

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

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

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

【讨论】:

  • 原始问题 Date 也在系统时区中。恕我直言,将 java.sql.Date 用于实际日期并不是那么遥不可及。
  • 不推荐这个答案,因为a)它缺乏对不同时区的支持,b)混合了两种不同的类型,其中继承关系仅表示实现驱动的依赖关系。 java.sql.Date 类型只能在 JDBC 上下文中应用。最佳答案见@Basil Bourque
  • 正如Hochschild所说,class doc告诉我们忽略java.util.Date和java.sql.Date之间的继承子类关系,告诉我们not做这个答案可以。此外,valueOf 方法确实避开时区问题,它只是隐藏问题,同时默默地应用JVM当前的默认区域设置时间到午夜。所以“没有时区,没有复杂性”的说法不正确:涉及个时区,有个复杂性,你只是选择忽略它们。 java.time 类的发明是有原因的;使用它们。
  • 作为java.time.* 库的作者,我很遗憾有超过 40 人认为适合对此进行投票。正确答案是here,下面是 Basil。使用java.sql.Date 是一种可怕的黑客攻击,正如其他 cmets 所表达的那样,这种方法隐藏了时区转换,这是一件坏事。多年来,众所周知java.sql.Date 永远不应该扩展java.util.Date。最后,在 Java 9 中使用模块时,java.sql 类将是一个单独的依赖项,因此使用此 hack 会产生后果。
  • 它充其量只是一个黑客。请忽略这个答案。而是查看@BasilBourque 的answer
【解决方案2】:

您可以将java.util.Date 对象转换为String 对象,这会将日期格式化为yyyy-mm-dd。

LocalDate 有一个parse 方法,可以将其转换为LocalDate 对象。该字符串必须代表一个有效的日期,并使用 DateTimeFormatter.ISO_LOCAL_DATE 进行解析。

本地日期的日期

LocalDate.parse(Date.toString())

【讨论】:

  • 你显然没有测试你的代码建议,否则你会看到一个异常,因为java.time.LocalDate 需要一个 ISO 格式的字符串,而不是java.util.Date 的标准输出。值得一票,但今天我过得愉快 ;-) Basil Bourque 给出了最佳答案。
【解决方案3】:

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.
)

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

因此,在将仅日期 (LocalDate) 转换为日期时间时,我们必须应用时区 (ZoneId) 以获得分区值 (ZonedDateTime),并且然后移动到 UTC (Instant) 以匹配 java.util.Date 的定义。

详情

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

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

java.util.Datejava.time.LocalDate

请记住,java.util.Date 是用词不当,因为它表示日期加上 UTC 时间。相比之下,LocalDate 类表示没有时间和时区的仅日期值。

java.util.Date 到java.time 意味着转换到java.time.Instant 的等效类。 Instant 类表示 UTC 时间线上的时刻,分辨率为 nanoseconds(最多九 (9) 位小数)。

Instant instant = myUtilDate.toInstant();

LocalDate 类表示没有时间和时区的仅日期值。

时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因区域而异。例如,Paris France 中午夜过后几分钟是新的一天,而 Montréal Québec 中仍然是“昨天”。

所以我们需要将Instant 移动到一个时区。我们申请ZoneId 以获得ZonedDateTime

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

从那里,要求一个仅限日期,LocalDate

LocalDate ld = zdt.toLocalDate();

java.time.LocalDatejava.util.Date

换个方向,从java.time.LocalDatejava.util.Date 意味着我们要从仅日期到日期时间。所以我们必须指定一个时间。您可能想在一天的第一时间去。 不要假设那是00:00:00。夏令时 (DST) 等异常意味着第一个时刻可能是另一个时间,例如 01:00:00。让 java.time 通过在 LocalDate 上调用 atStartOfDay 来确定该值。

ZonedDateTime zdt = myLocalDate.atStartOfDay( z );

现在提取一个Instant

Instant instant = zdt.toInstant();

通过调用 from( Instant )Instant 转换为 java.util.Date

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

更多信息


关于java.time

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

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

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

从哪里获取 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

  • 我喜欢这个答案,因为它同时包含 tl 和 dr 部分,谢谢
【解决方案4】:

我用下面的解决方案解决了这个问题

  import org.joda.time.LocalDate;
  Date myDate = new Date();
  LocalDate localDate = LocalDate.fromDateFields(myDate);
  System.out.println("My date using Date" Nov 18 11:23:33 BRST 2016);
  System.out.println("My date using joda.time LocalTime" 2016-11-18);

在这种情况下,localDate 以这种格式“yyyy-MM-dd”打印您的日期

【讨论】:

  • 错字?您的意思是通过date 而不是data
  • 请引用该方法的文档。我在class doc for java.time.LocalDate 上没有看到该方法。
  • 我的错。我的错。我忘记复制变量了。
  • 您可以编辑您的答案以更正错字。并澄清您使用的该方法的来源。似乎来自 Joda-Time,但这个问题是关于 java.time.LocalDate。 Joda-Time 项目现在处于维护模式,团队建议迁移到 java.time。
  • 感谢@BasilBourque 的观察。在这种情况下,我使用包的类 LocalDate:org.joda.time 修复答案我用以下解决方案解决了这个问题:import org.joda.time.LocalDate Date myDate = new Date (); LocalDate localDate = LocalDate.fromDateFields (myDate); System.out.println("My date using Date" Nov 18 11:23:33 BRST 2016); System.out.println("My date using joda.time LocalTime" 2016-11-18);
【解决方案5】:

日期 -> 本地日期:

LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

LocalDate -> 日期:

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

【讨论】:

  • 如果你的java.util.Date实际上是java.sql.Date,那么这会给你一个UnsupportedOperationException
【解决方案6】:

将 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);

【讨论】:

    【解决方案7】:

    本地日期的日期

    Date date = new Date();
    LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    

    LocalDate 日期

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

    【讨论】:

      猜你喜欢
      • 2011-04-10
      • 2019-07-22
      • 2018-07-15
      • 2011-08-01
      • 2015-06-27
      • 1970-01-01
      • 1970-01-01
      • 2015-06-28
      • 2020-01-04
      相关资源
      最近更新 更多