Java 如何以字符串格式从Oracle数据库中收集操作系统的时区?(使用tz将日期迁移/转换为ts)

Java 如何以字符串格式从Oracle数据库中收集操作系统的时区?(使用tz将日期迁移/转换为ts),java,oracle,date,timezone,stored-functions,Java,Oracle,Date,Timezone,Stored Functions,我想更新一个数据库表,它使用date type来timestamp with timezonetype,以便旧日期获得正确的时区信息 简单的转换对我来说并不好,因为如果时区是UTC+2小时(UTC+1+1小时用于日光保存),并且我尝试将日期转换为带有时区的时间戳,则数据库表中的所有日期都与时区偏移量相同+2小时,无论是夏季还是冬季日期 我已经可以编写一个SQL查询,它可以确定日期是否在DaylightSave time中,如果我知道字符串格式的当前时区,例如“Europe/Berlin”。问题是

我想更新一个数据库表,它使用date type来
timestamp with timezone
type,以便旧日期获得正确的时区信息

简单的转换对我来说并不好,因为如果时区是UTC+2小时(UTC+1+1小时用于日光保存),并且我尝试将日期转换为带有时区的时间戳,则数据库表中的所有日期都与时区偏移量相同+2小时,无论是夏季还是冬季日期

我已经可以编写一个SQL查询,它可以确定日期是否在DaylightSave time中,如果我知道字符串格式的当前时区,例如“Europe/Berlin”。问题是dbtimezone和sessiontimezone也可以以其他格式存储(+02:00,CET等)。我无法以静态方式轻松设置当前sessiontimezone,因为全球多个地方的客户都有自己的数据库,但使用的是通用的更新脚本。 timestamp的Express方法也无能为力,因为它无法将偏移量映射到指定的时区

我见过一个解决方案,它使用java存储过程来获取操作系统的时区,而不是Oracles时区。不幸的是,我们使用的是Oracle12c,它包含一个较旧的JRE(我认为它是1.6版本)。因此,尽管Java1.8能够很好地处理时区和夏令时(它使用更新的tzmapping表),但它对我来说并不适用。我尝试过它,如果我从Netbeans运行测试,它会返回正确的时区ID(欧洲/柏林格式),但即使它被Oracle SQL开发人员SQLPlus(我们用于运行更新脚本)接受,它也只显示+02:00

我已经尝试使用JodaTime(为了被SQL*Plus接受,重新编译到Java 1.6中)。最新的JodaTimes在理论上使用了自己的映射表。我在StackOverflow上读到,如果它不能从
user.timezone
变量中收集时区,那么它将转向
java.util
,正如我所提到的,这是不好的。如果不成功,则使用UTC。但我不清楚为什么它不能从
user.timezone
systemm变量中获取时区。这可能是许可问题吗?
或者我怎么可能解决这个问题?谢谢大家!

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

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

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

标题中的问题

如何以字符串格式从Oracle数据库中收集操作系统的时区

这很容易回答。运行以下语句:

SELECT TO_CHAR(SYSTIMESTAMP, 'tzr') FROM dual;
但是我假设你有一个不同的问题,但是我不完全理解

当您有一列带有时区的时间戳时,时区信息可用。像
+02:00
这样的时区没有任何夏令时,无论是夏季还是冬季,它总是比UTC提前2小时。像
欧洲/柏林
CET
这样的时区适用夏令时

如果您有一个时间,例如
2018-06-22 10:00:00+02:00
,那么您根本不知道这是否意味着开启夏令时的欧洲/柏林非洲/开罗,总是比UTC提前+02:00小时-您无法检索此类信息

如果在
日期
(或
时间戳
)列中有数据,则您根本没有任何时区信息,因此在没有进一步信息的情况下,无法将这些值转换为带时区的
时间戳


在操作系统的时区中存储时间是毫无用处的。将它们存储在UTC中,或使用数据类型
时间戳和本地时区
。带有本地时区的
时间戳中的数据存储在
DBTIMEZONE
(建议设置为UTC,但实际上与您无关)中,并且始终且仅显示在当前用户
SESSIONTIMEZONE

中,我无法读取所有未格式化的文本,但如果我正确理解您的问题…-为什么不使用带有本地时区的
时间戳
数据类型,并使用它呢?在任何情况下:数据库服务器的时区(在创建或上次更改数据库时设置)在
DBTIMEZONE
中可用,而客户端时区在
SESSIONTIMEZONE
中可用。根据您的具体需要,您可以使用一个或另一个作为_TZ()
的第二个参数(第一个参数是您的日期,先转换为时间戳)。如果您要将问题文本格式化为更可读的格式,您将有更好的机会获得答案,并且不会因为问题不清楚而关闭问题。请参阅.Reading system property
user.timezone
,Java中的该属性不需要任何权限。您确定它的值正确吗?您可能需要使用
System.getProperty
System.setProperty
。后者可能只有在您在接触任何日期和时间类之前才有效。PS您可以将其作为Joda time的替代方案。它为您提供了Java 1.8
Java.time
的核心功能,并在Java 1.6上运行。我认为,如果我能够以“大陆/城市”格式获得DB服务器的当前时区,我将能够为最初没有此信息的日期计算正确的tz信息。我假设所有日期都保存在DB服务器的时间(区域)中,并且这和创建
SELECT TO_CHAR(SYSTIMESTAMP, 'tzr') FROM dual;