从Oracle中选择UTC日期并在Java中转换为UTC

从Oracle中选择UTC日期并在Java中转换为UTC,java,spring,oracle,timestamp,jdbctemplate,Java,Spring,Oracle,Timestamp,Jdbctemplate,如果我调用我的应用程序: System.currentTimeMillis() 结果将是,比如说:1536842771599,,即:格林威治标准时间:2018年9月13日星期四12:46:11.599下午或我的本地时间:2018年9月13日星期四3:46:11.599下午GMT+03:00夏令时 如果在本地安装的Oracle数据库上执行以下操作,请选择: select CAST(sys_extract_utc(SYSTIMESTAMP) AS DATE) from dual; 我通过以下Jd

如果我调用我的应用程序:

System.currentTimeMillis()
结果将是,比如说:1536842771599,,即:格林威治标准时间:2018年9月13日星期四12:46:11.599下午或我的本地时间:2018年9月13日星期四3:46:11.599下午GMT+03:00夏令时

如果在本地安装的Oracle数据库上执行以下操作,请选择:

select CAST(sys_extract_utc(SYSTIMESTAMP) AS DATE) from dual;
我通过以下JdbcTemplate代码获得:

jdbc.queryForObject(sqlCommand, new Object[0], Timestamp.class);
结果如下:

在我看来,这已经是错误的,因为时间戳通常表示本地化的时间。此外,如果我打电话:

myResult.getTime()
为了得到长值,这将把我的时间(大约是下午12:46)转换为1536831971599,实际上是:格林尼治时间:2018年9月13日星期四上午9:46:11.599

显然这并不好,因为它比我的实际本地时间晚了2*GMT+03:00(6小时),比数据库的UTC时间晚了GMT+03:00(3小时)

我做错了什么?到目前为止,我唯一的结论是避免对数据库执行sys\u extract\u utc,让数据库返回本地时间,当我调用Timestamp实例上的getTime时,本地时间将转换为utc时间

对此有何解释

附言。 基于java.sql.Timestamp是UTC的答案,我附上了调试器显示给我的屏幕截图,这是错误的,因为它认为UTC的结果是GMT+03:00。所以,它显示我的时间是8.26+03:00。我的当地时间是11点26分。如果我在这个时间戳实例上调用getTime,我将得到一个长值,如果我输入该值,那么我将得到2018年9月14日星期五8:26:06 AM GMT+03:00 DST或2018年9月14日星期五5:26:06 AM,这正好比我实际拥有的UTC晚3小时

p.S.2 我使用SpringJDBC4.2.5-RELEASE。无法使用Instant,它抛出无法将时间戳转换为Instant的异常,因为它需要从数字派生的内容。不幸的是,我现在无法更改这个JDBC,甚至是版本

tl;博士 你误解了课堂

  • java.sql.Timestamp
    始终表示UTC中的一个时刻
  • 几年前取代了
    时间戳
仅使用
即时
,切勿使用
时间戳

Instant
可怕的
java.sql.Timestamp
类现在已经被java.time类,特别是
Instant
过时了

Instant.now()  // Capture the current moment in UTC. 
JDBC4.2 从JDBC4.2开始,我们可以直接与数据库交换java.time对象。无需再次使用可怕的
日期
日历
或java.sql类

找回

Instant instant = myResultSet.getObject( … , Instant.class ) ;
插入

myPreparedStatement.setObject( … , instant ) ;
时间戳通常表示本地化的时间

不对。
java.sql.Timestamp
表示UTC中的一个时刻,根据定义总是UTC。同样,
Instant
也代表UTC中的一个时刻。这两个类别都表示自1970年第一个UTC时刻以来的计数


关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

该项目现已启动,建议迁移到类

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要
java.sql.*

从哪里获得java.time类

  • 、和更高版本-标准Java API的一部分,带有捆绑实现。
    • Java9添加了一些次要功能和修复
    • 大多数java.time功能都在中向后移植到Java6和Java7
    • 更高版本的Android捆绑包实现了java.time类

    • 对于早期的Android(感谢您如此详细的解释!不过,我不明白为什么在执行了我上面编写的Oracle SQL之后,Timestamp的构造函数中出现了值1536831971599,而不是1536842771599。基于文档系统。currentTimeMillis()返回UTC,我也从Oracle UTC中选择。为什么值与我所在的时区(即GMT+03:00)完全不同?我更新了问题,也许这会澄清我的困惑。谢谢!