使用JAVA在DB中存储日期/时间信息?

时间:2017-07-28 21:01:35

标签: java oracle timestamp jodatime

存储日期/时间信息(以及一般时间戳)的最佳方法/方法是什么,以便可以在不同时区显示的信息?

我的想法是让数据库只保留指定格式的时间(如GMT或UTC)。当从DB读取数据时,将收集的任何日期/时间/时间戳数据转换为该区域的本地时间戳。

将数据插入数据库时​​。以下内容适用。

  
      
  1. 从用户界面收集时间作为字符串
  2.   
  3. 将时间转换为本地日期/时间表示(包含时区)
  4.   
  5. 将本地日期/时间转换为GMT(或UTC)
  6.   
  7. 以GMT / UTC格式保存到数据库
  8.   

我已经看过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代码。

Setting session timezone with spring jdbc oracle

1 个答案:

答案 0 :(得分:2)

我建议使用数据类型TIMESTAMP WITH LOCAL TIME ZONETIMESTAMP 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错误,但在某种程度上它是有道理的。