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


当前回答

博士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表示精确到毫秒的特定时刻。它表示不带时区的日期和时间信息。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,这从它们的实现细节中可以明显看到。

使用java.sql.Date的唯一时间是在PreparedStatement.setDate中。否则,使用java.util.Date。它告诉ResultSet。getDate返回一个java.sql.Date,但它可以直接分配给java.util.Date。

祝贺您,您已经解决了JDBC最让我头疼的问题:日期类处理。

基本上,数据库通常至少支持三种形式的datetime字段,即date、time和timestamp。它们中的每一个在JDBC中都有一个对应的类,并且它们都扩展了java.util.Date。这三者的快速语义如下:

java.sql.Date对应于SQL DATE,这意味着它存储年、月和日,而忽略小时、分钟、秒和毫秒。此外sql。日期不受时区限制。 java.sql.Time对应于SQL TIME,很明显,它只包含有关小时、分钟、秒和毫秒的信息。 java.sql.Timestamp与SQL TIMESTAMP相对应,SQL TIMESTAMP是精确到纳秒的日期(请注意util. TIMESTAMP是精确到纳秒的日期)。日期只支持毫秒!),可自定义精度。

在使用与这三种类型相关的JDBC驱动程序时,最常见的错误之一是这些类型被错误地处理。这意味着sql。Date是特定于时区的,sql。时间包含当前的年、月、日等等。

最后:用哪一个呢?

实际上这取决于字段的SQL类型。PreparedStatement有三个值的设置器,#setDate()是sql的设置器。日期,#setTime() sql。sql.Timestamp的时间和#setTimestamp()。

请注意,如果您使用ps.setObject(fieldIndex, utilDateObject);你可以给出一个正常的util。大多数JDBC驱动程序会很高兴地处理它,就好像它是正确的类型一样,但是当您随后请求数据时,您可能会注意到您实际上遗漏了一些东西。

我的意思是,这些日期都不应该使用。

我所说的是将毫秒/纳秒保存为普通的长度,并将它们转换为您正在使用的任何对象(强制性的joda-time插头)。一种简单的方法是将日期组件存储为一个长时间组件,将时间组件存储为另一个长时间组件,例如现在将存储为20100221和154536123。这些神奇的数字可以在SQL查询中使用,并且可以从数据库移植到另一个数据库,并且可以让您完全避免JDBC/Java Date API:s的这一部分。

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

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

博士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....