将 TIMESTAMP WITH TIME ZONE 与 DATE 进行比较

Comparing TIMESTAMP WITH TIME ZONE to DATE

我需要将数据库生成的日期(列值默认为 SYSDATE)与记录时区的手写时间戳进行比较。这是我正在尝试的比较:

where trunc(updated, 'mi') >= to_timestamp_tz('2017-10-24 04:45 US/Pacific', 'YYYY-MM-DD HH24:mi TZR')

我假设转换为 TIMESTAMP WITH TIME ZONE 的字符串应该与 DATE 相当。但是,这仅在数据库位于我自己的时区时才有效。否则,我必须手动将外部时间戳转换为数据库时区。比如我是BST,数据库是EST,就得写:

where trunc(updated, 'mi') >= to_timestamp_tz('2017-10-24 04:45 US/Pacific', 'YYYY-MM-DD HH24:mi TZR')

其中04:45 = 10:45 - 6,6是BST和EST的差值。这看起来完全违反直觉,因为原始时间戳已记录在 PST 中,因此输入为 US/Pacific。有人可以解释为什么需要这种转换吗?如果有人提出更好的解决方案,我也将不胜感激。

您可以将 DATE 列转换为 TIMESTAMP WITH TIME ZONE 值,如下所示:

WHERE 
  FROM_TZ(CAST(TRUNC(updated, 'mi') AS TIMESTAMP), 
       (SELECT TO_CHAR(SYSTIMESTAMP, 'TZR') FROM dual)) >= to_timestamp_tz('2017-10-24 04:45 US/Pacific', 'YYYY-MM-DD HH24:mi TZR')

但反过来也可以,即将 TIMESTAMP WITH TIME ZONE 转换为数据库时区中的日期:

WHERE 
    TRUNC(updated, 'mi') >=
        CAST(TO_TIMESTAMP_TZ('2017-10-24 04:45 US/Pacific', 'YYYY-MM-DD HH24:mi TZR') AT TIME ZONE (SELECT TO_CHAR(SYSTIMESTAMP, 'TZR') FROM dual) AS DATE)

SYDATE 是在数据库服务器操作系统的时区中提供的 (NOT DBTIMEZONE) ,因此您必须使用 (SELECT TO_CHAR(SYSTIMESTAMP, 'TZR') FROM dual)或在适当时提供硬编码值。

如果任何用户 inserted/updated 任何 updated 使用他当前的本地时区,此方法将失败。在这种情况下,时区信息会丢失并且无法恢复。

如果您在任何 oracle 客户端中 运行 此查询,您还可以通过 运行

更改会话设置

ALTER SESSION SET TIME_ZONE ='BST';

当您更改会话时time_zone所有来自数据库列的日期值和不带时区传递的时间戳值都将转换为 BST。

因此它将确保比较发生在共同时区