Oracle, как преобразовать метку времени с любым часовым поясом, в дату с сервером базы данных часового пояса - PullRequest
2 голосов
/ 19 марта 2019

У меня есть столбец меток времени, который содержит данные с разными часовыми поясами. Мне нужно выбрать записи, которые принадлежат данному «дню» часового пояса сервера базы данных.

Например, если данные в столбце MY_TIMESTAMP равны 19-MAR-19 00.37.56.030000000 EUROPE/PARIS.
И в данную дату 19-MAR-19 (также представленную как 2019078), где сервер базы данных находится на EUROPE/LONDON. Есть ли способ, чтобы, если мой сервер баз данных находился в EUROPE/LONDON часовом поясе, то эта запись игнорировалась, но если она была в EUROPE/PARIS, то эта запись была выбрана.

Обратите внимание , что указанная временная метка является первым часом дня, а EUROPE/PARIS опережает EUROPE/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 Ответ

3 голосов
/ 19 марта 2019

Вам не нужно конвертировать данные таблицы; это не только потребует больше усилий, но и остановит использование любого индекса в этом столбце.

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')

или если вам передаются даты в виде значений ГГГГДДД (замените фиксированное значение на числовое имя аргумента):

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 завтра все еще сегодня из Лондона. И пятый исключен, потому что в Лондоне после полуночи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...