如何在PostgreSQL中读取带有时区的时间戳?

时间:2019-01-01 23:01:26

标签: postgresql datetime

可以说我有一个带时区的时间戳记存储在我的PostgreSQL数据库中。像这样:

2003-04-12 04:05:06.814191 America/New_York

在读取此数据时,数据库会以GMT返回调整后的时间以标准化所有读取的时间戳,还是只是按原样返回它?

我问这个问题的原因是我创建了一个带有记录的表,其中每个记录都有一个timestamp列。我继续为不同的记录提供不同的时区。当我查询该表并尝试按timestamp列进行排序时,时区似乎对排序没有任何影响。这是设计使然吗?

我的结果示例:

1954-06-27 08:44:01.963454 Asia/Baghdad
1954-06-27 08:44:01.963454 GMT
1954-06-27 08:44:01.963454 Europe/Paris
1954-06-27 08:44:01.963454 Asia/Baghdad
1954-06-27 08:44:01.963454 America/New_York
1954-06-27 08:44:01.963454 America/New_York
1954-06-27 08:44:01.963454 America/New_York
1954-06-27 08:44:01.963454 GMT
1954-06-27 08:44:01.963454 America/New_York
1954-06-27 08:44:01.963454 America/New_York
1954-06-27 08:44:01.963454 Europe/Paris
1954-06-27 08:44:01.963454 America/New_York
1954-06-27 08:44:01.963454 Asia/Dhaka
1954-06-27 08:44:01.963454 GMT
1954-06-27 08:44:01.963454 GMT
1954-06-27 08:44:01.963454 Asia/Damascus
1954-06-27 08:44:01.963454 GMT
1954-06-27 08:44:01.963454 Asia/Damascus
1954-06-27 08:44:01.963454 America/New_York
1954-06-27 08:44:01.963454 Asia/Dhaka
1954-06-27 08:44:01.963454 Asia/Baghdad
1954-06-27 08:44:01.963454 Europe/Paris
1954-06-27 08:44:01.963454 Europe/Paris
1954-06-27 08:44:01.963454 Asia/Baghdad
1954-06-27 08:44:01.963454 Asia/Baghdad

所有这些记录的日期和时间都相同,并且不同的时区对顺序没有影响。

为了更清楚一点,我实际上是将这些时间戳记作为字符串存储在名为data的JSONb列中,其键为datetime,即:

data = {
    "datetime" : "2003-04-12 04:05:06.814191 America/New_York",
    .....
}

在排序和过滤期间,我将其强制转换为时间戳。像这样:

"(data->>'datetime')::timestamp"

1 个答案:

答案 0 :(得分:2)

PostgreSQL的“带时区的时间戳”类型实际上并未在每个记录中存储时区偏移量。它只是在内部将所有内容标准化为UTC。

“带时区的时间戳”的要点是,由于存储的值是在已知的时区中表示的,因此它明确地表示了特定的时间点。备选方案“没有时区的时间戳”是模棱两可的,因为它有时间,但没有说出它所在的时区-记录今天可能说中午,但是格林威治中午是中午吗?纽约中午?东京中午? “带时区”类型避免了该问题,因为该时区始终为格林威治。

(作为比较:我相信Oracle具有一个“带有时区的时间戳”,实际上在每个记录中存储一个偏移量,以及一个“带有本地时区的时间戳”,该规范将所有内容标准化到服务器的时区,以避免必须存储每个时区。 -记录偏移量。PostgreSQL的“带时区的时间戳”的名称与前者类似,但行为与后者类似。)


但是,听起来您实际上并没有在表中存储“带时区的时间戳”;您实际上是存储一个字符串,并作为timestamp的一部分强制转换为selecttimestamp关键字本身指的是“无时区”变体(SQL标准要求),而PostgreSQL文档说:

  

在已确定为timestamp without time zone的文字中,PostgreSQL将静默忽略任何时区指示。也就是说,结果值是从输入值中的日期/时间字段派生的,并且未针对时区进行调整。

我希望转换也一样,尽管如果是这样,还不清楚为什么您的输出(timestamp值)包含TZ名称。但是您可能想强制转换为timestamptz,或者可能创建一个单独的timestamptz列(以便可以为值建立索引)。


PostgreSQL documentation on date/time types是很好的参考。