sys_extract_utc 和 summer/wintertime 的问题

Problems with sys_extract_utc and summer/wintertime

我在将时间戳转换为 UTC 时遇到问题。

我们的系统时区是 'Europe/Berlin'。目前的实际 ZoneOffset(因为还不是夏季)是 +1。此 ZoneOffset 将于 2017 年 3 月 26 日从 +1 更改为 +2。 (冬季到夏季)。

如果我使用函数 sys_extract_utc('2017.03.27 00:00'),那么现在应用的偏移量将用于计算。所以结果是'2017.03.26 23:00',但我预期结果是'2017.03.26 22:00'。

怎样才能得到正确的结果?

你说

the offset which now applies is being used for the calculation

事实并非如此。您的会话时区似乎设置为 +01:00 偏移量而不是区域名称:

alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set TIME_ZONE = '+01:00';
select sys_extract_utc(timestamp '2017-03-27 00:00:00') from dual;

SYS_EXTRACT_UTC(TIM
-------------------
2017-03-26 23:00:00

提供的时间戳文字没有时区信息,因此作为函数调用的一部分,它被隐式转换为会话时区。偏移量不知道 summer/wintertime,因此不会(或不能)进行任何调整。如果您 运行 在 27 日之后查询,您会看到同样的结果。

如果您将会话时区设置为区域,那么您将获得正确的结果。

alter session set TIME_ZONE = 'Europe/Berlin';
select sys_extract_utc(timestamp '2017-03-27 00:00:00') from dual;

SYS_EXTRACT_UTC(TIM
-------------------
2017-03-26 22:00:00

您可以通过修改操作系统环境变量来自动执行此操作;如果没有,那么您可以在您的客户端或(对于 SQL*Plus)在 .login.glogin 安装文件中设置它。

如果您从一个实际具有区域的值开始,即是具有时区数据类型的时间戳,则会话时区无关紧要:

alter session set TIME_ZONE = '+01:00';
select sys_extract_utc(timestamp '2017-03-27 00:00:00 Europe/Berlin') from dual;

SYS_EXTRACT_UTC(TIM
-------------------
2017-03-26 22:00:00