如何将 java.util.Date 转换为 java.sql.Date?

新手上路,请多包涵

我正在尝试使用 java.util.Date 作为输入,然后用它创建一个查询 - 所以我需要一个 java.sql.Date

我惊讶地发现它不能隐式或显式地进行转换——但我什至不知道该怎么做,因为 Java API 对我来说还是相当新的。

原文由 David Ackerman 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 714
2 个回答

tl;博士

如何将 java.util.Date 转换为 java.sql.Date?

不。

Date 两个类都已过时。 SunOracleJCP 社区几年前就放弃了这些遗留的日期时间类,一致采用了定义 java.time 类的 JSR 310

  • 使用 java.time 类而不是传统的 java.util.Date & java.sql.Date 与 JDBC 4.2 或更高版本。
  • 如果与尚未更新为 java.time 的代码进行互操作,则转换为 java.time 或从 java.time 转换。

遗产现代的转换java.util.Datejava.time.Instantjava.util.Date.toInstant()

java.util.Date.from( Instant )java.sql.Datejava.time.LocalDatejava.sql.Date.toLocalDate()

java.sql.Date.valueOf( LocalDate )

使用 PreparedStatement 的示例查询。

 myPreparedStatement.setObject(
    … ,                                         // Specify the ordinal number of which argument in SQL statement.
    myJavaUtilDate.toInstant()                  // Convert from legacy class `java.util.Date` (a moment in UTC) to a modern `java.time.Instant` (a moment in UTC).
        .atZone( ZoneId.of( "Africa/Tunis" ) )  // Adjust from UTC to a particular time zone, to determine a date. Instantiating a `ZonedDateTime`.
        .toLocalDate()                          // Extract a date-only `java.time.LocalDate` object from the date-time `ZonedDateTime` object.
)

替代品:

两者都代表 UTC 中的一个时刻。但现在用纳秒而不是毫秒。 - LocalDate 而不是 java.sql.Date

两者都表示没有时间和时区的仅日期值。

细节

如果您尝试使用仅日期值(无时间、无时区),请使用 LocalDate 类而不是 java.util.Date

Java(传统和现代)和 SQL 标准中的日期时间类型表。

java.time

在 Java 8 及更高版本中,与早期版本的 Java 捆绑在一起的麻烦的旧日期时间类已被新的 java.time 包 取代。请参阅 Oracle 教程。大部分功能已在 ThreeTen- Backport 中向后移植到 Java 6 和 7,并在 ThreeTenABP 中 进一步适应 Android。

SQL 数据类型 DATE 意味着只有日期,没有时间和时区。在 Java 8 中的 java.time.LocalDate 之前,Java 从未有过这样的类†。让我们通过根据特定时区获取今天的日期来创建这样的值(时区对于确定日期很重要,因为新的一天更早黎明例如,在巴黎比在蒙特利尔)。

 LocalDate todayLocalDate = LocalDate.now( ZoneId.of( "America/Montreal" ) );  // Use proper "continent/region" time zone names; never use 3-4 letter codes like "EST" or "IST".

至此,我们可能就完成了。如果您的 JDBC 驱动程序 符合 JDBC 4.2 规范,您应该能够将 LocalDate 通过 setObjectPreparedStatement 上传递到存储到 SQLATE 字段中。

 myPreparedStatement.setObject( 1 , localDate );

同样,使用 ResultSet::getObject 从 SQL DATE 列获取到 Java LocalDate 对象。在第二个参数中指定类使您的代码 类型安全

 LocalDate localDate = ResultSet.getObject( 1 , LocalDate.class );

换句话说, 这整个问题在 JDBC 4.2 或更高版本下是无关紧要的

如果您的 JDBC 驱动程序不以这种方式执行,您需要退回到转换为 java.sql 类型。

转换为 java.sql.Date

要进行转换,请使用添加到旧日期时间类的新方法。我们可以调用 java.sql.Date.valueOf(…) 来转换一个 LocalDate

 java.sql.Date sqlDate = java.sql.Date.valueOf( todayLocalDate );

并走向另一个方向。

 LocalDate localDate = sqlDate.toLocalDate();

java.util.Date 转换

虽然您应该避免使用旧的日期时间类,但在使用现有代码时可能会被迫这样做。如果是这样,您可以转换为/从 java.time。

通过 Instant 类,它代表 UTC 时间线上的时刻。一个 Instant 在思想上类似于一个 java.util.Date 。但请注意, Instant 的分辨率高达 纳秒,而 java.util.Date 只有 毫秒 的分辨率。

要进行转换,请使用添加到旧类的新方法。例如, java.util.Date.from( Instant )java.util.Date::toInstant

 Instant instant = myUtilDate.toInstant();

要确定日期,我们需要时区的上下文。对于任何给定的时刻,日期在全球范围内因时区而异。应用 ZoneId 以获得 ZonedDateTime

 ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
LocalDate localDate = zdt.toLocalDate();


† java.sql.Date 类假装只有日期,没有时间,但 实际上 是时间,调整为午夜时间。令人困惑?是的,旧的日期时间课程一团糟。


关于 java.time

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

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

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

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

从哪里获得 java.time 类?

哪个 java.time 库与哪个版本的 Java 或 Android 一起使用的表

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

原文由 Basil Bourque 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题