Преобразование даты XSD xs:dateTime в дату Oracle

Мне нужно преобразовать дату в следующем формате:

2002-10-10T12:00:00-05:00 (xs: dateTime, как определено в XML)

до даты Oracle.

Я привык использовать это в PL / SQL: to_date('date here', 'yyyymmdd'), есть ли способ преобразовать это, сохраняя информацию о часовом поясе?

спасибо

3 ответов


даты Oracle не имеют информации о часовом поясе. Вместо этого вам нужно использовать тип данных TIMESTAMP.

Он работает примерно так:

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>

обратите внимание, есть сложная проблема T в XSD-формате. Это бросает ORA-01858 исключение, потому что это недопустимый формат в Oracle. Я уверен, что есть обходной путь, но в настоящее время он ускользает от меня.


Ну, один обходной путь-применить функцию SUBSTR () sto split откройте две части метки времени, как показывает Боб. Но должен быть более элегантный способ.


это, вероятно, не квалифицируется как "элегантный", но поскольку это строка, мы можем использовать функцию подстановки, чтобы избавиться от раздражающего 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>

но учитывая все усилия Oracle вложили в XMLDB это довольно раздражает, что нет более аккуратного решения.


"Я не понимаю, как вы получаете -05:00."

In мой оригинальный образец я использую маску формата 'YYYY-MM-DD HH24:MI:SS-TZH:TZM'. Это интерпретирует - в часовом поясе, в качестве разделителя не знак "минус". Поэтому он вернулся +05:00. С тех пор я исправил свой образец кода, чтобы удалить эту последнюю черточку. Теперь часовой пояс правильно отображается как -05: 00. Извините за путаницу.


короткий ответ:

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.

С уважением, Грабить.


вот пример того, как преобразовать это в дату и метку времени с типами данных часового пояса. Обратите внимание, что с типом даты теряется информация о часовом поясе (в преобразовании из метки времени с часовым поясом):

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;

просто для удовольствия я добавил некоторый код в пример, чтобы вытащить часовой пояс из строки, а затем добавил часовой пояс в местное время, чтобы получить GMT/UTC.

поделиться и наслаждаться.