2012-02-04 33 views
4

我应该如何将我的“日期+时间”存储在PostgreSQL数据库中?如何独立于时区获取所有相同的日期和时间

这就是我想要达到的目标:

  1. 我怎么能有所有的(例如)2012年1月1日00:00:00当地时间在世界任何地方发生的条目?
  2. 根据UTC时间显示按日期排序的所有条目。 (2012年纽约新年除夕比伦敦新年更近)。

我应该如何存储我的数据?我已经读过PostgreSQL在内部存储所有时间(PostgreSQL documentation),所以我的用户时区实际上已经丢失。

我想我应该用型一列“时间戳无时区”:

  • 点1是容易的。
  • 并与类型为“String”的另一列我将存储时区的字符串(如:美国/纽约) 但随后,2点似乎还是很难做到....

我希望我明确。

编辑新的想法:我想用存储两个时间戳:一个无时区(1 OK)和一个带有时区(2 OK)

回答

1

是的,PostgreSQL在内部存储所有时间戳为UTC。对于timestamp with time zone,时区偏移量仅适用于将时间调整为UTC,但不会显式存储。

我不会存储时区字符串或更少的时区缩写(这些不是精确的)。这可能稍后需要昂贵的计算,因为你必须考虑夏令时和国际时间制度的其他古怪。

您可以存储时区间隔偏移量(需要12字节)或秒的数值量(需要4个字节作为整数)等我在此related answer演示。

或者像你已经提出的那样:除了UTC时间戳之外还存储本地时间戳(需要8字节)。这会让你的任务变得轻松。请看下面的演示::

-- 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为带时区或不带时区的时间戳提供了不同的结果。

0

我想你可以存储日期为一个字符串,并使用ISO 8601或RFC 2822,所以你也存储时区。 或者的确,对于更多的比较选项,将时间戳和时区存储在2个不同的列中。

+0

作为字符串存储日期/时间是一种非常肮脏的处事方式,应该避免 – Skuld 2012-02-07 16:29:09

+0

数据库中的日期/时间字段是不是一个字符串? 我同意你的查询比较,但如果不需要将它存储为ISO 8601字符串不应该是一个问题 – 2012-02-08 17:29:27

+0

除非postgresql做与其他数据库引擎非常不同的东西,否则,datetime永远不会存储为字符串(通常它是表示从过去的特定日期/时间定义的时间量的整数值) – Skuld 2012-02-10 16:43:53

相关问题