2012-02-09 33 views
0

我寫了一個函數將日期轉換爲Unix時間戳。無論當前的DST狀態如何(例如,EST或EDT),該函數都會被寫入工作。這是函數:使用mod_plsql時無法獲取時區信息?

function unix_time_from_date(in_date in date) return number 
as 
    ut number  := 0; 
    tz varchar2(8) := ''; 
begin 
    -- Get the local timezone from the passed in date 
    -- Assuming the date supplied is for the local time zone 
    select 
    extract(
     timezone_abbr from cast(in_date as timestamp with local time zone) 
    ) 
    into tz 
    from dual; 

    -- Get the Unix timestamp 
    select 
    (new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (
    86400) 
    into ut 
    from dual; 

    return ut; 
end unix_time_from_date; 

此功能偉大的,當我從喜歡的JDeveloper客戶端執行它。從我收集的信息來看,這是因爲客戶端向第一個查詢提供時區信息。但是,如果我使用從mod_plsql頁面調用的過程中的函數,那麼出現錯誤ORA-01857: not a valid time zone。由於tz設置爲'UNK',因此new_time函數正在拋出此錯誤。

所以,我實現了一個變通針對此問題,像這樣:

function unix_time_from_date(in_date in date) return number 
as 
    ut number  := 0; 
    tz varchar2(8) := ''; 
begin 
    -- Get the local timezone from the passed in date 
    -- Assuming the date supplied is for the local time zone 
    select 
    extract(
     timezone_abbr from cast(in_date as timestamp with local time zone) 
    ) 
    into tz 
    from dual; 

    if tz = 'UNK' then 
    select 
     extract(
     timezone_abbr from cast(sysdate as timestamp with local time zone) 
    ) 
    into tz 
    from dual; 
    end if; 

    -- Get the Unix timestamp 
    select 
    (new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (
    86400) 
    into ut 
    from dual; 

    return ut; 
end unix_time_from_date; 

除此之外,這仍然失敗tz被設置爲'UNK'。有誰知道這裏會發生什麼?當從Oracle應用服務器進程調用該函數時,爲什麼我無法獲取本地時區縮寫?

回答

0

當調用它的會話沒有設置時區信息時,寫入的函數不起作用。因此,您需要明確指定源時區。下面的函數解決了這個問題(和糾正返回類型):

function unix_time_from_date 
    (
     in_date in date, 
     in_src_tz in varchar2 default 'America/New_York' 
    ) 
    return integer 
as 
    ut  integer  := 0; 
    tz  varchar2(8) := ''; 
    tz_date timestamp with time zone; 
    tz_stmt varchar2(255); 
begin 
    -- Get the local time zone abbreviation from the passed in date 
    tz_stmt := 'select systimestamp at time zone ''' || in_src_tz || ''' from dual'; 
    execute immediate tz_stmt into tz_date; 
    select 
    extract(timezone_abbr from tz_date) 
    into tz 
    from dual; 

    -- Get the Unix timestamp 
    select 
    (new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (86400) 
    into ut 
    from dual; 

    return ut; 
end unix_time_from_date; 

注意添加第二個參數的功能。此參數in_src_tz用於指示in_date參數所在的時區。in_src_tz的值應爲v$timezone_names表的tzname列中列出的時區之一。

另外,由於時區有多個縮寫,您不能簡單地選擇v$timezone_names表中的tzabbrev列的值。通過使用提取,您將得到DST的當前縮寫因子。

0

我想這不取決於你傳遞的日期參數。它可能取決於數據庫服務器運行的操作系統設置。在JDeveloper中,它可能從您的計算機(OS)時區設置中選取。嘗試在數據庫服務器上執行ssh並在腳本中運行前兩個查詢(對第一個查詢使用'DD-MON-YY'格式的實際日期)。兩者都應該返回'UNK'。 UNK(未知)很可能是因爲返回了多個時區。示例:在以下示例中,假設當前時區爲CST(美國中部時間)。

SELECT NEW_TIME(SYSDATE, 'CST', 'GMT') FROM DUAL --returns the date in London. 

SELECT TO_CHAR(NEW_TIME(SYSDATE, 'CST', 'GMT'),'HH24:MI') FROM DUAL --returns the time, based on the 24-hour clock, in London. 

SELECT TO_CHAR(NEW_TIME(SYSDATE + (14/24), 'PST', 'PST'),'DD-MON-YY HH24:MI') FROM DUAL --returns the date and time in China. 

SELECT TO_CHAR(NEW_TIME(SYSDATE + (diff/24), ‘GMT’, ‘GMT’),’DD-MON-YY HH24:MI’) FROM DUAL; --returns the date and time of your office. 
+0

通過OAS服務器上的sqlplus執行這些查詢,因爲提供網頁的用戶不會導致錯誤。 – 2012-02-10 13:59:42

0

您是否比較了本地計算機和服務器上的NLS_DATE_FORMAT?您可能會發現這種差異的組合,以及在日期被傳入時發生不正確轉換的可能性可能是您的問題。