java.sql.Timestamp是从java.util.Date创建的,为什么总是在它之前?
在一个bug之后,我注意到如果使用以毫秒为单位的构造函数从java.util.Date创建java.sql.Timestamp,则Date实例总是在时间戳之后。这是令人费解的,因为(a)before()的契约指定了严格的比较,(b)如果不相等,时间戳(因为它有纳秒)本身可能在日期()之后。但是结果是相反的,并且是可重复的(对于JDK1.6和1.7,使用不同的JVM时区)。比较两个日期是正确的,但是对一个日期调用before()或after()并给出Timestamp参数会产生意外的结果 下面的示例代码有两个日期和一个时间戳实例,它们都具有相同的毫秒值。然而,将日期与时间戳进行比较会显示日期在时间戳之后java.sql.Timestamp是从java.util.Date创建的,为什么总是在它之前?,java,time,Java,Time,在一个bug之后,我注意到如果使用以毫秒为单位的构造函数从java.util.Date创建java.sql.Timestamp,则Date实例总是在时间戳之后。这是令人费解的,因为(a)before()的契约指定了严格的比较,(b)如果不相等,时间戳(因为它有纳秒)本身可能在日期()之后。但是结果是相反的,并且是可重复的(对于JDK1.6和1.7,使用不同的JVM时区)。比较两个日期是正确的,但是对一个日期调用before()或after()并给出Timestamp参数会产生意外的结果 下面的示
import java.util.Date;
import java.sql.Timestamp;
public class X extends Date {
public static void main(String[] args) {
Date d1 = new Date();
Date d2 = new Date(d1.getTime());
Timestamp t = new Timestamp (d1.getTime());
System.out.println ("date1 = " + d1 + " (" + d1.getTime() + ")" );
System.out.println ("date2 = " + d2 + " (" + d2.getTime() + ")" );
System.out.println ("timestamp = " + t + " (" + t.getTime() + ")" );
System.out.println ("d1 before d2: " + d1.before(d2));
System.out.println ("d1 after d2: " + d1.after(d2));
System.out.println ("d1 before ts: " + d1.before(t));
System.out.println ("d1 after ts: " + d1.after(t)); //why true?
}
}
样本输出:
C:\>\Java\jdk1.7.0_05\bin\java X
date1 = Tue Oct 30 10:15:59 EDT 2012 (1351606559812)
date2 = Tue Oct 30 10:15:59 EDT 2012 (1351606559812)
timestamp = 2012-10-30 10:15:59.812 (1351606559812)
d1 before d2: false
d1 after d2: false
d1 before ts: false
d1 after ts: true
最后一行是奇怪的一行
谢谢。如果您查看内部表示以及
after()
方法中比较的内容,您可以看到例如
millis = 1351607849957
您将获得一个日期
fastTime = 1351607849957
fastTime = 1351607849000
nanos = 957000000
以及带有
fastTime = 1351607849957
fastTime = 1351607849000
nanos = 957000000
由于所有的比较都是fastTime
部分,因此您可以观察到您的行为。
正如@user714965在上面指出的,您不应该将
时间戳
视为日期
java.sql的API文档中所说:
注意:此类型是一个java.util.Date
和一个单独的纳秒值的组合。java.util.Date
组件中只存储整数秒。分数秒-纳米-是分开的
(这与Keppil的回答一致)
它还说:
由于Timestamp
类和上述java.util.Date
类之间的差异,建议代码不要将Timestamp
值作为java.util.Date
的一个实例来查看。Timestamp
和java.util.Date
之间的继承关系实际上表示实现继承,而不是类型继承
这意味着您不应该将时间戳
视为java.util.Date
,如果您将它传递给java.util.Date.after()
(该方法需要一个java.util.Date
——您正在传递一个时间戳,将其视为java.util.Date
,此注释说您不应该这样做)
在标准Java库中,这当然是糟糕的设计。如果您需要处理日期和时间,请使用一个设计更好、功能更强大的库。使用调试器指出这一点。并提醒“[…]建议代码不要将时间戳值作为Java.util.Date的实例进行查看。”d1.compareTo(ts)
结果1
,表明存在1纳米级的差异或类似的东西。我相信这是一个bug,是的。找到它很好!仅供参考,非常麻烦的旧日期时间类,如,java.text.SimpleDateFormat
,现在被内置到java 8和更高版本中的类所取代。看。是的,我知道这些se差异(以及不兼容,尤其是equals())以及Joda,但我正在寻找这种奇怪行为的解释。请注意,您可以深入研究类的源代码,例如java.sql.Timestamp
,您可以在JDK安装目录中的文件src.zip
中找到它。