2010-08-23 9 views
6

Trzeba przekonwertować datę z tego formatu:Konwersja daty XSD xs: DATETIME do Oracle Data

2002-10-10T12: 00: 00-05: 00 (xs: dateTime zdefiniowane w języku XML)

na Data Oracle.

Jestem przyzwyczajony do używania tego w języku PL/SQL: to_date ("date here", "yyyymmdd"), czy istnieje sposób na konwersję tego, zachowując informacje o strefie czasowej?

Dzięki

+0

@ user412045: Twoje pytanie nie jest jasne. Czy chcesz przekonwertować to '2002-10-10T12: 00: 00-05: 00' na to' 20021010'? Co masz na myśli przez "przechowywanie informacji o strefie czasowej"? –

+0

Chcę konwertować 2002-10-10T12: 00: 00-05: 00 na datę Oracle. 20021010 był tylko przykładem. Przechowując informacje o strefie czasowej mam na myśli to, że chcę mieć możliwość pobrania pełnej daty. Dzięki – MoreCoffee

Odpowiedz

7

Daty Oracle nie zawierają informacji o strefie czasowej. Zamiast tego należy użyć typu danych TIMESTAMP.

To działa mniej więcej tak:

SQL> desc tz 
Name          Null? Type 
----------------------------------------- -------- ---------------------------- 
ID             NUMBER 
TS             TIMESTAMP(6) WITH TIME ZONE 
TNOW            TIMESTAMP(6) WITH TIME ZONE 

SQL> insert into tz 
    2 values (1 
    3   , to_timestamp_tz('2002-10-10 12:00:00-05:00' 
    4       , 'YYYY-MM-DD HH24:MI:SSTZH:TZM') 
    5   , systimestamp) 
    6/

1 row created. 

SQL> select * from tz 
    2/

     ID 
---------- 
TS 
--------------------------------------------------------------------------- 
TNOW 
--------------------------------------------------------------------------- 
     1 
10-OCT-02 12.00.00.000000 -05:00 
23-AUG-10 17.37.06.502000 +01:00 


SQL> 

Uwaga, nie jest trudne zagadnienie T w notacji XSD. To rzuca wyjątek ORA-01858, ponieważ nie jest to poprawny format w Oracle. Jestem pewna, że ​​istnieje obejście, ale obecnie ucieka mi.


Cóż, jednym z rozwiązań jest zastosowanie funkcji SUBSTR() sto podział otworzyć dwie części znacznika czasu, jak Bob pokazuje. Ale powinien istnieć bardziej elegancki sposób.


To prawdopodobnie nie kwalifikuje się jako „elegancki”, ale jako, że jest to ciąg możemy użyć funkcji podstawiania się pozbyć uciążliwego T:

SQL> insert into tz 
    2 values (2 
    3   , to_timestamp_tz(translate('2003-10-10T12:00:00-05:00', 'T', ' ') 
    4     , 'YYYY-MM-DD HH24:MI:SSTZH:TZM') 
    5   , systimestamp) 
    6/

1 row created. 

SQL> select * from tz 
    2/

     ID 
---------- 
TS 
--------------------------------------------------------------------------- 
TNOW 
--------------------------------------------------------------------------- 
     1 
10-OCT-02 12.00.00.000000 -05:00 
23-AUG-10 17.37.06.502000 +01:00 

     2 
10-OCT-03 12.00.00.000000 -05:00 
23-AUG-10 17.53.37.113000 +01:00 


SQL> 

Ale biorąc pod uwagę cały wysiłek Oracle mają wprowadzone do XMLDB jest dość denerwujące, że nie ma bardziej przejrzystego rozwiązania.


"Nie rozumiem, jak można dostać -05. 00"

W mojej oryginalnej próbce używam maski formatu 'YYYY-MM-DD HH24:MI:SS-TZH:TZM'. To interpretuje - w strefie czasowej jako separator, a nie znak minus. W rezultacie powrócił +05: 00. Od tego czasu poprawiłem próbkę kodu, aby usunąć ostatni kresk. Teraz strefa czasowa jest poprawnie wyświetlana jako -05: 00. Przepraszamy za jakiekolwiek zamieszanie.

+0

Dzięki! Ale kiedy wykonuję wybierz to_timestamp_tz (przetłumacz ("2003-10-10T12: 00: 00-05: 00", "T", ""), "RRRR-MM-DD HH24: MI: SS-TZH: TZM ") od dual; Otrzymuję 10-OCT-03 12.00.00.000000000 PM +05: 00 (mam otrzymać -05: 00 nie +05: 00)? – MoreCoffee

+0

Nie rozumiem, jak się masz -05: 00 .. – MoreCoffee

+0

Doskonały, dokładnie to, czego potrzebowałem – MoreCoffee

2

Oto przykład konwertowania tego na typy danych DATE i TIMESTAMP WITH TIME STONE. Zauważ, że z datą wprowadzić strefę czasową informacja jest tracona (w konwersji z TIMESTAMP WITH TIME ZONE):

declare 
    strDate  VARCHAR2(32767); 
    tzDate  TIMESTAMP WITH TIME ZONE; 
    dtDate  DATE; 
    nTimezone NUMBER; 
    dtDate_GMT DATE; 
begin 
    strDate := '2002-10-10T12:00:00-05:00'; 

    dtDate := TO_TIMESTAMP_TZ(SUBSTR(strDate, 1, 10) || 
          SUBSTR(strDate, 12, 8) || ' ' || 
          SUBSTR(strDate, 20, 6), 'YYYY-MM-DDHH:MI:SS TZH:TZM'); 
    tzDate := TO_TIMESTAMP_TZ(SUBSTR(strDate, 1, 10) || 
          SUBSTR(strDate, 12, 8) || ' ' || 
          SUBSTR(strDate, 20, 6), 'YYYY-MM-DDHH:MI:SS TZH:TZM'); 
    nTimezone := TO_NUMBER(SUBSTR(strDate, 20, 3)) + 
       (TO_NUMBER(SUBSTR(strDate, 24, 2))/60); 
    dtDate_GMT := dtDate - ((INTERVAL '1' HOUR) * nTimezone); 

    dbms_output.put_Line('dtDate=' || dtDate); 
    dbms_output.put_Line('dtDate=' || TO_CHAR(dtDate, 'YYYY-MM-DD HH24:MI:SS')); 
    dbms_output.put_line('tzDate=' || tzDate); 
    dbms_output.put_line('tzDate=' || TO_CHAR(tzDate, 'YYYY-MM-DD HH24:MI:SS TZH:TZM')); 
    dbms_output.put_line('nTimezone=' || nTimezone); 
    dbms_output.put_Line('dtDate_GMT=' || TO_CHAR(dtDate_GMT, 'YYYY-MM-DD HH24:MI:SS')); 
end; 

Tylko dla zabawy dodałem trochę kodu na przykład wyciągnąć strefę czasową z ciągu, a następnie dodano strefę czasową do czasu lokalnego, aby uzyskać GMT/UTC.

Udostępnij i ciesz się.

9

Krótka odpowiedź:

SQL> select to_timestamp_tz('2002-10-10T12:00:00-05:00','yyyy-mm-dd"T"hh24:mi:sstzh:tzm') 
    2 from dual 
    3/

TO_TIMESTAMP_TZ('2002-10-10T12:00:00-05:00','YYYY-MM-DD"T"HH24:MI:SSTZH:TZM 
--------------------------------------------------------------------------- 
10-OCT-02 12.00.00.000000000 PM -05:00 

1 row selected. 

Pozdrowienia, Rob.