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

Wil*_*ino 30 java timestamp calendar

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

这是重现问题的代码

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是转换的示例结果

BEFORE 2012-10-18 14:30:13.362001
AFTER 2012-10-18 14:30:13.362
Run Code Online (Sandbox Code Playgroud)

它失去了它的精确度.如何保持小数值不变?

Boh*_*ian 30

您设置的时间以毫秒为单位,但您的输入精度以微秒单位,因此您将失去任何精度超过毫秒的精度.

Calendar不支持比毫秒更精细的粒度.没有解决方法.

  • @William没有一个.见编辑的答案. (3认同)

Bas*_*que 8

java.time

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

这个新框架具有纳秒分辨率.这足以处理旧的java.util.Date值,Joda-Time值,都是毫秒.它足以处理一些数据库(如Postgres)使用的微秒.一些数据库如H2使用纳秒.所以java.time可以处理所有这些,或者至少所有主流情况.唯一的例外是利基科学或工程情况.

图片

使用Java 8,旧类获得了转换为/从java.time转换的新方法.在java.sql.Timestamp上使用new 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 );
Run Code Online (Sandbox Code Playgroud)