如何计算两个Java java.sql.Timestamps之间的差异?

请包括nanos,否则它将是微不足道的:

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纳秒)。 这比它看起来更加狡猾。

我建议不要在没有实际测试代码或准备好工作代码示例的情况下发布答案:)

经过一个小时和各种unit testing,我想出了这个解决方案:

 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; } 

unit testing:

  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 ()); 

在什么单位? 你上面的差异将给出毫秒,Timestamp.nanos()返回一个int,它将是毫秒(百万分之一?)毫秒。你的意思是,例如

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

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

以mmyers代码为基础……

 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); } } 

(删除旧代码以缩短答案)

编辑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); } 

此代码通过了您的unit testing。