将XSD日期xs:dateTime转换为Oracle Date

时间:2010-08-23 15:32:46

标签: oracle date xsd timezone

我需要从这种格式转换日期:

2002-10-10T12:00:00-05:00 (xs:XML中定义的dateTime)

Oracle日期

我习惯在PL​​ / SQL中使用它:to_date('date here','yyyymmdd'),有没有办法在保留时区信息的同时进行转换?

由于

3 个答案:

答案 0 :(得分:9)

一个简短的回答:

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.

此致 罗布。

答案 1 :(得分:7)

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()函数sto拆分打开时间戳的两个部分,如Bob所示。但应该有一种更优雅的方式。


它可能不符合“优雅”的条件,但因为它是一个字符串,我们可以使用替换函数来摆脱恼人的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 :(得分:2)

以下是如何将此转换为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;

为了好玩,我在示例中添加了一些代码,将时区拉出字符串,然后将时区添加到本地时间以获取GMT / UTC。

分享并享受。