将TIMESTAMP与时区比较为DATE

时间:2017-10-25 11:12:20

标签: oracle time timezone timestamp-with-timezone

我需要将数据库生成的日期(列值默认为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。有人可以解释为什么需要这种转换吗?如果有人建议更好的解决方案,我也很感激。

2 个答案:

答案 0 :(得分:2)

您可以将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转换为DATE:

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)或如果合适,提供硬编码值。

如果任何用户使用其当前本地时区插入/更新任何updated,则此方法将失败。在这种情况下,时区信息会丢失,无法恢复。

答案 1 :(得分:0)

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

更改会话设置
  

ALTER SESSION SET TIME_ZONE =' BST';

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

因此它将确保在公共时区进行比较