Преобразование даты XSD xs: dateTime в дату Oracle - PullRequest
6 голосов
/ 23 августа 2010

Мне нужно преобразовать дату из этого формата:

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

в дата Oracle .

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

Спасибо

Ответы [ 3 ]

9 голосов
/ 16 сентября 2010

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

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.

С уважением, Роб.

7 голосов
/ 23 августа 2010

У дат 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>

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


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


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

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

2 голосов
/ 23 августа 2010

Вот пример того, как преобразовать это в типы данных DATE и TIMESTAMP WITH TIME ZONE.Обратите внимание, что при использовании типа DATE информация о часовом поясе теряется (в преобразовании из 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;

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...