Преобразование даты 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.
поделиться и наслаждаться.