Oracle DB时间戳到Java时间戳:混淆

Oracle DB时间戳到Java时间戳:混淆,java,oracle,timestamp,gmt,Java,Oracle,Timestamp,Gmt,我花了几个小时努力理解代码中的时间戳是怎么回事 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 '

我花了几个小时努力理解代码中的时间戳是怎么回事

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 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以来的毫秒数 由这个Timestamp对象表示

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

时间戳。toString()内部使用
Date.getHours()
,其javadoc声明:

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


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

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

最重要的一点是不要依赖于
Timestamp.toString
,因为这会产生误导。
Date
中的整个时区机制(以及
Timestamp
是一个子类)早就被弃用了。相反,只使用
getTime()
值,并由其他API(如Java8日期/时间API)对其进行格式化

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

多亏了上面的答案和相关参考。最终帮助我理解了我在理解时间戳方面的错误

从链接的答案中计算

Note: Timestamp.valueOf("2010-10-23 12:05:16"); means "create a timestamp with the given time in the default timezone".
时间戳表示时间的一个瞬间。默认情况下,当前时区中的该时刻

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

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

TimeStamp.getTime()
从UTC返回毫秒。
TimeStamp.toString()
返回当前
时区中的时间表示形式。谢谢@marko topolnik

举个例子,

  • 数据库中的值:
    2014-12-09 12:16:50.365
  • 在时间戳中读取此值时,PST中的瞬间为
    2014-12-09 12:16:50.365
  • 将其转换为UTC,即
    2014-12-09 20:16:50
因此,解决方案是将
时区
偏移量添加到从数据库读取的值中,以获得作为
UTC
时间戳的实例


这里的关键是“
时间戳是一个没有时区信息的时间瞬间。时间戳被认为是相对于默认的系统时区的。
”-我花了很长时间才理解这一点。

因为正如你从你引用的文本中所注意到的:
自1970年1月1日起,00:00:00 GMT
。注意那里的
GMT
?这是否意味着这里的绝对UTC时间是
2014年12月9日星期二20:16:50 UTC
(这与我掌握的信息不一致)?我还从数据库中添加了一个select。您如何确保Oracle的输出不适合其默认时区?我假设这是因为当我在时区“UTC”使用
执行select时,它给出了相同的结果。要确保这确实证明了这一点,请在时区“PDT”使用
重试。我还将尝试将时间戳转换为数字,以获得原始值。如果它确实证明了这一点,那么在解释JDBC端的值时可能会出现问题。是的,它返回与
PDT
相同的结果。这里可能有什么问题?这是否意味着这里的绝对UTC时间是2014年12月9日星期二20:16:50 UTC(数据库中字段的值)?似乎是这样。我不知道为什么SQL select语句以分钟和秒为单位显示差异。