2009-02-24 36 views
10

请包括毫微秒,否则将是微不足道的:如何计算两个Java java.sql.Timestamps之间的差异?

long diff = Math.abs(t1.getTime() - t2.getTime()); 

[编辑]我想最精确的结果,所以没有双打;只有整数/长整数算术。此外,结果必须是积极的。伪代码:

Timestamp result = abs (t1 - t2); 

实例:

t1 = (time=1001, nanos=1000000), t2 = (time=999, nanos=999000000) 
-> diff = (time=2, nanos=2000000) 

是的,在的java.sql.Timestamp毫秒的时间和毫微秒帕是重复的,所以1001毫秒装置1秒(1000)和1毫它在time部分和nanos部分,因为1毫秒= 1000000纳秒)。这比看起来更狡猾。

我建议不要发布没有实际测试的代码或具有工作代码示例准备:)

+0

所以你是否有解决方案,你会发布,如果没有人得到它? – 2009-02-24 16:23:26

+0

根据时间戳源代码中的注释,millis部分实际上并没有在纳米中复制。相反,直到秒数存储在java.lang.Date的超类中,并且nanos提供所有其余的时间。 – Richard 2009-02-24 16:34:24

+0

@mmyers:我正在研究一个,但我希望有人有一个可行的例子来拯救我可怜的大脑......但是我应该猜到,没有人在谷歌没有关闭任何东西的时候,但是t1.getTime() - t2 .getTime() – 2009-02-24 16:46:17

回答

10

一小时,各个单元测试后,我想出了这个解决方案:

public static Timestamp diff (java.util.Date t1, java.util.Date t2) 
{ 
    // Make sure the result is always > 0 
    if (t1.compareTo (t2) < 0) 
    { 
     java.util.Date tmp = t1; 
     t1 = t2; 
     t2 = tmp; 
    } 

    // Timestamps mix milli and nanoseconds in the API, so we have to separate the two 
    long diffSeconds = (t1.getTime()/1000) - (t2.getTime()/1000); 
    // For normals dates, we have millisecond precision 
    int nano1 = ((int) t1.getTime() % 1000) * 1000000; 
    // If the parameter is a Timestamp, we have additional precision in nanoseconds 
    if (t1 instanceof Timestamp) 
     nano1 = ((Timestamp)t1).getNanos(); 
    int nano2 = ((int) t2.getTime() % 1000) * 1000000; 
    if (t2 instanceof Timestamp) 
     nano2 = ((Timestamp)t2).getNanos(); 

    int diffNanos = nano1 - nano2; 
    if (diffNanos < 0) 
    { 
     // Borrow one second 
     diffSeconds --; 
     diffNanos += 1000000000; 
    } 

    // mix nanos and millis again 
    Timestamp result = new Timestamp ((diffSeconds * 1000) + (diffNanos/1000000)); 
    // setNanos() with a value of in the millisecond range doesn't affect the value of the time field 
    // while milliseconds in the time field will modify nanos! Damn, this API is a *mess* 
    result.setNanos (diffNanos); 
    return result; 
} 

单元测试:在mmyers代码

Timestamp t1 = new Timestamp (0); 
    Timestamp t3 = new Timestamp (999); 
    Timestamp t4 = new Timestamp (5001); 
    // Careful here; internally, Java has set nanos already! 
    t4.setNanos (t4.getNanos() + 1); 

    // Show what a mess this API is... 
    // Yes, the milliseconds show up in *both* fields! Isn't that fun? 
    assertEquals (999, t3.getTime()); 
    assertEquals (999000000, t3.getNanos()); 
    // This looks weird but t4 contains 5 seconds, 1 milli, 1 nano. 
    // The lone milli is in both results ... 
    assertEquals (5001, t4.getTime()); 
    assertEquals (1000001, t4.getNanos()); 

    diff = DBUtil.diff (t1, t4); 
    assertEquals (5001, diff.getTime()); 
    assertEquals (1000001, diff.getNanos()); 

    diff = DBUtil.diff (t4, t3); 
    assertEquals (4002, diff.getTime()); 
    assertEquals (2000001, diff.getNanos()); 
3

在什么单位的答案?上面的diff将会给出毫秒,Timestamp.nanos()返回一个int值,它将以毫秒为单位(百万分之一?)表示。

(t1.getTime() + (.000001*t1.getNanos()) - (t2.getTime() + (.000001*t2.getNanos()) 

还是我错过了什么?另一个问题是你需要这样的精度水平吗? AFAIK JVM不能保证在这个级别上是精确的,我不认为这很重要,除非你确定你的数据源是精确的。

0

(旧的代码去除,以缩短答案)

编辑2:新代码:

public class ArraySizeTest { 
    public static void main(String[] args) throws InterruptedException { 
     Timestamp t1 = new Timestamp(System.currentTimeMillis()); 
     t1.setNanos(t1.getNanos() + 60); 
     Thread.sleep(20); 
     Timestamp t2 = new Timestamp(System.currentTimeMillis()); 
     t2.setNanos(t2.getNanos() + 30); 
     System.out.println(t1); 
     System.out.println(t2); 
     // The actual diff... 
     long firstTime = (getTimeNoMillis(t1) * 1000000) + t1.getNanos(); 
     long secondTime = (getTimeNoMillis(t2) * 1000000) + t2.getNanos(); 
     long diff = Math.abs(firstTime - secondTime); // diff is in nanos 
     System.out.println(diff); 
     System.out.println(Math.abs(t1.getTime() - t2.getTime())); 
    } 
    private static long getTimeNoMillis(Timestamp t) { 
     return t.getTime() - (t.getNanos()/1000000); 
    } 
} 

输出:

2009-02-24 10:35:15.56500006 
2009-02-24 10:35:15.59600003 
30999970 
31

编辑3:如果你喜欢返回时间戳的东西,请使用:

public static Timestamp diff(Timestamp t1, Timestamp t2) { 
    long firstTime = (getTimeNoMillis(t1) * 1000000) + t1.getNanos(); 
    long secondTime = (getTimeNoMillis(t2) * 1000000) + t2.getNanos(); 
    long diff = Math.abs(firstTime - secondTime); // diff is in nanoseconds 
    Timestamp ret = new Timestamp(diff/1000000); 
    ret.setNanos((int) (diff % 1000000000)); 
    return ret; 
} 
private static long getTimeNoMillis(Timestamp t) { 
    return t.getTime() - (t.getNanos()/1000000); 
} 

此代码通过您的单元测试。

1

大厦...

import java.math.BigInteger; 
import java.sql.Timestamp; 


public class Main 
{ 
    // 1s == 1000ms == 1,000,000us == 1,000,000,000ns (1 billion ns) 
    public final static BigInteger ONE_BILLION = new BigInteger ("1000000000"); 
    public static void main(String[] args) throws InterruptedException 
    { 
     final Timestamp t1; 
     final Timestamp t2; 
     final BigInteger firstTime; 
     final BigInteger secondTime; 
     final BigInteger diffTime; 

     t1 = new Timestamp(System.currentTimeMillis()); 
     Thread.sleep(20); 
     t2 = new Timestamp(System.currentTimeMillis()); 

     System.out.println(t1); 
     System.out.println(t2); 
     firstTime = BigInteger.valueOf(t1.getTime()/1000 * 1000).multiply(ONE_BILLION).add(BigInteger.valueOf(t1.getNanos())); 
     secondTime = BigInteger.valueOf(t2.getTime()/1000 * 1000).multiply(ONE_BILLION).add(BigInteger.valueOf(t2.getNanos())); 
     diffTime = firstTime.subtract(secondTime); 
     System.out.println(firstTime); 
     System.out.println(secondTime); 
     System.out.println(diffTime); 
    } 
} 
相关问题