java.util.Date vs . java.sql.Date:什么时候使用哪个,为什么?


当前回答

date表示精确到毫秒的特定时刻。它表示不带时区的日期和时间信息。date类实现了可序列化、可克隆和可比较的接口。它被java.sql继承。Date、java.sql.Time和java.sql.Timestamp接口。

java.sql.Date扩展了java.util.Date类,它表示没有时间信息的日期,只应该在处理数据库时使用。为了符合SQL DATE的定义,java.sql.Date实例包装的毫秒值必须“规范化”,方法是在实例关联的特定时区中将小时、分钟、秒和毫秒设置为零。

它继承了java.util.Date的所有公共方法,如getHours()、getMinutes()、getSeconds()、setHours()、setMinutes()、setSeconds()。由于java.sql.Date不存储时间信息,它覆盖了java.util. date中的所有时间操作,并且所有这些方法在调用时会抛出java.lang.IllegalArgumentException,这从它们的实现细节中可以明显看到。

其他回答

博士tl;

用都没有。

java.time.Instant取代java.util.Date java.time.LocalDate替换java.sql.Date

既不

java.util.Date vs . java.sql.Date:什么时候使用哪个,为什么?

这两个类都很糟糕,在设计和实现上都有缺陷。像避免鼠疫冠状病毒一样。

请使用java。在JSR 310中定义。这些类是用于处理日期-时间处理的行业领先框架。它们完全取代了可怕的遗留类,如Date、Calendar、SimpleDateFormat等。

java.util.Date

第一个,java.util.Date表示UTC中的一个时刻,即与UTC的零小时-分钟-秒的偏移量。

java.time.Instant

现在被java.time.Instant取代。

Instant instant = Instant.now() ;  // Capture the current moment as seen in UTC.

java.time.OffsetDateTime

Instant是java.time的基本构建块类。为了获得更大的灵活性,可以将OffsetDateTime设置为ZoneOffset。同样的目的:表示UTC时间。

OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;

您可以在JDBC 4.2或更高版本中使用PreparedStatement::setObject将该对象发送到数据库。

myPreparedStatement.setObject( … , odt ) ;

检索。

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

java.sql.Date

date类也很糟糕,过时了。

该类只表示日期,没有时间和时区。不幸的是,在一个糟糕的设计中,这个类继承了java.util.Date,它表示一个时刻(一个UTC时间的日期)。因此,这个类只是假装只有日期,而实际上携带了一个时间和UTC的隐式偏移量。这引起了很多困惑。永远不要使用这个类。

java.time.LocalDate

相反,使用java.time.LocalDate只跟踪一个日期(年、月、日),而不跟踪任何时间、任何时区或偏移量。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate ld = LocalDate.now( z ) ;    // Capture the current date as seen in the wall-clock time used by the people of a particular region (a time zone).

发送到数据库。

myPreparedStatement.setObject( … , ld ) ;

检索。

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;


关于java.time

java。时间框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期-时间类,如java.util。日期,日历和简单日期格式。

要了解更多,请参阅Oracle教程。搜索Stack Overflow可以找到很多例子和解释。规范是JSR 310。

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

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

从哪里获取java。时间类?

Java SE 8、Java SE 9、Java SE 10、Java SE 11及更高版本——带有捆绑实现的标准Java API的一部分。 Java 9增加了一些小特性并进行了修复。 Java SE 6和Java SE 7 大部分的java。时间功能在ThreeTen-Backport中向后移植到Java 6和7。 安卓 后续版本的Android捆绑实现的java。时间类。 对于早期的Android (<26), ThreeTenABP项目适应ThreeTen-Backport(如上所述)。参见如何使用ThreeTenABP....

date类在Java中表示一个特定的时刻(例如,.g。, 2013 Nov 25 16:30:45精确到毫秒),但是DB中的DATE数据类型只表示一个日期(例如,2013 Nov 25)。为了防止您错误地向DB提供Java .util. date对象,Java不允许您直接将SQL参数设置为Java .util. date:

PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, d); //will not work

但是它仍然允许您通过强制/意图来这样做(然后DB驱动程序将忽略小时和分钟)。这是通过java.sql.Date类完成的:

PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, new java.sql.Date(d.getTime())); //will work

java.sql.Date对象可以存储时刻(因此很容易从java.util.Date构造它),但如果您试图询问它的小时数(以强制其仅为日期的概念),则会抛出异常。DB驱动程序应该能够识别这个类,并且只使用0表示小时数。试试这个:

public static void main(String[] args) {
  java.util.Date d1 = new java.util.Date(12345);//ms since 1970 Jan 1 midnight
  java.sql.Date d2 = new java.sql.Date(12345);
  System.out.println(d1.getHours());
  System.out.println(d2.getHours());
}

LATE EDIT:从Java 8开始,你不应该使用Java .util. date或Java .sql. date,如果你可以避免它,而宁愿使用Java .util. date。时间包(基于Joda)而不是其他任何东西。如果你没有使用Java 8,以下是最初的回复:


java.sql.Date -当你调用使用它的库(如JDBC)的方法/构造函数时。没有否则。对于不显式处理JDBC的应用程序/模块,您不希望向数据库库引入依赖项。

date -当使用使用它的库时。否则,尽可能少,原因如下:

It's mutable, which means you have to make a defensive copy of it every time you pass it to or return it from a method. It doesn't handle dates very well, which backwards people like yours truly, think date handling classes should. Now, because j.u.D doesn't do it's job very well, the ghastly Calendar classes were introduced. They are also mutable, and awful to work with, and should be avoided if you don't have any choice. There are better alternatives, like the Joda Time API (which might even make it into Java 7 and become the new official date handling API - a quick search says it won't).

如果您觉得引入像Joda这样的新依赖项有点过分,那么对于对象中的时间戳字段使用long也不是那么糟糕,尽管我自己在传递它们时通常将它们包装在j.u.D中,以确保类型安全和作为文档。

我有同样的问题,我发现插入当前日期到一个准备好的语句的最简单的方法是:

preparedStatement.setDate(1, new java.sql.Date(new java.util.Date().getTime()));

date表示精确到毫秒的特定时刻。它表示不带时区的日期和时间信息。date类实现了可序列化、可克隆和可比较的接口。它被java.sql继承。Date、java.sql.Time和java.sql.Timestamp接口。

java.sql.Date扩展了java.util.Date类,它表示没有时间信息的日期,只应该在处理数据库时使用。为了符合SQL DATE的定义,java.sql.Date实例包装的毫秒值必须“规范化”,方法是在实例关联的特定时区中将小时、分钟、秒和毫秒设置为零。

它继承了java.util.Date的所有公共方法,如getHours()、getMinutes()、getSeconds()、setHours()、setMinutes()、setSeconds()。由于java.sql.Date不存储时间信息,它覆盖了java.util. date中的所有时间操作,并且所有这些方法在调用时会抛出java.lang.IllegalArgumentException,这从它们的实现细节中可以明显看到。