Oracle DB时间戳到Java时间戳:混淆
我花了几个小时努力理解代码中的时间戳是怎么回事 Oracle DB和java应用程序都在PDT中 从数据库中选择: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 '
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语句以分钟和秒为单位显示差异。