Oracle DB Timestamp to Java Timestamp : Confusion



我正在努力理解代码中TimeStamp是怎么回事。

Oracle DB 和 Java 应用程序都在 PDT 中

从数据库中选择:

select id, time_stamp from some_Table where id = '3de392d69c69434eb907f1c0d2802bf0';
3de392d69c69434eb907f1c0d2802bf0    09-DEC-2014 12.45.41.354000000 PM
select id, time_stamp at time zone 'UTC' from some_Table where id = '3de392d69c69434eb907f1c0d2802bf0';
3de392d69c69434eb907f1c0d2802bf0    09-DEC-2014 12.45.41.354000000 PM

Oracle数据库中的字段是TimeStamp的,因此不存储时区信息。

Timestamp dbTimeStamp = dbRecord.getLastLoginTime();
System.out.println(dbTimeStamp.toString()); // 2014-12-09 12:16:50.365
System.out.println(dbTimeStamp.getTime()); // 1418156210365 --> Tue Dec 09 2014 20:16:50 UTC?

根据文件,getTime()

返回自 1970 年 1 月 1 日 00:00:00 GMT 以来的毫秒数 由此时间戳对象表示。

为什么getTime()的响应中增加了8 hours (PDT - UTC)额外的时间?

TimeStamp.toString()内部使用javadoc声明的Date.getHours()

返回此 Date 对象表示的小时。这 返回值是一个数字(0 到 23( 表示一天中包含或开始的小时 以该日期表示的时刻 对象,以本地时区解释。

因此,toString使用的是您的本地时区,而getDate则没有。

这两者是一致的。getTime()方法为您提供绝对毫孔值,您选择以 UTC 解释该值。toString() 方法为您提供在关联时区中解释的相同毫秒值。因此,不是getTime()在增加时间,而是toString()在减去时间。这并没有真正记录下来,但这就是它的行为方式。

最重要的收获应该是不要依赖Timestamp.toString因为它具有误导性。Date中的整个时区机制(Timestamp是一个子类(很久以前就被弃用了。而是仅使用 getTime() 值,并由其他 API 对其进行格式化,例如 Java 8 日期/时间 API。

更新

显然,toString()输出实际上是正确的,对我来说,这只是Java日期/时间处理所有错误的厚目录中的一个小补充。您可能会以格式化字符串的形式从数据库中接收时间戳,而不是毫秒值。然后,JDBC 根据与Timestamp实例关联的时区将其解析为毫秒值,以便toString()的输出与数据库返回的内容匹配,并且实际毫秒值是辅助值。

感谢上面的答案和关于 SO 的参考资料。这个答案最终帮助我理解了我在理解时间戳时出错的地方。

从链接的答案中询问

Note: Timestamp.valueOf("2010-10-23 12:05:16"); means "create a timestamp with the given time in the default timezone".

时间戳表示时间的瞬间。默认情况下,当前时区中的该时刻。

写入数据库的时间戳是 UTC 时刻,即正在写入当前 UTC 时间。因此,无论应用程序部署在何处,写入数据库的值都是相同的时间戳。

但是,在读取生成的时间戳时,假定默认时区是从部署 JVM 读取的。因此,读取的值是太平洋标准时间时区的时刻。实际 UTC 值比太平洋标准时间多 8 小时。因此,差异。

TimeStamp.getTime()从 UTC 返回毫秒数。 TimeStamp.toString() 返回当前TimeZone中时间的表示形式。谢谢@marko-托波尔尼克

举个例子,

  • 数据库中的值:2014-12-09 12:16:50.365
  • 在时间戳中读取此值时,将在 PST 中2014-12-09 12:16:50.365时刻
  • 将其转换为 UTC,这将是2014-12-09 20:16:50

因此,解决方案是将TimeZone偏移量添加到从数据库中读取的值中,以获取UTC时间戳的时刻。

这里的关键是"TimeStamp is a time instant without TimeZone information. The timestamp is assumed to be relative to the default system TimeZone."——我花了很长时间才理解这一点。

最新更新