48

在我正在开发的应用程序中,我需要将java.time.Instant对象转换为java.sql.Timestamp. 当我创建Instant对象时:

Instant now = Instant.now();

我收到类似的东西2017-03-13T14:28:59.970Z。当我尝试创建Timestamp这样的对象时:

Timestamp current = Timestamp.from(now);

我收到类似的东西2017-03-13T16:28:59.970Z。结果相同,但额外延迟了 2 小时。有人可以解释为什么会发生这种情况并为我提供解决此问题的答案,而不会延迟吗?

当我这样创建时:

LocalDateTime ldt = LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC);
Timestamp current = Timestamp.valueOf(ldt);

一切正常,但我尽量避免转换。有没有办法只使用Instant对象来做到这一点?

4

5 回答 5

50

我将计算机的时区更改为欧洲/布加勒斯特进行实验。这是 UTC + 2 小时,就像您的时区一样。

现在,当我复制您的代码时,我会得到与您类似的结果:

    Instant now = Instant.now();
    System.out.println(now); // prints 2017-03-14T06:16:32.621Z
    Timestamp current = Timestamp.from(now);
    System.out.println(current); // 2017-03-14 08:16:32.621

输出在评论中给出。但是,我继续说:

    DateFormat df = DateFormat.getDateTimeInstance();
    df.setTimeZone(TimeZone.getTimeZone("UTC"));
    // the following prints: Timestamp in UTC: 14-03-2017 06:16:32
    System.out.println("Timestamp in UTC: " + df.format(current));

现在您可以看到Timestamp与我们一开始的真正一致Instant(只有毫秒没有打印,但我相信它们也在那里)。所以你做的一切都是正确的,只是感到困惑,因为当我们打印时,Timestamp我们隐含地调用了它的toString方法,而这个方法又会获取计算机的时区设置并显示该时区的时间。正因为如此,显示器才不同。

您尝试使用的另一件事LocalDateTime似乎可以工作,但它实际上并没有给您想要的东西:

    LocalDateTime ldt = LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC);
    System.out.println(ldt); // 2017-03-14T06:16:32.819
    current = Timestamp.valueOf(ldt);
    System.out.println(current); // 2017-03-14 06:16:32.819
    System.out.println("Timestamp in UTC: " + df.format(current)); // 14-03-2017 04:16:32

现在,当我们Timestamp使用 UTC打印时DateFormat,我们可以看到太早了 2 小时,04:16:32 UTC,而 UTC 时间Instant是 06:16:32。所以这个方法是骗人的,它看起来很有效,但实际上并没有。

这显示了导致设计 Java 8 日期和时间类以替换旧的类的麻烦。因此,真正解决您的问题的好方法可能是让自己获得一个可以轻松接受Instant对象的 JDBC 4.2 驱动程序,这样您就可以避免Timestamp完全转换为。我不知道你现在是否可以使用,但我相信它会的。

于 2017-03-14T06:27:48.907 回答
46
于 2018-11-27T21:42:46.387 回答
2

Instant always gives time in UTC whereas Timestamp gives time in your local zone. So if you are not concern about any specific time zone, you can use Instant. It's also a good practice to save records in UTC, so that your application remains unaffected in case it is deployed in any other timezone.

于 2021-04-21T10:38:30.843 回答
1

如果您想要当前时间戳为什么不使用以下功能,我已经在各种项目中使用过它并且效果很好:

public static Timestamp getTimeStamp()
{
    // Calendar information
    Calendar calendar       = Calendar.getInstance();
    java.util.Date now      = calendar.getTime();
    Timestamp dbStamp       = new Timestamp(now.getTime());
    return dbStamp;
}   

例子:

System.out.println( getTimeStamp() );

输出:2017-03-13 15:01:34.027

编辑

使用 Java 8 本地日期时间:

public static Timestamp getTimeStamp()
{
    return Timestamp.valueOf(LocalDateTime.now());
}   
于 2017-03-13T15:02:32.177 回答
0

在将记录保存到 SQL Server DB 期间,我遇到了同样的问题。我曾经 在UTCjava.sql.Timestamp.valueOf(String s)中获取时间戳

import java.time.Instant; import java.time.format.DateTimeFormatter; .... .... DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(UTC); String dateTime = dateTimeFormatter.format(Instant date); Timestamp timestamp = Timestamp.valueOf(dateTime);

这个对我有用。

于 2018-11-26T16:16:49.427 回答