在Java中将Date对象与TimeStamp进行比较

当我测试此代码时:

java.util.Date date = new java.util.Date();

java.util.Date stamp = new java.sql.Timestamp(date.getTime());

assertTrue(date.equals(stamp));

assertTrue(date.compareTo(stamp) == 0);

assertTrue(stamp.compareTo(date) == 0);

assertTrue(stamp.equals(date));

我期待一个真实,真实,真实,错误。因为这:

在java.sql.Timestamp的javadoc中,它指出:

注意:此类型是java.util.Date和单独的纳秒值的组合。仅整数秒存储在java.util.Date组件中。小数秒-纳米-

是分开的。传递值java.util.Date类型的值时,Timestamp.equals(Object)方法从不返回true,因为日期的nanos组件是未知的。结果,Timestamp.equals(Object)方法相对于java.util.Date.equals(Object)方法不对称。另外,hashcode方法使用底层的java.util.Date实现,因此在其计算中不包括nanos。

由于上述Timestamp类和java.util.Date类之间的差异,建议代码不要以java.util.Date的实例的形式一般性地查看Timestamp值。Timestamp和java.util.Date之间的继承关系实际上表示实现继承,而不是类型继承。

但是相反,我会得到一个真实,错误,真实,错误的信息。有任何想法吗?

编辑:当我用equals方法检查两个日期,但其中一个Date对象来自Hibernate类并进行调试时,出现此问题,我看到该对象包含一个TimeStamp。因此equals方法的评估结果为false,然后我发现了这一点:http

//mattfleming.com/node/141

但是,当我尝试代码时,会得到不同的结果…如果我不能同时使用equals和compareTo,那我应该用什么来检查2个日期是否相同?!

回答:

tl; dr

使用现代的 java.time 类,而不要使用那些麻烦的旧式日期时间类。

myPreparedStatement.setObject(

… ,

Instant.now() // Capture the current moment in UTC.

)

设计不好的旧日期时间类

坦率地说,java.sql.Timestamp / .Date /

.Time类是一个hack,一个糟糕的hack。像java.util.Date/.Calendar一样,它们是错误的设计选择的结果。

应该尽可能简短地使用java.sql类型,仅用于将数据移入/移出数据库。请勿用于业务逻辑和进一步的工作。

java.time

旧的日期时间类已被内置在Java

8及更高版本中的java.time框架取代。这些新类由JSR 310定义,其灵感来自于非常成功的Joda-Time库,并由ThreeTen-Extra项目扩展。

最终,我们应该看到JDBC驱动程序已更新,可以直接与这些java.time类型一起使用。但是直到那一天,我们需要转换为java.sql类型或从java.sql类型转换为。对于此类转换,请调用添加到旧类中的新方法。

一个Instant是UTC时间线的分辨率了一下纳秒。

Instant instant = myJavaSqlTimestamp.toInstant();

要走另一个方向:

java.sql.Timestamp ts = java.sql.Timestamp.valueOf( instant );

应用一个时区以获得壁钟时间。

ZoneId zoneId = ZoneId.of( "America/Montreal" );

ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

java.time类具有简洁明智的类设计。因此您可以按预期使用equalscompareTo。需要注意的是有偏移的,UTC或时区的班还提供isEqualisBeforeisAfter方法。这些方法通过考虑时间轴上的时刻及其时间顺序进行比较。该equalscompareTo方法也考虑偏移或时区。

最小化java.sql的使用,同时最大化java.time的使用,使问题的讨论变得毫无意义。

在Hibernate中,将转换器用于java.time。

回答:

从JDBC 4.2和更高版本开始,您根本不需要使用旧类。您可以通过&方法直接与数据库交换 java.time

对象。getObject``setObject

myPreparedStatement.setObject( … , instant ) ;

和检索。

Instant instant = myResultSet.getObject( … , Instant.class ) ;

注意,许多数据库无法存储分辨率与 java.time中 使用的纳秒一样精细的 时刻

。您可能想要显式截断而不是让JDBC驱动程序隐式截断。

Instant instant = Instant.now().truncatedTo( ChronoUnit.MILLIS ) ; // Lop off any nanoseconds & microseconds, keeping only the milliseconds, to match limitations of database.


关于 java.time

java.time 框架是建立在Java

8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和SimpleDateFormat

现在处于维护模式的 Joda-

Time

项目建议迁移到java.time类。

要了解更多信息,请参见

Oracle教程 。并在Stack

Overflow中搜索许多示例和说明。规格为JSR 310。

您可以直接与数据库交换 java.time 对象。使用与JDBC

4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要类。java.sql.*

在哪里获取java.time类?

  • , , 和更高版本

    • 内置的
    • 标准Java API的一部分,具有捆绑的实现。
    • Java 9添加了一些次要功能和修复。

    • java.time的许多功能在 Backport中都被反向移植到Java 6和7 。

    • 更高版本的Android捆绑了java.time类的实现。
    • 对于早期的Android(<26), 项目改编了 (如上所述)。请参阅 如何使用ThreeTenABP…

项目与其他类扩展java.time。该项目是将来可能向java.time添加内容的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多。

以上是 在Java中将Date对象与TimeStamp进行比较 的全部内容, 来源链接: utcz.com/qa/415524.html

回到顶部