【问题标题】:Converting a XSD date xs:dateTime to an Oracle Date将 XSD 日期 xs:dateTime 转换为 Oracle 日期
【发布时间】:2010-08-23 15:32:46
【问题描述】:

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

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

Oracle 日期

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

谢谢

【问题讨论】:

  • @user412045:你的问题不清楚。您想将此2002-10-10T12:00:00-05:00 转换为此20021010 吗? “保留时区信息”是什么意思?
  • 我想将 2002-10-10T12:00:00-05:00 转换为 Oracle 日期。 20021010 只是一个例子。通过保留时区信息,我的意思是我希望能够在之后获取完整的日期时间。谢谢

标签: oracle date xsd timezone


【解决方案1】:

简短回答:

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.

问候, 抢。

【讨论】:

    【解决方案2】:

    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() 函数 s 来拆分时间戳的两个部分,如 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。如有任何混淆,请见谅。

    【讨论】:

    • 谢谢!!但是当我执行 select to_timestamp_tz(translate('2003-10-10T12:00:00-05:00', 'T', ' '), 'YYYY-MM-DD HH24:MI:SS-TZH:TZM')从双;我得到 10-OCT-03 12.00.00.000000000 PM +05:00(我应该得到 -05:00 而不是 +05:00)?
    • 完美,正是我所需要的
    • 如何处理烦人的T,用双引号括起来:'YYYY-MM-DD"T"HH24:MI:SSTZH:TZM'
    【解决方案3】:

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

    分享和享受。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多