将java.sql.Timestamp转换为java.util.Calendar而不失去精度

32

我正在尝试从数据库中获取时间戳值,将它们转换为日历,然后再转换回时间戳,但会失去精度。

以下是复现问题的代码:

import java.sql.Timestamp;
import java.util.Calendar;

public class Test {
    public static void main(String[] args)
    {
        Timestamp timestamp = new Timestamp(112, 10, 5, 15, 39, 11, 801000000);
        System.out.println("BEFORE "+timestamp.toString());
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp.getTime());
        timestamp = new Timestamp(calendar.getTimeInMillis());
        System.out.println("AFTER "+timestamp.toString());
    }
}

这是转换的示例结果

BEFORE 2012-10-18 14:30:13.362001
AFTER 2012-10-18 14:30:13.362

它失去了精确度。 我应该怎么做才能保持小数的值不变?


我在我的IDE中尝试过这个,但是没有得到这样的结果,每次都打印相同的内容 - Calendar calendar = Calendar.getInstance(); Timestamp timestamp = new Timestamp(new Date().getTime()); System.out.println("1 -> "+timestamp); // Thread.currentThread().sleep(1000); calendar.setTimeInMillis(timestamp.getTime()); timestamp = new Timestamp(calendar.getTimeInMillis()); System.out.println("2 -> "+timestamp); - Subhrajyoti Majumder
你能提供更多的上下文吗?这些时间戳是从哪里获取的,你是如何输出它们的? - axtavt
我已经更新了示例,之前的错误结果是我的错。 - William Wino
2个回答

31
你设置的时间单位是毫秒,但你的输入精度是微秒,所以你将会失去任何比毫秒更小的精度。
日历不支持比毫秒更细的粒度。没有变通办法。

那么也没有其他的类可以替代吗? - William Wino
@William JodaTime通常是常见的答案,但它也只支持毫秒。您的要求有点不寻常-考虑使用毫秒粒度(像其他人一样)。 - Bohemian

8

java.time

在Java 8及之后,我们现在有了一个解决方案:新的java.time框架已内置。由JSR 310定义,受Joda-Time启发,扩展了ThreeTen-Extra项目。

这个新框架具有纳秒的分辨率。足以处理旧的java.util.Date值、Joda-Time值,它们都是毫秒。它也足以处理一些数据库使用的微秒,比如Postgres。一些数据库,如H2使用纳秒。因此,java.time可以处理所有主流情况,唯一的例外是一些科学或工程领域的特殊情况。

Image

在Java 8中,旧类得到了转换为/from java.time的新方法。对于java.sql.Timestamp,使用新的toInstantfromInstant方法。Instant类包含从纪元开始的纳秒计数,1970年UTC的第一个时刻(基本上,详见类文档)。

Instant中,您可以获取一个ZonedDateTime对象。

java.sql.Timestamp ts = myResultSet.getTimestamp( 1 );
Instant instant = ts.toInstant();
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( zoneId );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接