我应该如何在PostgreSQL数据库中存储“date + times”?
这就是我想要实现的目标:
我应该如何存储数据?我已经读过PostgreSQL内部存储所有时间(PostgreSQL documentation),所以我的用户时区实际上已经丢失了。
我想我应该使用一个类型为“timestamp without timezone”的列:
我希望我很清楚。
编辑新想法:我认为存储两个时间戳:一个没有时区(1. ok),一个带时区(2. ok)
答案 0 :(得分:1)
是的,PostgreSQL在内部将所有时间戳存储为UTC。对于timestamp with time zone
,时区偏移仅适用于调整UTC时间,但不会显式存储。
我不会存储时区字符串,甚至不会存储时区缩写(这些都不准确)。这可以在以后需要昂贵的计算,因为你必须考虑夏令时和国际时间制度的其他奇怪之处。
你可以将时区偏移量存储为间隔(取 12字节)或数字秒数(取 4字节作为整数),就像我在此演示一样related answer
或者,就像您已经建议的那样:除了UTC时间戳之外还存储本地时间戳(需要 8个字节)。这将使您的任务变得简单。考虑以下demo ::
-- DROP TABLE tbl;
CREATE TEMP TABLE tbl (id int, ts_tz timestamp with time zone, ts timestamp);
INSERT INTO tbl VALUES
(1,'2012-1-1 00:00+01','2012-1-1 00:00+01')
,(2,'2012-1-1 00:00+02','2012-1-1 00:00+02')
,(3,'2012-1-1 00:01+03','2012-1-1 00:01+03')
,(4,'2012-1-1 00:02+04','2012-1-1 00:02+04');
查询问题1:
SELECT *
FROM tbl
WHERE ts = '2012-1-1 00:00'::timestamp;
id | ts_tz | ts
----+------------------------+---------------------
1 | 2012-01-01 00:00:00+01 | 2012-01-01 00:00:00
2 | 2011-12-31 23:00:00+01 | 2012-01-01 00:00:00
查询问题2:
SELECT *
FROM tbl
ORDER BY ts_tz;
id | ts_tz | ts
----+------------------------+---------------------
4 | 2011-12-31 21:02:00+01 | 2012-01-01 00:02:00
3 | 2011-12-31 22:01:00+01 | 2012-01-01 00:01:00
2 | 2011-12-31 23:00:00+01 | 2012-01-01 00:00:00
1 | 2012-01-01 00:00:00+01 | 2012-01-01 00:00:00
此解决方案的棘手部分可能是输入本地时间戳。只要在本地输入所有数据,这很容易。但是,如果你输入洛杉矶纽约的数据,就需要考虑。请使用AT TIME ZONE
construct:
SELECT ('2012-1-1 00:00+00' AT TIME ZONE 'America/New_York')::timestamp
, ('2012-1-1 00:00+00' AT TIME ZONE 'America/Los_Angeles')::timestamp
timezone | timezone
---------------------+---------------------
2011-12-31 19:00:00 | 2011-12-31 16:00:00
请注意我如何使用带时区的时间戳作为输入。对于带或不带时区的时间戳,AT TIME ZONE
会给出不同的结果。
答案 1 :(得分:0)
我猜您可以将日期存储为字符串并使用ISO 8601或RFC 2822,因此您还可以存储时区。 或者实际上,对于更多比较选项,将时间戳和时区存储在2个不同的列中。