我需要从这种格式转换日期:
2002-10-10T12:00:00-05:00 (xs:XML中定义的dateTime)
到 Oracle日期。
我习惯在PL / SQL中使用它:to_date('date here','yyyymmdd'),有没有办法在保留时区信息的同时进行转换?
由于
答案 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。
分享并享受。