5

在一个错误之后,我注意到如果我从 java.util.Date 创建一个 java.sql.Timestamp,使用需要毫秒的构造函数,Date 实例总是 after() Timestamp。这很令人费解,因为 (a) before() 的合同规定了严格的比较,并且 (b) 如果不相等,时间戳,因为它有纳秒,它本身可能是 after() 日期。但结果是相反的且可重复的(JDK 1.6 和 1.7,具有不同的 JVM 时区)。比较两个 Dates 可以正常工作,但是在 Date 上调用 before() 或 after() 并给出 Timestamp 参数会产生意想不到的结果。

下面的示例代码有两个 Date 和一个 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

最后一行是好奇的。

谢谢你。

4

2 回答 2

7

如果您查看内部表示以及after()方法中比较的内容,您会看到例如

millis = 1351607849957

你得到Date一个

fastTime = 1351607849957

Timestamp一个

fastTime = 1351607849000
nanos = 957000000

由于所比较的只是fastTime零件,因此您会得到观察到的行为。正如@user714965 上面指出的那样,您不应该将 aTimestamp视为Date.

于 2012-10-30T14:40:52.417 回答
4

API 文档java.sql.Timestamp说:

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

(这与 Keppil 的回答一致)。

它还说:

由于Timestamp类与上述java.util.Date类之间的差异,建议代码不要将Timestamp值一般视为java.util.Date. Timestamp和之间的继承关系java.util.Date真正表示实现继承,而不是类型继承。

这意味着您不应将Timestamp其视为 a java.util.Date,如果您将其传递给,这就是您正在做的事情java.util.Date.after()(该方法需要 a java.util.Date- 您传入 a Timestamp,将其视为 a java.util.Date,此评论说您不应该这样做) .

这在标准 Java 库中当然是糟糕的设计。如果您需要处理日期和时间,请使用Joda Time,这是一个设计更好、功能更强大的库。

于 2012-10-30T14:41:44.967 回答