我有一个类型为
added_at
的列 timestamp without time zone
。我希望它的默认值是当前日期时间但没有时区。函数 now()
也返回时区。
我该如何解决这个问题?
SELECT now()::timestamp;
转换会将
timestamptz
返回的 now()
转换为您时区中相应的 timestamp
- 由会话的 timezone
设置定义。这也是 标准 SQL 函数 LOCALTIMESTAMP
在 Postgres 中的实现方式。
如果您不在多个时区运营,那也没有问题。否则切换到
timestamptz
以获得 added_at
。有什么区别?
顺便说一句,这完全一样,只是更吵且更贵:
SELECT now() AT TIME ZONE current_setting('timezone');
你可以这样做:
SELECT now() AT TIME ZONE current_setting('TimeZone');
SELECT now() AT TIME ZONE 'Europe/Paris';
SELECT now() AT TIME ZONE 'UTC';
不确定这对于“added_at”列有什么意义。您几乎总是想要一个绝对时间戳(带时区的时间戳)而不是浮动时间戳。
编辑对以下几点的回应:
是的,应该使用带时区的时间戳(绝对时间),除非你有充分的理由不这样做。
客户端时区由
SHOW TimeZone
或 current_setting(...)
给出,如上所示。请花一些时间浏览一下手册 - 它们很好地涵盖了所有这些内容。
CURRENT_TIME 和 CURRENT_TIMESTAMP 传递带有时区的值; LOCALTIME 和 LOCALTIMESTAMP 提供没有时区的值。
2020 年新的原生答案
在 PostgreSQL 中,如果您只需要当前日期时间,可以通过调用
CURRENT_TIMESTAMP()
不带时区,以及秒字段中的小数位位于秒字段小数点之后?
(在 PostgreSQL v12.4 上测试)
然后使用这个:
SELECT CURRENT_TIMESTAMP(0)::TIMESTAMP WITHOUT TIME ZONE;
如果您将列的数据类型定义为
timestamp
(而不是timestamptz
),那么您可以存储不带时区的时间戳,在这种情况下,您不需要添加TIMESTAMP WITHOUT TIME ZONE
像这样:
CREATE TABLE foo (created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP(0))
在上面的函数中,传递 0 来去掉秒字段中的小数位。
如果您的应用程序不关心时区,您可以使用
SELECT LOCALTIMESTAMP
。
例如:
SELECT LOCALTIMESTAMP
-- Result: 2023-01-30 17:43:33.628952