Oracle DB Timestamp到Java时间戳:混乱

时间:2014-12-09 12:36:36

标签: java oracle timestamp gmt

我在几个小时内努力了解代码中TimeStamp的内容。

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

从DB中选择:

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?

根据documentationgetTime()

  

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

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

3 个答案:

答案 0 :(得分:4)

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

  

返回此Date对象表示的小时。该        返回值是一个数字(0到23)        表示包含或开始的当天内的小时        与此日期所代表的即时时间        对象,在本地时区解释。

因此toString正在使用您当地的时区,而getDate则没有。

答案 1 :(得分:3)

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

最重要的外卖应该是不要依赖Timestamp.toString因为它具有误导性。很久以前,Date(和Timestamp是一个子类)中的整个时区机制已被弃用。而是仅使用getTime()值并将其格式化为其他API,例如Java 8 Date / Time API。

更新

显然,toString()输出实际上是正确的输出,对我而言,这只是Java日期/时间处理错误的粗略目录的一小部分。您可能会从数据库中收到格式化字符串的时间戳,而不是毫秒值。 JDBC然后根据与Timestamp实例关联的时区将其解析为毫秒值,以使toString()的输出与数据库返回的输出匹配,并且实际的毫秒值是次要的。

答案 2 :(得分:0)

感谢上面的答案以及关于SO的参考资料。 This answer终于帮助我理解了在理解TimeStamps时出错的地方。

从链接的答案中进行评论

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

TimeStamp代表一个时刻。默认情况下,当前时区中的那个时刻。

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

但是,在读取生成的TimeStamp时,会假定从部署JVM读取的默认TimeZone。因此,读取的值是PST时区中的瞬间。实际UTC值比PST时间多8小时。因此,差异。

TimeStamp.getTime()返回UTC的毫秒数。 TimeStamp.toString()返回当前TimeZone中的时间表示。谢谢@marko-topolnik

举个例子,

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

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

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