Oracle 如何将任何时区的时间戳转换为数据库服务器时区的日期

Oracle how to convert Timestamp with any Timezone, to Date with database server Timezone

我有一个时间戳列,其中包含不同时区的数据。我需要 select 属于给定 'day' 数据库服务器时区的记录。

例如MY_TIMESTAMP列的数据为19-MAR-19 00.37.56.030000000 EUROPE/PARIS.
在数据库服务器位于 EUROPE/LONDON 的给定日期 19-MAR-19(也表示为 2019078)。 有什么办法可以让我的数据库服务器在 EUROPE/LONDON 时区时忽略此记录,但如果在 EUROPE/PARIS 时区,则记录为 selected.

请注意给定的时间戳是当天的第一个小时,EUROPE/PARISEUROPE/LONDON早一个小时

不幸的是,我尝试的查询忽略了时间戳的时区。

select * from MY_TABLE where to_number(to_char(CAST(MY_TIMESTAMP AS DATE), 'RRRRDDD')) between 2019078 AND 2019079

下面提到了将 TIMESTAMP 从已知时区转换为所需时区日期的方法,但我无法使用此逻辑,因为不知道源时区。

CAST((FROM_TZ(CAST(MY_TIMESTAMP AS TIMESTAMP),'EUROPE/PARIS') AT TIME ZONE 'EUROPE/LONDON') AS DATE)'

您不需要转换table数据;这样做不仅会增加工作量,还会停止使用该列上的任何索引。

Oracle 在比较值时将遵循时区,因此将原始 table 数据与特定日期进行比较 - 并将其转换为带时区的时间戳:

select * 
from MY_TABLE 
where MY_TIMESTAMP >= timestamp '2019-03-19 00:00:00 Europe/London'
and   MY_TIMESTAMP <  timestamp '2019-03-20 00:00:00 Europe/London'

或者如果您想以今天而不是固定日期为基础:

where MY_TIMESTAMP >= from_tz(cast(trunc(sysdate) as timestamp), 'Europe/London')
and   MY_TIMESTAMP <  from_tz(cast(trunc(sysdate) + 1 as timestamp), 'Europe/London')

或者如果您将日期作为 YYYYDDD 值传递(用数字参数名称替换固定值):

where MY_TIMESTAMP >= from_tz(to_timestamp(to_char(2019078), 'RRRRDDD'), 'Europe/London')
and   MY_TIMESTAMP <  from_tz(to_timestamp(to_char(2019079), 'RRRRDDD'), 'Europe/London')

使用 CTE 中的一些样本数据进行快速演示,为简单起见分为两个区域:

with my_table (id, my_timestamp) as (
  select 1, timestamp '2019-03-19 00:37:56.030000000 Europe/Paris' from dual
  union all
  select 2, timestamp '2019-03-19 00:37:56.030000000 Europe/London' from dual
  union all
  select 3, timestamp '2019-03-19 01:00:00.000000000 Europe/Paris' from dual
  union all
  select 4, timestamp '2019-03-20 00:37:56.030000000 Europe/Paris' from dual
  union all
  select 5, timestamp '2019-03-20 00:37:56.030000000 Europe/London' from dual
)

select * 
from MY_TABLE 
where MY_TIMESTAMP >= timestamp '2019-03-19 00:00:00 Europe/London'
and   MY_TIMESTAMP <  timestamp '2019-03-20 00:00:00 Europe/London'
/

        ID MY_TIMESTAMP                                      
---------- --------------------------------------------------
         2 2019-03-19 00:37:56.030000000 EUROPE/LONDON       
         3 2019-03-19 01:00:00.000000000 EUROPE/PARIS        
         4 2019-03-20 00:37:56.030000000 EUROPE/PARIS        

第一个示例行被排除在外,因为巴黎的 00:37 仍然是伦敦的前一天。第二行和第三行被包括在内,因为它们都在当天的凌晨 - 第三行刚刚进入。第四行被包括在内的原因与第一行被排除在外的原因相同 - 00:37 明天仍然是今天来自伦敦.第五个被排除在外,因为它是在伦敦午夜之后。