2017-02-22 15 views
0

я следующую информацию о системе:Oracle SQL: Ручка с Time Переход на летнее

Я использую Oracle Database 10g
SysTimeStamp является UTC
SessionTimeZone является Europe/Athens
dbTimeZone является +03:00

Так , У меня есть столбециз таблицы tbl_1 со следующими датами:

date_1 
----------------- 
08.02.2017 10:00 
08.02.2017 11:00 
08.02.2017 12:00 
----------------- 

результаты, я хочу, как это:

date_2 
----------------- 
08.02.2017 13:00 
08.02.2017 14:00 
08.02.2017 15:00 

Для этого я использую:

SELECT TO_CHAR(date_1 + INTERVAL '3' HOUR, 'DD.MM.YYYY HH24:MI') as date_2 
FROM tbl_1 
WHERE date_1 >= TO_DATE('08.02.2017 10:00','DD.MM.YYYY HH24:MI') 
    AND date_1 <= TO_DATE('08.02.2017 12:00','DD.MM.YYYY HH24:MI') 

Моя проблема появляется, когда час от March и October происходит потому, что меняется в последнее воскресенье из March у нас есть 23 часа в день и в последнее воскресенье от October у нас есть 25 часов в день.

Из-за этого я должен изменить свой запрос в 4 раза/года (На летнее время, в зимнее время, когда у нас есть 23 часа в марте, когда мы имеем 25 часов в октябре)

Можете ли вы порекомендовать запрос в этом select, который решает эту проблему?

+0

Почему знак postgresql? Вы не используете Oracle? – jarlh

+0

Каким типом данных является столбец 'date_1', и в каком часовом поясе находятся значения, которые он содержит номинально? –

+0

@Alex Poole Тип 'date_1' -' DATE', а часовой пояс - «Европа/Афины» – BOB

ответ

1

Если у вас есть простая дата или метка времени без какой-либо вложенной информации часового пояса, вы можете сказать, Oracle, чтобы рассматривать его как в конкретной временной зоне с the from_tz() function. Затем вы можете преобразовать это значение, которое теперь имеет временную метку типа с зоной зоны, а не обычную временную метку, - в другую зону с at time zone datetime expression syntax, либо используя часовой пояс сеанса как «локальный», либо определенный часовой пояс :

alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS'; 
alter session set nls_timestamp_format='YYYY-MM-DD HH24:MI:SS'; 
alter session set nls_timestamp_tz_format='YYYY-MM-DD HH24:MI:SS TZR'; 
alter session set time_zone = 'America/New_York'; 

with cte (ts) as (
    select timestamp '2017-02-08 12:00:00' from dual 
) 
select ts, 
    from_tz(ts, 'UTC') as ts_utc, 
    from_tz(ts, 'UTC') at local as ts_local, 
    from_tz(ts, 'UTC') at time zone 'Europe/Athens' as ts_athens 
from cte; 

TS     TS_UTC     TS_LOCAL        TS_ATHENS       
------------------- ----------------------- ------------------------------------ --------------------------------- 
2017-02-08 12:00:00 2017-02-08 12:00:00 UTC 2017-02-08 07:00:00 AMERICA/NEW_YORK 2017-02-08 14:00:00 EUROPE/ATHENS 

Если вы начинаете с даты, то вы должны преобразовать его в метку времени перед вызовом from_tz():

with cte (dt) as (
    select cast(timestamp '2017-02-08 12:00:00' as date) from dual 
) 
select dt, 
    from_tz(cast(dt as timestamp), 'UTC') as ts_utc, 
    from_tz(cast(dt as timestamp), 'UTC') at local as ts_local, 
    from_tz(cast(dt as timestamp), 'UTC') at time zone 'Europe/Athens' as ts_athens 
from cte; 

DT     TS_UTC     TS_LOCAL        TS_ATHENS       
------------------- ----------------------- ------------------------------------ --------------------------------- 
2017-02-08 12:00:00 2017-02-08 12:00:00 UTC 2017-02-08 07:00:00 AMERICA/NEW_YORK 2017-02-08 14:00:00 EUROPE/ATHENS 

так тип данных ваших исходных значений date_1 вопросов, как это делает номинальный часовой пояс, который он должен представлять. Если это: готовая «метка времени с часовым поясом» или «метка времени с местным часовым поясом», тогда она уже имеет встроенную информацию о часовом поясе, так что вам вообще не нужна часть from_tz(). Если это дата, вам нужно преобразовать ее в метку времени.

Предполагая, что date_1 хранится в виде простой метки времени (возможно, подразумеваемой вашего интервала дополнение, но не по имени столбца и фильтров, используемых), и что это номинально UTC, вы могли бы сделать:

from_tz(date_1, 'UTC') at time zone 'Europe/Athens' 

. .. который даст вам результат с меткой времени с часовым поясом; или вы можете использовать local, чтобы полагаться на свой часовой пояс сеанса.Если `дата_1 хранится в виде даты вы бы добавить преобразование в отметку времени:

from_tz(cast(date_1 as timestamp), 'UTC') at time zone 'Europe/Athens' 

В демке, генерируя временные метки (не даты) в КТР, включая некоторые вокруг изменений ДСТ в течение этого года:

with tbl_1(date_1) as (
    select timestamp '2017-02-08 10:00:00' from dual 
    union all select timestamp '2017-02-08 11:00:00' from dual 
    union all select timestamp '2017-02-08 12:00:00' from dual 
    union all select timestamp '2017-03-23 12:00:00' + numtodsinterval(level, 'day') 
    from dual connect by level <= 4 
) 
select date_1, 
-- cast(from_tz(date_1, 'UTC') at time zone 'Europe/Athens' as timestamp) as date_2 
    to_char(from_tz(date_1, 'UTC') at time zone 'Europe/Athens', 
    'DD.MM.YYYY HH24:MI') as date_2 
from tbl_1 
order by date_1; 

DATE_1    DATE_2   
------------------- ---------------- 
2017-02-08 10:00:00 08.02.2017 12:00 
2017-02-08 11:00:00 08.02.2017 13:00 
2017-02-08 12:00:00 08.02.2017 14:00 
2017-03-24 12:00:00 24.03.2017 14:00 
2017-03-25 12:00:00 25.03.2017 14:00 
2017-03-26 12:00:00 26.03.2017 15:00 
2017-03-27 12:00:00 27.03.2017 15:00 

Вы можете видеть, что дополнительный час добавляется автоматически после смены часов 26 марта. Но результаты выходят за час для ваших данных образца февраля - так что ваши данные фактически не хранятся в формате UTC (но есть -01: 00, и вы можете изменить вызов from_tz(), чтобы это отразить), или ваши ожидаемые результаты неправильно.

+0

Спасибо за ваше время! Ваше объяснение очень помогает мне в том, что я делаю. – BOB

0

Вы можете подать иск в избранный:

select date_1 + case 
        when to_char(date_1 ,'MM') <= 3 then 2/24 -- Jan/Feb/Mar 
        when to_char(date_1,'MM') <= 10 then 3/24 -- Apr to Oct 
        else 2/24 -- Nov/Dec 
       end as date_2 
from tbl_1 

 Смежные вопросы

  • Нет связанных вопросов^_^