2008-11-13 8 views
5

क्या ओरेकल में उस दिन का चयन करने का कोई तरीका है जिस दिन मेरी लोकेल के लिए डेलाइट बचत चालू हो जाएगी?ओरेकल में, मैं उस तारीख का पता कैसे लगा सकता हूं जिस पर डेलाइट बचत समय शुरू होता है/समाप्त होता है?

कुछ अस्पष्ट इस के बराबर अच्छा होगा:

SELECT CHANGEOVER_DATE 
FROM SOME_SYSTEM_TABLE 
WHERE DATE_TYPE = 'DAYLIGHT_SAVINGS_CHANGEOVER' 
    AND TO_CHAR(CHANGEOVER_DATE,'YYYY') = TO_CHAR(SYSDATE,'YYYY'); -- in the current year 

संपादित करें: मैं एक समाधान है कि परिवर्तन जब कांग्रेस समायोजित कर देता है डीएसटी कानूनों की आवश्यकता नहीं होगी के लिए उम्मीद की गई थी, के रूप में वे 2007 पोस्ट समाधान में किया था होगा काम, यद्यपि।

उत्तर

3

हम किसी दिए गए वर्ष (2007 के बाद, अमेरिका) के लिए प्रारंभ और समाप्ति तिथियों की गणना करने के लिए निम्नलिखित दो फ़ंक्शंस का उपयोग करते हैं।

Function DaylightSavingTimeStart (p_Date IN Date) 
Return Date Is 
    v_Date  Date; 
    v_LoopIndex Integer; 
Begin 
    --Set the date to the 8th day of March which will effectively skip the first Sunday. 
    v_Date := to_date('03/08/' || to_char(p_Date,'YYYY') || '02:00:00 AM','MM/DD/YYYY HH:MI:SS PM'); 
    --Advance to the second Sunday. 
    FOR v_LoopIndex IN 0..6 LOOP 
     If (RTRIM(to_char(v_Date + v_LoopIndex,'DAY')) = 'SUNDAY') Then 
     Return v_Date + v_LoopIndex; 
     End If; 
    END LOOP; 
End; 

Function DaylightSavingTimeEnd (p_Date IN Date) 
Return Date Is 
    v_Date  Date; 
    v_LoopIndex Integer; 
Begin 
    --Set Date to the first of November this year 
    v_Date := to_date('11/01/' || to_char(p_Date,'YYYY') || '02:00:00 AM','MM/DD/YYYY HH:MI:SS PM'); 
    --Advance to the first Sunday 
    FOR v_LoopIndex IN 0..6 LOOP 
     If (RTRIM(to_char(v_Date + v_LoopIndex,'DAY')) = 'SUNDAY') Then 
     Return v_Date + v_LoopIndex; 
     End If; 
    END LOOP; 
End; 

शायद यह करने के लिए एक सरल तरीका है, लेकिन इन हमारे लिए काम किया है। निस्संदेह यह प्रश्न यह नहीं जानता कि आप कहां हैं, इसके लिए डेलाइट सेविंग टाइम मनाया जाता है या नहीं। इसके लिए आपको location data की आवश्यकता होगी।

1

यूनाइटेड स्टेट्स, डेलाइट सेविंग टाइम में मार्च के दूसरे रविवार को शुरुआत के रूप में के बाद 2007

मैं वर्षों के लिए, क्षेत्रों कि डीएसटी निरीक्षण के लिए परिभाषित है, और नवंबर में पहले रविवार को समाप्त हो रहा है, ऐसा नहीं लगता कि ओरेकल से यह जानकारी प्राप्त करने का एक आसान तरीका है, लेकिन मानक परिभाषा के आधार पर, आपको एक संग्रहित प्रक्रिया लिखने में सक्षम होना चाहिए जो Doomsday Algorithm का उपयोग करके शुरुआत और समाप्ति तिथि की गणना करता है।

1

ओरेकल आंतरिक ज्ञान का उपयोग करने का एक तरीका यहां है कि क्या टाइमज़ोन डेलाइट सेविंग टाइम देखता है या नहीं, इसकी शुरुआत और अंत निर्धारित करने के लिए। इसकी जटिलता और सामान्य अजीबता के अलावा, इसे दो समय क्षेत्र जानने की आवश्यकता होती है जब डेलाइट सेविंग टाइम प्रभावी नहीं होता है और जब यह अलग होता है तो अलग-अलग समय होते हैं। जैसे कि डेलाइट सेविंग टाइम होता है (मान लीजिए कि आपका डेटाबेस पैच के साथ अद्यतित है) में कांग्रेस के बदलावों के प्रति लचीला है, लेकिन समय-समय पर बंद होने वाले क्षेत्रीय परिवर्तनों के प्रति लचीला नहीं है। उन चेतावनियों के साथ, मेरे पास यही है।

ALTER SESSION SET time_zone='America/Phoenix'; 
DROP TABLE TimeDifferences; 
CREATE TABLE TimeDifferences(LocalTimeZone TIMESTAMP(0) WITH LOCAL TIME ZONE); 
INSERT INTO TimeDifferences 
(
    SELECT to_date('01/01/' || to_char(sysdate-365,'YYYY') || '12:00:00','MM/DD/YYYYHH24:MI:SS')+rownum-1 
    FROM dual CONNECT BY rownum<=365 
); 
COMMIT; 

ALTER SESSION SET time_zone='America/Edmonton'; 
SELECT LocalTimeZone-1 DaylightSavingTimeStartAndEnd 
FROM 
(
    SELECT LocalTimeZone, 
     to_char(LocalTimeZone,'HH24') Hour1, 
     LEAD(to_char(LocalTimeZone,'HH24')) OVER (ORDER BY LocalTimeZone) Hour2 
    FROM TimeDifferences 
) 
WHERE Hour1 <> Hour2; 

मैंने आपको बताया है कि यह अजीब था। कोड केवल परिवर्तन के दिन का आंकड़ा बताता है, लेकिन घंटे दिखाने के लिए बढ़ाया जा सकता है। वर्तमान में यह 09-MAR-08 और 02-NOV-08 लौटाता है। यह साल के समय के प्रति भी संवेदनशील है, इसलिए मुझे -365 ... + 365 करना पड़ा। सब कुछ मैं इस समाधान की सिफारिश नहीं करता, लेकिन जांच करना मजेदार था। शायद किसी और के पास कुछ बेहतर है।

2

अगले रविवार को पाने के लिए लूप करने के बजाय आप ऑरैक के अगले दिन (दिनांक, 'सूर्य') फ़ंक्शन का भी उपयोग कर सकते हैं।

0

यहां उपरोक्त का मेरा संस्करण है। इसका लाभ यह है कि इसे दूसरे 'वैकल्पिक सत्र सेट समय क्षेत्र' की आवश्यकता नहीं है, और इसे एप्लिकेशन से अधिक आसानी से उपयोग किया जा सकता है। आप संग्रहीत फ़ंक्शन बनाते हैं, और फिर आप बस उपयोग करते हैं: वैकल्पिक सत्र SET time_zone = 'एशिया/जेरूसलम'; GetDSTDates (2012,1) DSTStart, GetDSTDates (2012,2) DSTEnd, सत्र TimeZone TZ दोहरी से चुनें;

जो निर्दिष्ट वर्ष के लिए डीएसटी प्रारंभ तिथि, डीएसटी समाप्ति तिथि, टाइमज़ोन वापस कर देगा।

create or replace function GetDSTDates 
(
    year integer, 
    GetFrom integer 
) 
return Date 
as 
    cursor c is 
    select 12-to_number(to_char(LocalTimeZone at time zone '+00:00','HH24')) offset, 
    min(to_char(LocalTimeZone at time zone '+00:00','DD/MM/YYYY')) fromdate, 
    max(to_char(LocalTimeZone at time zone '+00:00','DD/MM/YYYY')) todate 
     from (
     SELECT cast((to_date('01/01/'||to_char(year)||'12:00:00','MM/DD/YYYYHH24:MI:SS')+rownum-1) as timestamp with local time zone) LocalTimeZone 
     FROM dual CONNECT BY rownum<=365 
     ) 
    group by 12-to_number(to_char(LocalTimeZone at time zone '+00:00','HH24')); 
    dstoffset integer; 
    offset integer; 
    dstfrom date; 
    dstto date; 
begin 
    offset := 999; 
    dstoffset := -999; 
    for rec in c 
    loop 
    if rec.offset<offset 
    then 
     offset := rec.offset; 
    end if; 
    if rec.offset>dstoffset 
    then 
     dstoffset := rec.offset; 
     dstfrom := to_date(rec.fromdate,'DD/MM/YYYY'); 
     dstto :=to_date(rec.todate,'DD/MM/YYYY'); 
    end if; 
    end loop; 
    if (offset<999 and dstoffset>-999 and offset<>dstoffset) 
    then 
    if GetFrom=1 
    then 
     return dstfrom; 
    else 
     return dstto; 
    end if; 
    else 
    return null; 
    end if; 
end; 
/
ALTER SESSION SET time_zone='Asia/Jerusalem'; 
select GetDSTDates(2012,1) DSTStart, 
     GetDSTDates(2012,2) DSTEnd, 
     SessionTimeZone TZ from dual; 
4

लेह Riffel के जवाब पर सुधार करने के लिए, यह एक ही तर्क के साथ बहुत सरल है:

Function DaylightSavingTimeStart (p_Date IN Date) 
Return Date Is 
Begin 
    Return NEXT_DAY(TO_DATE(to_char(p_Date,'YYYY') || '/03/01 02:00 AM', 'YYYY/MM/DD HH:MI AM') - 1, 'SUN') + 7; 
End; 

Function DaylightSavingTimeEnd (p_Date IN Date) 
Return Date Is 
Begin 
    Return NEXT_DAY(TO_DATE(to_char(p_Date,'YYYY') || '/11/01 02:00 AM', 'YYYY/MM/DD HH:MI AM') - 1, 'SUN'); 
End; 
संबंधित मुद्दे