PostgreSQL 提供两种存储时间戳的数据类型: 不带时区的 TIMESTAMP
和带时区的 TIMESTAMPTZ
。sql
TIMESTAMP
数据类型能够同时存储日期和时间,但它不存储时区。这意味着,当修改了数据库服务器所在的时区时,它里面存储的值不会改变。数据库
TIMESTAMPTZ
数据类型在存储日期和时间的同时还能正确处理时区。PostgreSQL 使用 UTC 值来存储 TIMESTAMPTZ
数据。在向 TIMESTAMPTZ
字段插入值的时候,PostgreSQL 会自动将值转换成 UTC 值,并保存到表里。当从一个 TIMESTAMPTZ
字段查询数据的时候,PostgreSQL 会把存储在其中的 UTC 值转换成数据库服务器、用户或当前链接所在的时区。服务器
TIMESTAMP
和 TIMESTAMPTZ
都使用8字节存储空间。以下所示:post
SELECT typname, typlen FROM pg_type WHERE typname ~ '^timestamp'; typname | typlen -------------+-------- timestamp | 8 timestamptz | 8 (2 rows)
重要提示,TIMESTAMPTZ
并不会存储时区,它只是了 UTC 值,而后会和当前时区进行转换。spa
首先,建立一个含有 TIMESTAMP
和 TIMESTAMPTZ
的表:postgresql
CREATE TABLE timestamp_demo (ts TIMESTAMP, tstz TIMESTAMPTZ);
接下来,将数据库服务器的时区设置为 America/Los_Angeles
:code
SET timezone = 'America/Los_Angeles';
顺便说一句,可使用 SHOW TIMEZONE
语句来显示当前时区:blog
SHOW TIMEZONE;
而后,插入一些示例数据:get
INSERT INTO timestamp_demo (ts, tstz) VALUES ( '2016-06-22 19:10:25-07', '2016-06-22 19:10:25-07' );
最后,查询:class
SELECT ts FROM timestampz_demo; ts | tstz ---------------------+------------------------ 2016-06-22 19:10:25 | 2016-06-22 19:10:25-07 (1 row)
再把时区设置为 America/New_York
:
SET timezone = 'America/New_York';
再查询一次,结果以下:
ts | tstz ---------------------+------------------------ 2016-06-22 19:10:25 | 2016-06-22 22:10:25-04 (1 row)
TIMESTAMP
类型字段的值不变,而 TIMESTAMPTZ
类型字段的值变成了当前时区下的时间。