将UTC时间中的DATE转换为DATE:sys_extract_utc的sysdate和systimestamp行为不同

时间:2018-11-16 07:21:05

标签: sql oracle

select sysdate from dual;    
15-NOV-2018 23:09:31

select cast(sysdate as TIMESTAMP) from dual;
15-NOV-18 11.07.47.000000000 PM

select sys_extract_utc(cast(sysdate as TIMESTAMP)) from dual;
15-NOV-18 05.40.35.000000000 PM

但是

select systimestamp from dual;
15-NOV-18 11.11.16.345959000 PM -08:00

select sys_extract_utc(systimestamp) from dual;
16-NOV-18 07.08.49.772214000 AM

进一步

select cast(sysdate as TIMESTAMP) at time zone 'UTC' from dual;
15-NOV-18 05.48.11.000000000 PM UTC

为什么我的数据库中sys_extract_utc(cast(sysdate as TIMESTAMP))sys_extract_utc(systimestamp)不同?
sys_extract_utc(systimestamp)给出的时间是正确的UTC时间,顺便说一句。

我的核心要求是将选择查询中具有DATE列的表中的数据转换为“ UTC时区中的DATE”。它当然不起作用(使用sys_extract_utcat time zone 'UTC'),可能是由于相同的原因,上述使用sysdate进行的转换也不起作用。

如果有帮助,dbtimezone为:

SELECT DBTIMEZONE FROM DUAL;
+00:00

1 个答案:

答案 0 :(得分:3)

函数SYS_EXTRACT_UTC仅适用于TIMESTAMP WITH TIME ZONETIMESTAMP WITH LOCAL TIME ZONE值。 DATETIMESTAMP不包含任何时区信息,因此SYS_EXTRACT_UTC对于DATETIMESTAMP值基本上是无用的。

运行时

SYS_EXTRACT_UTC(CAST(SYSDATE AS TIMESTAMP))

然后Oracle执行隐式强制转换并实际运行

SYS_EXTRACT_UTC(FROM_TZ(CAST(SYSDATE AS TIMESTAMP), SESSIONTIMEZONE))

SYSDATESYSTIMESTAMP返回数据库服务器操作系统所在时区的时间( DBTIMEZONE),而您的命令使用当前会话{{1} }

如果您坚持使用SESSIONTIMEZONE值,则可以使用以下值:

DATE

SYS_EXTRACT_UTC(FROM_TZ(CAST(SYSDATE AS TIMESTAMP), TO_CHAR(SYSTIMESTAMP, 'tzr'))) 为您提供数据库服务器操作系统的时区。

请注意,数据库服务器操作系统的时区通常不是TO_CHAR(SYSTIMESTAMP, 'tzr')之类的区域,而是由于夏令时而每年在Europe/Zurich+01:00之间进行两次更改。对于+02:00SYSDATE,这无关紧要,因为当前 UTC偏移始终是正确的。但是例如,如果我的表包含DATE值SYSTIMESTAMP,那么如果您在11月今天从上面运行查询,则会得到错误的结果。

如果您的数据库服务器利用夏时制,那么最好使用类似的查询

2018-08-01 12:00:00