根据类型的不同,Oracle 正在从哪个时区转换取决于 myTimestamp 的数据类型,存在一些问题。
带有时区的时间戳
It Just Works™。 a_horse_with_no_name 在这里有正确的答案。
带有本地时区的时间戳
它被隐式转换为 timestamp with time zone,然后 It Just Works™。同样,a_horse_with_no_name 就在这里。
时间戳
虽然它也被隐式转换为 timestamp with time zone,但默认分配的时区是 session 时区(而不是 数据库时区)。
- 对此的显式调用是
myTimestamp at local。
- 或者(而且很可能更好),您可以按照 Madhawas 所说的进行操作,并使用
from_tz 函数显式构建一个具有明确时区而非会话时区的值。李>
日期
如您所述,尝试在 date 之前执行上述任何操作都会失败:
-
myTimestamp at time zone 'UTC'
ORA-30084:具有时区修饰符的日期时间主数据类型无效
-
from_tz(myTimestamp, 'America/New_York')
ORA-00932:不一致的数据类型:预期 TIMESTAMP 得到 DATE
这里的解决方案是先将日期转换为时间戳:
select from_tz(cast(myTimestamp as timestamp), 'America/New_York') from tableA
示例脚本
以下脚本说明了该行为。请注意,在我的系统上,dbtimezone 是美国/中部,sessiontimezone 是 GMT-05:00。
我还使用to_char 来转换输出,因为我发现一些工具会以微妙的方式改变结果时间戳,特别是如果它们没有良好的时间戳支持(现在这种情况很少见,但仍然可能是个问题) .
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'
/
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'
/
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS TZR'
/
select dbtimezone
,sessiontimezone
,to_char(timestamp '2017-01-01 06:00:00') as ts
,to_char(timestamp '2017-01-01 06:00:00' at local) as ts_at_local
,to_char(timestamp '2017-01-01 06:00:00' at time zone dbtimezone) as ts_at_db
,to_char(timestamp '2017-01-01 06:00:00' at time zone sessiontimezone) as ts_at_session
from dual
/
我系统上的输出如下(为了便于阅读,重新格式化为柱状):
DBTIMEZONE US/Central
SESSIONTIMEZONE -05:00
TS 2017-01-01 06:00:00
TS_AT_LOCAL 2017-01-01 06:00:00 -05:00
TS_AT_DB 2017-01-01 05:00:00 US/CENTRAL
TS_AT_SESSION 2017-01-01 06:00:00 -05:00