我在将时间戳转换为 UTC 时遇到问题。
我们的系统时区是"欧洲/柏林"。目前的实际区域偏移量(因为现在还不是夏季)是+1。此区域偏移量将于 2017 年 3 月 26 日从 +1 更改为 +2。(冬季至夏季)。
如果我使用函数sys_extract_utc('2017.03.27 00:00')
则现在应用的偏移量将用于计算。所以结果是'2017.03.26 23:00',但我期望的结果是'2017.03.26 22:00'。
如何获得正确的结果?
你说
现在应用的偏移量用于计算
这并不完全正确。您的会话时区似乎设置为+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
提供的时间戳文本没有时区信息,因此它作为函数调用的一部分隐式转换为会话时区。偏移量不知道夏令时/冬时,因此不会(或可以)进行调整。如果您在 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