我认为IT的两个祸害之一是时间戳和时区(另一个是字符编码),其中一个人一次又一次地磕磕绊绊......
在这方面,我目前遇到的问题与存储到PostgreSQL数据库中的Java应用程序中的不同时间戳有关。
为了简单起见,假设有下表:
CREATE TABLE ts_test
(
id integer NOT NULL,
utc timestamp without time zone,
local timestamp with time zone,
CONSTRAINT pk PRIMARY KEY (id)
)
所以,我必须存储UTC时间戳和本地时间戳,在我的情况下是欧洲中部夏令时,所以目前UTC + 2。
进一步假设表中有2个条目,psql控制台上的输出如下(数据库以UTC格式运行):
# select id, utc, local, local-utc as diff from ts_test;
id | utc | local | diff
----+---------------------+------------------------+----------
1 | 2012-06-27 12:00:00 | 2012-06-27 12:00:00+00 | 00:00:00
2 | 2012-06-27 12:00:00 | 2012-06-27 14:00:00+00 | 02:00:00
(2 rows)
现在,出现了几个问题:
我原以为,第一行的本地“12:00:00 + 00”表示它是UTC的12:00,再次是CEST的14:00。但似乎(我的数据库管理员告诉我),第二行的本地“14:00:00 + 00”是14:00 CEST的正确值 - 由2小时的差异支持。 / p>
但是要通过sql insert生成第二行,我必须写
insert into ts_test (id, utc, local) values (2, '2012-06-27 12:00:00', '2012-06-27 16:00:00+02');
再次不支持预测。
所以,总结这个长期的问题 - 任何人都可以告诉我整个事情如何详细运作,输出应该是什么意思以及如何将本地时间戳正确地写入数据库?
答案 0 :(得分:1)
根据local
列的输出,您的SQL会话的时区设置为UTC
或GMT
,而不是您居住的时区。大概这是你的意思是:数据库以UTC格式运行。这是问题的根源,但我们试着详细说明。
db本身作为数据存储库没有时区,但每个SQL会话都有自己的时区。
当SQL会话请求它们时,timestamp without time zone
的值不会旋转到会话的时区,不会显示时间偏移,timestamp with time zone
的值将旋转到会话的时区,并显示此时区的时间偏移量。这是两者之间的差异。
时区永远不会存储在任何数据类型中,因为在读取值时,重要的是请求此值的SQL会话的时区。
将您的SQL时区设置为UTC
不是一个好主意,因为它与您问题的其他部分相矛盾:
所以,我必须存储UTC时间戳和本地时间戳,在我的情况下 是欧洲中部的夏季时间,所以目前UTC + 2
让SQL会话知道您的实时区域,它将按预期开始工作。如果不这样做,timestamp with time zone
基本上没用。
另请注意,将同一时间存储在utc timestamp without time zone
和local timestamp with time zone
中没有意义,因为您始终可以使用utc
获取:
SELECT local AT TIME ZONE 'UTC' FROM ts_test WHERE...
编辑:评论中的问题答案:
问:你是说如果我的时区设置为当地时间 会话,然后我应该看到例如... 14:00:00 + 02 in local for a utc值为... 12:00:00
是
问:从我的应用程序写入本地字段时, 重要的是哪个时区?
完全。
问:如何在JDBS会话中设置它?
我不知道JDBC,但在SQL级别,例如:
SET timezone='Europe/Berlin';
通常情况下,它会自动从环境中设置,但可以强制执行各种级别,包括postgresql.conf
。在会话中明确设置它将覆盖其他任何内容。
问:我能否以某种方式看到时间戳的原始值,以确保时间戳 显示时不仅仅是表示问题
我不知道怎么做,除了pageinspect在较低级别操作。