我的J2EE应用程序部署在集群中,服务器可以位于多个时区。例如,一台服务器在EST中,另一台服务器在CST中。
考虑将请求发送到EST中的服务器并将日期和时间存储在数据库中的情况(没有时区)。还有另一个请求来检索相同的日期。但该请求可能会转到CST中的另一台服务器。
有没有办法确定哪个时区日期存储在数据库中?
PS:我正在使用Oracle / Java / Hibernate。
答案 0 :(得分:6)
没有。如果您存储没有时区的DATE
,则无法查询时区。
作为开发人员,您需要决定如何处理时区。请记住,您有3个时区:
如果洛杉矶的用户输入时间,巴黎的用户应该看到什么?
如果悉尼的用户执行操作,多伦多的用户应该看到什么操作时间戳?
在您回答这些问题(即定义您的要求)之前,解决方案/实施无法进行编码/验证。
正如评论中所提到的,基本上有两种处理时区的方法:
答案 1 :(得分:2)
当您使用数据类型DATE
或TIMESTAMP
时,您将无法获得有关时区的任何信息 - 除非您的应用确保数据时始终为某个时区(例如UTC)插入或更新。
Andreas声明并不完全正确,在Oracle数据库中你有三个时区:
数据库时区
您可以使用DBTIMEZONE
查询它。它仅与TIMESTAMP WITH LOCAL TIME ZONE
数据类型列相关,并定义存储格式。因此,如果数据库包含一个带有DBTIMEZONE
列的表并且该列包含数据,则无法更改数据库上的TIMESTAMP WITH LOCAL TIME ZONE
。请注意,这是 NOT 时区SYSDATE
和SYSTIMESTAMP
数据库服务器操作系统的时区
此时区与SYSDATE
和SYSTIMESTAMP
的结果相关。
会话的时区
您可以使用SESSIONTIMEZONE
查询它。它可能由您的Web应用程序服务器或您的客户端浏览器时区决定。 (我不是Web技术的专家)如果是胖客户端,可以在注册表或环境变量ORA_SDTZ
中设置。我不知道哪一个具有优先权以及当未定义其中任何一个时获得的值,它可能会因您的数据库提供程序和驱动程序而异。用户可以随时使用ALTER SESSION SET TIME_ZONE=...
日期类型TIMESTAMP WITH TIME ZONE
存储包含时区信息的时间。您可以将它们转换为客户端本地时区,或者根据您的要求填充插入或其他任何内容。您可以使用EXTRACT函数或转换为字符串时获得时区值,例如TO_CHAR(TS_VALUE, TZH:TZM)
或TO_CHAR(TS_VALUE, TZR)
。
日期类型TIMESTAMP WITH LOCAL TIME ZONE
还存储带有时区信息的时间。但是,它始终在客户端的当前会话时区中显示时间,您无法将其转换为任何其他时区(除非事先执行CAST)。因此,当您尝试使用TO_CHAR(TS_VALUE, 'hh24:mi:ss TZH:TZM')
值TIMESTAMP WITH LOCAL TIME ZONE
时,会出现错误!