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

时间:2019-03-19 16:11:37

标签: oracle datetime timezone timestamp-with-timezone

我有一个timestamp列,其中包含具有不同时区的数据。我需要选择属于给定数据库服务器时区“天”的记录。

例如,如果MY_TIMESTAMP列中的数据为19-MAR-19 00.37.56.030000000 EUROPE/PARIS
并且在给定日期19-MAR-19(也表示为2019078)中,数据库服务器位于EUROPE/LONDON上。 有什么方法可以使如果我的数据库服务器处于EUROPE/LONDON时区,那么该记录将被忽略,但是如果它处于EUROPE/PARIS,则将选择该记录。

请注意,给定的时间戳记是一天中的第一个小时,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)'

1 个答案:

答案 0 :(得分:3)

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

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

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今天仍然是伦敦。并且排除了第五个,因为它是在伦敦的午夜之后。