Java 如何从Oracle获取时区ID而不是时区偏移量

Java 如何从Oracle获取时区ID而不是时区偏移量,java,oracle,timezone,Java,Oracle,Timezone,有没有办法从oracle获取时区id而不是时区偏移量? 当我执行时,从DUAL中选择SYSTIMESTAMP作为时区返回的结果是13-JAN-21 10.19.52.936031000 AM+05:30 当我使用rs.getObject(“TIMEZONE”,zoneDateTime.class)从Java中检索这个时,zoneDateTime对象的偏移量和分区ID都设置为+05:30 但我希望看到的是,从DUAL中选择SYSTIMESTAMP作为时区应返回04-JAN-21 02.40.50.

有没有办法从oracle获取时区id而不是时区偏移量? 当我执行
时,从DUAL中选择SYSTIMESTAMP作为时区返回的结果是
13-JAN-21 10.19.52.936031000 AM+05:30

当我使用
rs.getObject(“TIMEZONE”,zoneDateTime.class)
从Java中检索这个时,zoneDateTime对象的
偏移量和
分区ID都设置为
+05:30

但我希望看到的是,
从DUAL中选择SYSTIMESTAMP作为时区
应返回
04-JAN-21 02.40.50.000000000 PM ASIA/COLOMBO
,查询的Java ZoneDateTime应将
偏移量设置为
+05:30
,并将
zoneID
设置为
ASIA/COLOMBO


有没有一种方法可以在DB级或Java级进行设置?当前
DBTIMEZONE
设置为
+05:30

您可以使用
ALTER database
命令在数据库级别设置时区,如下所示:

alter database set time_zone = '+05:30';
请注意,这将在重新启动数据库后生效

shutdown immediate
startup
Oracle TZ_OFFSET()函数返回有效时区名称或SESSIONTIMEZONE或DBTIMEZONE函数名称相对于UTC的时区偏移量

TZ_OFFSET(value)
TZ_OFFSET()函数接受一个参数,该参数可以是有效的时区名称,例如“Europe/London”、SESSIONTIMEZONE或DBTIMEZONE的函数名,或者UTC的时区偏移量(它只返回自身)


结果将是+01:00

这是获取时区的方式

SELECT systimestamp AS DBTime,
       systimestamp at time zone 'Europe/London',
       systimestamp at time zone 'America/Sao_Paulo'from dual;


从某种意义上说,你运气不好
SYSTIMESTAMP
只返回操作系统报告的内容。时区是承载数据库的计算机系统的时区。它不是数据库时区(可能与数据库实际驻留的位置完全无关)或会话时区或诸如此类的东西。如果可以,您需要在db主机操作系统本身中进行更改

如果您确信托管您的数据库的系统位于斯里兰卡,那么您可以通过以下方式间接获得您想要的:

select systimestamp AT TIME ZONE 'ASIA/COLOMBO' from dual;

如果数据已经在Oracle SQL表中,并且必须转换为带时区的时间戳(例如,在同一表中创建的新列中),则不需要显式转到操作系统,也不需要使用Java或Oracle数据库本身以外的任何其他东西

您的问题不清楚您是否必须假定“日期”在服务器时区(您提到的“数据库”通常指服务器)或客户端时区(您提到的“会话”指客户端)。无论哪种方式:

update <your_table>
set <timestamp_with_time_zone_col> = 
            from_tz(cast<date_col> as timestamp, dbtimezone)
;

作为参考,您可以检查此链接,该链接在数据库操作系统的时区中返回,因此无法在数据库中更改

不要将数据库操作系统的时区与
DBTIMEZONE
混用,它们是不同的

另请注意,尽管(目前)具有相同的UTC偏移量,但亚洲/科伦坡时区与时区
+05:30
不同

时区
亚洲/科伦坡
考虑了夏令时,以防其适用,它还包括。例如,亚洲/科伦坡在2006年从UTC+06:00改为UTC+05:30。因此
TZ_OFFSET(时间戳'2020-01-01 12:00:00 Asia/Colombo')
返回的偏移量不同于
TZ_OFFSET(例如,时间戳'2000-01-01 12:00:00 Asia/Colombo')

时区
+05:30
始终在UTC前5:30


你的问题不是很清楚,你想得到什么?

正如我在问题中所说的,
从DUAL中选择DBTIMEZONE返回
+05:30
。但我希望这是
亚洲/科伦坡
。实际上,只要查询
从DUAL中选择SYSTIMESTAMP作为时区,我就不关心这个查询返回什么
retunrs
04-JAN-21 02.40.50.000000000 PM ASIA/COLOMBO
而不是
04-JAN-21 02.40.50.000000000 PM+05:30
systimestamp
报告托管数据库的计算机操作系统的时区。数据库时区与此无关。实际上,我将我的数据库时区设置为+00:00,由
从dual
选择dbtimezone确认
systimestamp
的时区为
-08:00
,这是我的机器上Unix操作系统的时区,位于美国西海岸。更改
DBTIMEZONE
systimestamp
没有影响,请参阅其他答案。很明显,不需要创建从偏移量到名称的转换函数,您就可以得到想要的东西。您可能希望尝试从v$timezone\u名称中选择。问题是有不少于8个时区具有该偏移量。看,我想从ZoneOffset中获取ZoneID。这就提供了另一种方式,即已经有两票领先。。。对于一个根本不回答问题的答案(事实上,似乎回答者一开始就不理解问题)-这是如何回答问题的?这是如何回答OP的问题的?已经有两票了。。。哇-请看一看这个:您需要正确设置Java时区,例如,使用环境变量
Java\u TOOL\u OPTIONS=-Duser.timezone=Asia/Colombo
当我查询
rs.getObject(“时区”)时,我希望得到
ZoneID
ZoneOffset
,ZonedDateTime.class
来自Java。假设列
TIMEZONE
具有
SYSTIMESTAMP
作为值,那么Java中的
ZonedDateTime
对象将
ZoneID
ZoneOffset设置为
+05:30
。但我希望
ZoneID
成为
Asia/Colombo
ZoneOffset
>在
ZoneDateTime
对象中为
+05:30
。写入的
SYSTIMESTAMP
select systimestamp AT TIME ZONE 'ASIA/COLOMBO' from dual;
update <your_table>
set <timestamp_with_time_zone_col> = 
            from_tz(cast<date_col> as timestamp, dbtimezone)
;
with
  my_table ( dt ) as ( 
    select to_date('2018-06-20 14:30:00', 'yyyy-mm-dd hh24:mi:ss') from dual 
  )
select dt,
       from_tz(cast(dt as timestamp), sessiontimezone) as ts_with_tz
from   my_table
;

DT                  TS_WITH_TZ                                       
------------------- -------------------------------------------------
2018-06-20 14:30:00 2018-06-20 14:30:00.000000000 AMERICA/LOS_ANGELES