我在将时间戳转换为UTC时遇到问题。
我们的系统时区是欧洲/柏林'。此时的实际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'。
如何获得正确的结果?
答案 0 :(得分:2)
你说
现在适用的偏移用于计算
这不太正确。您的会话时区似乎设置为+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
您可以通过修改操作系统环境变量自动执行此操作;如果没有,那么您可以在.login
或.glogin
安装文件中的客户端或(对于SQL * Plus)进行设置。
如果你从一个实际上有一个区域的值开始,即是一个带有时区数据类型的时间戳,那么会话时区并不重要:
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