本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看 活动链接
Debug 笔记 <Java-将java.time.Instant转换为不带区域偏移的java.sql.Timestamp>
提问
在我正在开发的应用程序中,我需要将java.time.Instantobject转换为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对象吗?
回答
我将计算机的时区更改为欧洲/布加勒斯特进行了实验。这是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,我们可以看到现在比格林尼治标准时间06:16:32早了2小时,Instant即04:16:32 UTC。因此,该方法具有欺骗性,看起来像在起作用,但没有效果。
这显示了导致Java 8日期和时间类设计取代旧类的麻烦。
因此,解决您的问题的真正有效的解决方案可能是让自己拥有一个可以轻松接受Instant对象的JDBC 4.2驱动程序,从而避免Timestamp完全转换为JDBC 4.2驱动程序。
我不知道现在是否可以使用该功能,但我相信它会提供。
文章翻译自Stack Overflow :stackoverflow.com/questions/4…