ZZa*_*ZZa 7 oracle timezone oracle10g oracle11g timezone-offset
在Oracle中是否有顺畅的方法来获取当前时刻(当我执行调用时)SESSIONTIMEZONE和DBTIMEZONE之间的数字差异?
例如:
SELECT SESSIONTIMEZONE, DBTIMEZONE FROM DUAL;
Run Code Online (Sandbox Code Playgroud)
返回:
+04:00 +07:00
Run Code Online (Sandbox Code Playgroud)
所以,我需要某种功能,通过调用给定参数,我得到这两个值之间的差异.
对于上面的例子:
SELECT get_numeric_offset(SESSIONTIMEZONE, DBTIMEZONE) FROM DUAL;
Run Code Online (Sandbox Code Playgroud)
将返回-3(标志是至关重要的).
当然,我可以自己编写这个函数,通过使用字符串并解析它们然后进行一些算术运算或做类似的事情(我仍然不认为这是一个非常流畅的解决方案:
SELECT (
CAST(SYSTIMESTAMP AT TIME ZONE SESSIONTIMEZONE AS DATE) -
CAST(SYSTIMESTAMP AT TIME ZONE DBTIMEZONE AS DATE)
)*24
FROM DUAL;
Run Code Online (Sandbox Code Playgroud)
也许我错过了一些东西,Oracle实际上提供了一种计算两个给定时区之间差异的方法?
Mik*_*ert 15
您的第一个示例不是防弹,因为会话时区可以设置为以下任一项:
'OS_TZ')'DB_TZ')'-05:00')'Europe/London')看看这里发生了什么:
SELECT SESSIONTIMEZONE, DBTIMEZONE FROM DUAL;
SESSIONTIMEZONE | DBTIMEZONE
+04:00 | +07:00
ALTER SESSION SET TIME_ZONE='Europe/Paris';
SELECT SESSIONTIMEZONE, DBTIMEZONE FROM DUAL;
SESSIONTIMEZONE | DBTIMEZONE
Europe/Paris | +07:00
Run Code Online (Sandbox Code Playgroud)
在你的函数中解析'Europe/Paris'字符串将会变得更加困难......你应该使用该TZ_OFFSET函数,以确保你总是得到相同的±HH:MM格式.
ALTER SESSION SET TIME_ZONE='Europe/Paris';
SELECT DBTIMEZONE, SESSIONTIMEZONE, TZ_OFFSET(SESSIONTIMEZONE) FROM DUAL;
DBTIMEZONE | SESSIONTIMEZONE | TZ_OFFSET(SESSIONTIMEZONE)
+07:00 | Europe/Paris | +02:00
Run Code Online (Sandbox Code Playgroud)
我想我更喜欢你的第二个解决方案.你可以用它CURRENT_DATE代替它来缩短它们CAST(SYSTIMESTAMP AT TIME ZONE SESSIONTIMEZONE AS DATE),它们是等价的:
SELECT (
CURRENT_DATE -
CAST(SYSTIMESTAMP AT TIME ZONE DBTIMEZONE AS DATE)
)*24
FROM DUAL;
Run Code Online (Sandbox Code Playgroud)
你在技术上甚至可以做到这一点!
SELECT (CURRENT_DATE - SYSDATE) * 24
FROM DUAL;
Run Code Online (Sandbox Code Playgroud)
但实际上,SYSDATE并不保证与时区相同DBTIMEZONE.SYSDATE始终绑定到底层操作系统的时区,而DBTIMEZONE一旦服务器启动就可以更改.
虽然我正在分裂头发,但我还应该提醒你,某些国家/地区使用的不是整数,例如伊朗标准时间UTC+03:30,缅甸时间是UTC+06:30......我不知道你是否会遇到这在你的生产环境中,但我希望你的查询返回类似于1.5... 的可能性你也可以.
您想要的是不可能的,因为时区不是固定的,而是随着时间的推移而变化.因此,您无法计算两个时区之间的差异,而只能计算在某个时间点有效的差异.
时区随着时间的推移而变化是很常见的.在TZ数据库中,每年都会对时区进行许多更改,例如,更改时区的位置或日间节能时间的开始,结束或差异的更改,或"随机"时间插入的闰秒.
因此,要计算偏移量,您还必须给出一个特定的时间点,您希望计算偏移量(即应该应用哪个版本的时区定义).
考虑到这一点,很明显,如何计算某个时间点的两个时区之间的差异:
select
(TIMESTAMP '2012-06-30 22:00:00 US/Pacific') - (TIMESTAMP '2012-06-30 22:00:00 Europe/Berlin') as diff
from
dual
;
DIFF
------------------------------
+000000000 09:00:00.000000000
Run Code Online (Sandbox Code Playgroud)
当您拥有此信息时,您必须决定您希望区别的精度.我故意选择了上面的日期,因为那天晚上插入了闰秒.所以可能会有一些时间点,你会得到不完全九小时但九小时一秒(或九小时减去一秒)的差异.
同样重要的是,您要插入确切的位置而不是其他时间戳信息.地点可以更改为不同的时区.因此,您必须指定两个位置和一个时间点才能获得正确的时区差异.
如果要整理差异,可以使用EXTRACT(HOUR FROM ...)和访问其组件EXTRACT(MINUTE FROM ...).如果想要在第二级进行舍入,可以使用以下技巧:
select
(to_number(to_char(sys_extract_utc(TIMESTAMP '2012-07-01 01:00:00 US/Pacific'), 'SSSSSFF3'))
- to_number(to_char(sys_extract_utc(TIMESTAMP '2012-07-01 01:00:00 Europe/Berlin'), 'SSSSSFF3')))/1000 as diff_s
from
dual
;
DIFF_S
----------
-54000
Run Code Online (Sandbox Code Playgroud)