首页 > 解决方案 > Oracle 存储日期的 TIMESTAMP 数据类型是否根据本地时区进行调整?

问题描述

我有一个使用 Spring JDBC 将数据存储到 Oracle 的 java 应用程序。数据包括我们将来用来查询某些数据的时间戳/日期。

日期字段在 DDL SQL 文件中的定义如下:

JobExecution {
    START_TIME TIMESTAMP DEFAULT NULL ,
    END_TIME TIMESTAMP DEFAULT NULL 
...
}

更新这些字段的 Java 代码如下所示:

lastJobExecution.setEndTime(new Date(System.currentTimeMillis()));

new Date(System.currentTimeMillis())根据以下文档以 UTC 格式存储当前时间。的文档System.currentTimeMillis()说它返回以下内容:

当前时间与 UTC 1970 年 1 月 1 日午夜之间的差异,以毫秒为单位。

的文档Date说以下内容:

分配一个 Date 对象并将其初始化以表示自称为“纪元”的标准基准时间(即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。

参数: date - 自 1970 年 1 月 1 日 00:00:00 GMT 以来的毫秒数。另请参阅: System.currentTimeMillis()

但是,当我使用 SQL 开发人员连接到 oracle 数据库时,日期似乎是按照本地时间而不是 UTC 存储的。

问题 :

  1. Oracle 会TIMESTAMP根据当地时间调整日期吗?我在 Oracle 文档的任何地方都找不到明确写的。
  2. 如果是的话,处理这个问题的最佳方法是什么。一种方法是每次我从该表中读取数据时将其转换为 UTC。另一种方法可能是将其存储为 UTC 格式本身。

标签: javaoracle

解决方案


不,TIMESTAMP数据类型不存储任何时区信息。

请参阅日期时间数据类型文档。

Oracle 提供了两种支持时区的时间戳数据类型:

  • TIMESTAMP WITH TIME ZONE

顾名思义,它存储带有时区信息的时间戳。时区可以作为区域名称(例如Europe/Zurich)或 UTC 偏移量给出。请注意,您不能直接在此类列上创建索引。相反,Oracle 创建一个虚拟列,SYS_EXTRACT_UTC(<your column>)并在此虚拟​​列上创建索引。您可能需要相应地调整您的查询。

通常,当您使用时区时,一种常见的方法是将所有时间存储为 UTC 时间,然后客户端将其转换为本地时间。这完全由第二种数据类型提供:

  • TIMESTAMP WITH LOCAL TIME ZONE

在 a中,TIMESTAMP WITH LOCAL TIME ZONE所有值都存储在DBTIMEZONE(默认为 UTC),但值始终显示在当前用户会话时区中。

另请注意,所有值的比较(例如<, >, =, >=, <=TIMESTAMP WITH [LOCAL] TIME ZONE都是根据 UTC 值执行的。


推荐阅读