2017-02-22 5 views
0

나는 다음과 같은 시스템 정보를 한 일광 절약 시간으로 처리 : 내가
SysTimeStamp 10g는 오라클 데이터베이스 UTC
SessionTimeZoneEurope/Athens
입니다을오라클 SQL :

를 사용하는 dbTimeZone 그래서 +03:00

입니다 , 나는 다음과 같은 날짜와 함께 tbl_1 테이블에서 열 date_1을 가지고 있습니다 :

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

내가 원하는 결과 617,451,515,는 다음과 같이이다 : 그 내용은

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

내가 사용 MarchOctober에서 시간부터 마지막 ​​일요일로 인해 변경 될 때

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 우리는 하루 23 시간, 마지막 주일은 October에서 우리는 하루에 25 시간을 가지고 있습니다. (우리는 월 23 시간 가지고 때 10 월 25 시간이있을 때, 겨울 시간에, 여름 시간) 때문에 내 쿼리 4 회/년을 변경해야이의

당신이 추천 할 수있는 이 select에있는 쿼리로이 문제를 해결할 수 있습니까?

+0

왜 postgresql 태그입니까? 오라클을 사용하지 않습니까? – jarlh

+0

'date_1' 열은 어떤 데이터 유형입니까? 그리고 명목상 들어있는 값은 어떤 표준 시간대입니까? –

+0

@Alex Poole'date_1'의 타입은'DATE'이고 시간대는'유럽/아테네'입니다. – BOB

답변

1

, 당신은 특정 시간대에에있는 것으로 취급 오라클을 말할 수있다 the from_tz() function. 그런 다음 일반 '타임 스탬프'가 아닌 'zone zone이있는 타임 스탬프'데이터 유형이 at time zone datetime expression syntax 인 다른 영역으로 변환 할 수 있습니다. 세션 시간대를 'local'또는 특정 명명 된 시간대로 사용하십시오 :

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을 사용하여 세션 시간대를 사용할 수 있습니다.DATE_1이 날짜로 저장되어있는 '경우에 당신은 타임 스탬프 변환을 추가 할 것 :

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

을 데모로, 올해의 DST 변경 주위에 일부 포함 CTE의 타임 스탬프 (안 날짜) 생성 :

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 

3 월 26 일에 시계가 변경된 후 추가 시간이 자동으로 추가되는 것을 볼 수 있습니다. 그러나 결과는 샘플 2 월 데이터에 대해 한 시간 씩 밖에 나오지 않으므로 데이터가 실제로 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