我试图了解如何在Unix timestamp嵌入式文件数据库中存储UTC(即自{1970年以来HSQLDB / GMT时区中表示的自秒数以来的秒数)。但是,我还没有理解TZ处理如何与HSQL一起使用。
我的程序将在不同的区域使用,因此使用UTC是必须的。此外,我无法更改默认时区(与java.util.TimeZone.setDefault
一样),因为它将嵌入其他程序中,因此不应更改环境。
我的尝试 - 文档声明:
使用PreparedStatement或CallableStatement接口将datetime值发送到数据库时,Java对象将转换为ready或callable语句参数的类型。此类型可以是DATE,TIME或TIMESTAMP(带或不带时区)。时区位移是JDBC会话的时区。
所以我在数据库中使用了TIMESTAMP列(没有时区 - 默认值),并发出SET TIME ZONE INTERVAL '0:00' HOUR TO MINUTE
(将会话置于UTC TZ中),然后发出INSERT INTO TEST VALUES(?)
?是一个包含正确Unix值的Java Timestamp对象(GMT相关,测试正常)。
可悲的是,在这种情况下,数据库的SQL日志显示时间戳已恢复为我的本地时区(+2)。对于1442132237635的时间戳(UTC中的8H17,+ 2中的10H17),我们在日志中得到TIMESTAMP'2015-09-13 10:17:17.602000'
。错误的结果......似乎改变会话时区绝对没有任何影响(我已经尝试过+14,-14 ......没有变化)。然而,SET顺序正确执行 - 它出现在SQL日志中,TIMEZONE()的值随后发生变化。
其他尝试
我还尝试使用TIMESTAMP WITH TIME ZONE列,而不设置会话TZ。在这种情况下,数据库存储'本地时间+2',我可以从中提取正确的时间戳。这是边缘荒谬 - 这意味着HSQLDB驱动程序采用Java时间戳(UTC),将其正确解释为UTC,将其转换为JVM默认TZ,然后将其发送到DB。我不想要数据库中的TZ信息 - 不需要它。 (注意:改变会话TZ没有影响 - 发出的SQL命令总是与我的本地TZ ...让你想知道SET TZ命令的重点是什么)
将默认的JVM TZ更改为UTC有效,但如上所述我无法做到。
另外值得注意的是:this question似乎有关,但提供的答案基本上是破解我想避免的每个SQL命令......
我的问题
如何简单地将我的UTC Java时间戳存储在HSQLDB中? SET TIME ZONE订单的目的是什么?
感谢阅读。
答案 0 :(得分:1)
您的第一次尝试是正确的,并会返回正确的结果。
您的数据库位于UTC + 2时区。您正在连接,就像您是UTC时区的远程用户一样。
您声明的时间戳的日志存储没有错误。日志存储不是供数据库用户读取的。数据库将其日志存储在您所在位置的时区。下次读取日志时,它会根据您的数据库时区读取并解释它(与会话时区无关)。因此,日志中存储的时间为10:17,UTC时间为8:17。
使用TIMESTAMP WITHOUT TIME ZONE,数据库文件无法移动到其他时区,因为时间戳将根据新位置的区域进行解释。
SET TIME ZONE语句的作用是允许在存储数据时进行正确调整。它不会更改以前存储的数据。当然,如果时间存储为8:17,则无论何时以及在任何访问区域,都应将其读取为8:17。
为获得最佳便携性,请使用TIMESTAMP WITH TIME ZONE。即使您移动数据库文件,它存储和检索数据的方式也是正确的。