java.sql.Timestamp构造函数如下所示:
public Timestamp(long time) {
super((time/1000)*1000);
nanos = (int)((time%1000) * 1000000);
if (nanos < 0) {
nanos = 1000000000 + nanos;
super.setTime(((time/1000)-1)*1000);
}
}
它基本上接受以毫秒为单位的时间,然后提取最后3位数字,使其成为纳米。因此,对于1304135631421的毫秒值,我将Timestamp.getnanos((作为421000000。这是一个简单的计算(最后加6个零(。。。似乎不是最佳的。
一个更好的方法可能是Timestamp构造函数,它接受以纳秒为单位的时间,然后计算出其中的纳秒值。
如果您运行以下程序,您将看到实际纳秒与Timestamp计算纳米生态的方法返回的纳秒之间的差异。
long a = System.currentTimeMillis();
for(;;){
long b = System.currentTimeMillis();
Timestamp tm = new Timestamp(System.currentTimeMillis());
System.out.println(tm.getTime());
System.out.println(tm.getNanos());
System.out.println("This is actual nanos" + System.nanoTime()%1000000000);
System.out.println("--------------------------");
if(b-a >= 1)
break;
}
所以所有关于时间戳的讨论都说它可以存储纳秒的时间,这似乎并不正确。。不是吗?
以毫秒为单位的时间并不代表以纳米为单位的时刻。再精确不过了。你应该用Timestamp#setNanos()
来设置真正的纳米。
long timeInMillis = System.currentTimeMillis();
long timeInNanos = System.nanoTime();
Timestamp timestamp = new Timestamp(timeInMillis);
timestamp.setNanos((int) (timeInNanos % 1000000000));
// ...
自从引入java.time.*
以来,java.sql.Timestamp
中有一种新的工厂方法:Timestamp.from(Instant.now())
将完成这项工作(精度为纳秒(。还有Timestamp.toInstant()
可以反过来转换它。
虽然这是一篇老文章,但我想补充一点,Timestamp的文档确实声明它"通过允许小数秒到纳奥秒的精度"。令人困惑的部分是"保持"。这一点一开始看起来很困惑,但如果理解正确,实际上并没有说明它保持纳奥秒价值它说它"保持"分数值,并允许它达到纳秒的"精度"。应从表述的角度理解精度总位数的。因此,它本质上意味着该部分实际上是分数(仍然是毫秒(,但乘以1000000表示为纳秒。
公认的答案(由一向乐于助人的巴鲁C(很好地总结了这一点。
我喜欢OpenJPA对TimestampHelper的实现。它使用静态初始化程序来跟踪调用之间经过的纳秒时间,以生成时间戳。