存储日期/时间信息(以及一般时间戳)的最佳方法/方法是什么,以便可以在不同时区显示的信息?
我的想法是让数据库只保留指定格式的时间(如GMT或UTC)。当从DB读取数据时,将收集的任何日期/时间/时间戳数据转换为该区域的本地时间戳。
将数据插入数据库时。以下内容适用。
- 从用户界面收集时间作为字符串
- 将时间转换为本地日期/时间表示(包含时区)
- 将本地日期/时间转换为GMT(或UTC)
- 以GMT / UTC格式保存到数据库
醇>
我已经看过Joda Time套餐,并考虑过使用它。
人们解决此问题的正常方式是什么?我希望这不是太模糊 - 我在这里看到Oracle DB保存日期/时间,其时区似乎是本地的。
Ex:我得到以下内容:
SQL> SELECT EXTRACT(TIMEZONE_HOUR FROM SYSTIMESTAMP)||':'||
EXTRACT(TIMEZONE_MINUTE FROM SYSTIMESTAMP)
FROM dual;
Result => -5:0
非常感谢任何有关此问题的提示。
TIA
更新
完成以下工作:
SQL> ALTER DATABASE SET TIME_ZONE = 'UTC';
系统已经退回"
SQL> select dbtimezone from dual;
DBT
---
UTC
出于好奇,您如何插入数据库表以便考虑时区?使用TIMESTAMP类型作为列时出错:
SQL> create table shot (t timestamp);
Table created.
SQL> insert into shot values( '26-FEB-09 11.36.25.390713 AM Pacific/Auckland');
insert into shot values( '26-FEB-09 11.36.25.390713 AM Pacific/Auckland')
*
ERROR at line 1:
ORA-01830: date format picture ends before converting entire input string
SQL> insert into shot values( '26-FEB-09 11.36.25.390713 AM');
1 row created.
更新 同时在设置"会话时区"时添加旧帖子的链接在java / jdbc / Oracle中。如果我正确理解这一点,需要一个.jar文件来确保"会话时区"与"数据库时区相同"连接数据库时运行java代码。
答案 0 :(得分:2)
我建议使用数据类型TIMESTAMP WITH LOCAL TIME ZONE
。
TIMESTAMP WITH LOCAL TIME ZONE
的所有值都内部存储在DBTIMEZONE
中,在您的情况下为UTC(因此,一旦插入此数据类型的任何数据,就不能再更改DBTIMEZONE
)。选择此列后,当前用户会话时区SESSIONTIMEZONE
中显示始终的时间。因此,必须正确设置会话时区。
当您运行insert into shot values( '26-FEB-09 11.36.25.390713 AM Pacific/Auckland');
时出现错误,因为'26-FEB-09 11.36.25.390713 AM Pacific/Auckland'
是字符串 - 而不是时间戳!
您可以通过各种方式插入时间戳值,例如:
TIMESTAMP '2009-02-16 23:36:25.390713 Pacific/Auckland'
TO_TIMESTAMP_TZ('26-FEB-09 11.36.25.390713 AM Pacific/Auckland', 'DD-MON-RR HH:MI:SS.FF AM TZR')
FROM_TZ(TIMESTAMP '2000-03-28 18:00:00', 'Pacific/Auckland')
FROM_TZ(TIMESTAMP '2000-03-28 18:00:00', SESSIONTIMEZONE)
(尽管您可以跳过它,因为SESSIONTIMEZONE
是默认值)FROM_TZ(TO_TIMESTAMP('26-FEB-09 11.36.25.390713 AM', 'DD-MON-RR HH:MI:SS.FF AM'), 'Pacific/Auckland')
小心这些表达方式:
TIMESTAMP '1999-10-29 01:30:00' AT TIME ZONE 'Pacific/Auckland'
TO_TIMESTAMP('26-FEB-09 11.36.25.390713 AM', 'DD-MON-RR HH:MI:SS.FF AM') AT TIME ZONE 'Pacific/Auckland'
TIMESTAMP '1999-10-29 01:30:00' AT TIME ZONE 'Pacific/Auckland'
实际上意味着(FROM_TZ(TIMESTAMP '1999-10-29 01:30:00', 'SESSIONTIMEZONE') AT TIME ZONE 'Pacific/Auckland'
,因此您可能会遇到不必要的时间转移。
注意,当您使用TIMESTAMP
literal时,格式会在YYYY-MM-DD HH24:MI:SS
处修复
如果您未指定任何时区信息(例如TIMESTAMP '2009-02-16 11:36:25'
),则Oracle会将其视为当前用户会话时区SESSIONTIMEZONE
。
SYSTIMESTAMP
返回数据库服务器操作系统时区的当前时间,而不是DBTIMEZONE
- 虽然它们通常设置为相同的值。
CURRENT_TIMESTAMP
返回当前用户会话时区的当前时间。数据类型为TIMESTAMP WITH TIME ZONE
。
LOCALTIMESTAMP
也会返回当前用户会话时区的当前时间,但数据类型为TIMESTAMP
,而不是TIMESTAMP WITH TIME ZONE
。
另一个注意事项是,如果您有TIMESTAMP WITH LOCAL TIME ZONE
,则无法格式化此SELECT TO_CHAR(t, 'DD/MM/YYYY HH24:MI:SS ZTR') FROM shot
之类的输出,因为根据定义TIMESTAMP WITH LOCAL TIME ZONE
始终显示在当前用户会话时区和TZR
(即时区地区名称)没有任何意义。好吧,您可以将此视为Oracle错误,但在某种程度上它是有道理的。