Tor*_*res 28 java timestamp compare date equals
当我测试这段代码时:
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));
Run Code Online (Sandbox Code Playgroud)
我期待一个真实,真实,真实,虚假.因为这:
在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)方法不对称.此外,哈希码方法使用底层的java.util.Date实现,因此在其计算中不包括nanos.
由于Timestamp类和上面提到的java.util.Date类之间存在差异,因此建议代码不要将Timestamp值一般视为java.util.Date的实例.Timestamp和java.util.Date之间的继承关系实际上表示实现继承,而不是类型继承.
但相反,我会得到一个真实的,虚假的,真实的,错误的.有任何想法吗?
编辑:当我用equals方法检查两个日期时出现此问题,但其中一个Date对象来自Hibernate类并且调试我看到该对象包含TimeStamp.所以equals方法评估为false,然后我发现了这个:http://mattfleming.com/node/141
但是当我尝试代码时,我会得到不同的结果......如果我不能同时使用equals和compareTo,我应该用什么来检查2个日期是否相同?!?!
Nican解释了这equals
部分,关于compareTo
:
Timestamp
有一个compareTo(Date)
方法将其转换为Timestamp
内部Date
通过向下转换进行比较(因为它Timestamp
是它的子类); 但正如Javadoc:"时间戳和java.util.Date之间的继承关系实际上指的是实现继承,而不是类型继承"在我看来,这当然是一个可怕的想法.
使用现代java.time类而不是那些麻烦的遗留日期时间类.
myPreparedStatement.setObject(
… ,
Instant.now() // Capture the current moment in UTC.
)
Run Code Online (Sandbox Code Playgroud)
更直接地说,java.sql.Timestamp/.Date/.Time类是一个黑客,一个糟糕的黑客.与java.util.Date/.Calendar一样,它们是糟糕的设计选择的结果.
应尽可能简单地使用java.sql类型,仅用于数据传入/传出数据库.不要用于业务逻辑和进一步的工作.
旧的日期时间类已被Java 8及更高版本中内置的java.time框架所取代.这些新类由JSR 310定义,受到非常成功的Joda-Time库的启发,并由ThreeTen-Extra项目扩展.
最终我们应该看到更新的JDBC驱动程序直接使用这些java.time类型.但直到那天我们需要转换为/从java.sql类型.对于此类转换,请调用添加到旧类的新方法.
An Instant
是UTC时间轴上的一个时刻,分辨率为纳秒.
Instant instant = myJavaSqlTimestamp.toInstant();
Run Code Online (Sandbox Code Playgroud)
走向另一个方向:
java.sql.Timestamp ts = java.sql.Timestamp.valueOf( instant );
Run Code Online (Sandbox Code Playgroud)
应用时区以获得挂钟时间.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Run Code Online (Sandbox Code Playgroud)
java.time类有一个明智的选择类设计.所以你可以使用equals
和compareTo
预期的一样.需要注意的是有偏移的,UTC或时区的班还提供isEqual
,isBefore
和isAfter
方法.这些方法通过考虑时间轴上的时刻,它们的时间顺序来进行比较.该equals
和compareTo
方法也考虑偏移或时区.
最大限度地减少java.sql的使用,同时最大限度地使用java.time,这使得问题的问题没有实际意义.
在Hibernate中,为java.time使用转换器.
从JDBC 4.2及更高版本开始,您根本不需要使用遗留类.您可以通过&methods 直接与数据库交换java.time对象.getObject
setObject
myPreparedStatement.setObject( … , instant ) ;
Run Code Online (Sandbox Code Playgroud)
并检索.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Run Code Online (Sandbox Code Playgroud)
请注意,许多数据库无法存储分辨率与java.time中使用的纳秒一样精细的分钟.您可能希望显式截断,而不是让JDBC驱动程序隐式执行此操作.
Instant instant = Instant.now().truncatedTo( ChronoUnit.MILLIS ) ; // Lop off any nanoseconds & microseconds, keeping only the milliseconds, to match limitations of database.
Run Code Online (Sandbox Code Playgroud)
该java.time框架是建立在Java 8和更高版本.这些类取代麻烦的老传统日期时间类,如java.util.Date
,Calendar
,和SimpleDateFormat
.
现在处于维护模式的Joda-Time项目建议迁移到java.time类.
要了解更多信息,请参阅Oracle教程.并搜索Stack Overflow以获取许多示例和解释.规范是JSR 310.
您可以直接与数据库交换java.time对象.使用符合JDBC 4.2或更高版本的JDBC驱动程序.不需要字符串,不需要课程.java.sql.*
从哪里获取java.time类?
该ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval
,YearWeek
,YearQuarter
,和更多.
我曾在一个测试,我想比较同样的问题java.util.Date
和java.sql.Timestamp
对象。
我将它们转换为LocalDate
并且有效:
import org.apache.commons.lang.ObjectUtils;
// date1 and date2 can be java.util.Date or java.sql.Timestamp
boolean datesAreEqual = ObjectUtils.equals(toLocalDate(date1), toLocalDate(date2));
Run Code Online (Sandbox Code Playgroud)
在哪里toLocalDate
:
import org.joda.time.LocalDate;
import java.util.Date;
public static void LocalDate toLocalDate(Date date)
{
return date != null ? LocalDate.fromDateFields(date) : null;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
48232 次 |
最近记录: |