Oracle中是否有一种平滑的方法来获取当前时刻(执行调用时)SESSIONTIMEZONE和DBTIMEZONE之间的数值差异?
例如:
SELECT SESSIONTIMEZONE, DBTIMEZONE FROM DUAL;
返回值:
+04:00 +07:00
因此,我需要某种函数,通过使用给定参数调用该函数,可以得到这两个值之间的差异。
对于上述实例:
SELECT get_numeric_offset(SESSIONTIMEZONE, DBTIMEZONE) FROM DUAL;
将返回-3(该符号至关重要)。
当然,我可以自己编写该函数,方法是使用字符串并对其进行解析,然后进行一些算术运算或执行类似的操作(我仍然认为这不是一个非常平滑的解决方案:
SELECT (
CAST(SYSTIMESTAMP AT TIME ZONE SESSIONTIMEZONE AS DATE) -
CAST(SYSTIMESTAMP AT TIME ZONE DBTIMEZONE AS DATE)
)*24
FROM DUAL;
也许我错过了一些东西,而Oracle实际上提供了一种方法来计算两个给定时区之间的差异?
最佳答案
有关使用SESSIONTIMEZONE的一些警告
您的第一个示例不是防弹的,因为可以将 session 时区设置为以下任意一个:
'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
在您的函数中解析“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
关于第二个解决方案
我想我更喜欢您的第二个解决方案。您可以通过使用
CURRENT_DATE
而不是CAST(SYSTIMESTAMP AT TIME ZONE SESSIONTIMEZONE AS DATE)
来缩短它,它们是等效的:SELECT (
CURRENT_DATE -
CAST(SYSTIMESTAMP AT TIME ZONE DBTIMEZONE AS DATE)
)*24
FROM DUAL;
从技术上讲,您甚至可以这样做!
SELECT (CURRENT_DATE - SYSDATE) * 24
FROM DUAL;
但实际上不能保证
SYSDATE
与DBTIMEZONE
处于同一时区。 SYSDATE
始终绑定(bind)到底层操作系统的时区,而一旦服务器启动,就可以更改DBTIMEZONE
。而且,当我在割头发时,我还应该提醒您,某些国家/地区使用的偏移量不是整数,例如,伊朗标准时间是
UTC+03:30
,缅甸时间是UTC+06:30
……我不知道您是否会曾经在您的生产环境中遇到过这种情况,但我希望您可以接受查询返回1.5
之类的信息的可能性。关于oracle - 如何获得DBTIMEZONE和SESSIONTIMEZONE之间的数值差异?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18072549/