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

23 浏览
0 Comments

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

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

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

admin 更改状态以发布 2023年5月23日
0
0 Comments

tl;dr

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

不要这样做。

这两个Date类已经过时了。 SunOracleJCP社区多年前放弃了这些传统的日期时间类,统一采用JSR 310定义的java.time类

  • 使用java.time类而不是JDBC 4.2或更高版本的旧的java.util.Datejava.sql.Date类。
  • 如果需要与尚未更新到java.time的代码进行交互,则需进行转换。
传统的 现代的 转换
java.util.Date java.time.Instant java.util.Date.toInstant()
java.util.Date.from( Instant )
java.sql.Date java.time.LocalDate java.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.
)

替代方式:

  • 使用Instant而不是java.util.Date,两者都表示UTC中的一个时刻,但现在精确到纳秒而不是毫秒。
  • 使用LocalDate而不是java.sql.Date,两者都表示没有日期的时间和时区。

细节

如果您正在尝试使用仅具有日期(不含时间,不含时区)的值,则应使用LocalDate类而不是java.util.Date

Table of date-time types in Java (both legacy and modern) and in the SQL standard.

java.time

在Java 8及更高版本中,早期版本的Java中捆绑的令人困扰的旧日期时间类已被新的java.time包取代。请参见Oracle教程。大部分功能已经被导回到Java 6&7中的ThreeTen-Backport中,并在ThreeTenABP中进一步适应了Android。

SQL数据类型 DATE 表示只有日期而没有时间和时区。Java 8 中引入了 java.time.LocalDate 类型,正好满足这样的要求。我们可以使用指定时区的今天的日期来创建这样的值(时区在确定日期时很重要,例如新的一天在巴黎比蒙特利尔早)。

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规范,你应该可以在 PreparedStatement 上使用 setObject 通过传递一个 LocalDate 存储到 SQL DATE 字段中。

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

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

反过来也可以这么做。

LocalDate localDate = sqlDate.toLocalDate();

java.util.Date 进行转换

虽然你应该避免使用旧的日期时间类,但在使用现有代码时可能会被迫这样做。如果需要这样做,那么可以进行 java.time 和 java.util.Date 类型之间的转换。

使用代表 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 8 及其后续版本内建 java.time 框架。这些类代替了麻烦的旧遗留日期时间类,如 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 类?

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

ThreeTen-Extra项目扩展了java.time的附加类。该项目是java.time可能未来增加的类的实验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuarter更多

0
0 Comments

算了吧....

public class MainClass {
  public static void main(String[] args) {
    java.util.Date utilDate = new java.util.Date();
    java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
    System.out.println("utilDate:" + utilDate);
    System.out.println("sqlDate:" + sqlDate);
  }
}

解释了一下。链接是http://www.java2s.com/Tutorial/Java/0040__Data-Type/ConvertfromajavautilDateObjecttoajavasqlDateObject.htm

0