postgresql 中的“date_part('epoch', now() at time zone 'UTC')”与“now() at time zone 'UTC'”时间不同

sir*_*ark 5 php postgresql timezone datetime

我正在为数据库(PHP/Postgresql)编写一个基于网络的前端,我需要在其中存储各种日期/时间。时间应始终以当地时间在客户端输入,并以当地时间显示。出于存储目的,我将所有日期/时间存储为整数(UNIX 时间戳)并标准化为 UTC。一个特定字段有一个限制,即不允许在将来填写时间戳,因此我尝试使用数据库约束来实现这一点...

CONSTRAINT not_future 
    CHECK (timestamp-300 <= date_part('epoch', now() at time zone 'UTC'))
Run Code Online (Sandbox Code Playgroud)

-300 是为了在浏览器和服务器之间的时间稍微不同步的情况下给予 5 分钟的余地。问题是,当提交当前时间时,这个约束总是失败。我做了测试,发现了以下内容。

在 PostgreSQL 客户端中:

SELECT now()-- 返回正确的本地时间

SELECT date_part('epoch', now())-- 返回 UTC 的 unix 时间戳(通过将值输入 PHP 中的日期函数进行测试,并更正其对我的时区的补偿)

SELECT date_part('epoch', now() at time zone 'UTC')-- 返回向西偏移两个时区的 unix 时间戳,例如我在 GMT+2,我得到一个 GMT-2 时间戳。

我显然已经发现,删除“at time zone 'UTC'”将解决我的问题,但我的问题是,如果'epoch'意味着返回一个unix时间戳,据我所知,它总是意味着UTC,为什么会UTC 时间的“纪元”是否需要更正?这是一个错误,还是我错过了这里定义/正常行为的一些内容。

Mil*_*dev 4

“now() at time zone 'UTC'”值是将当前时间移至 UTC,然后转换为TIMESTAMP NOT TIME ZONE

因此,您给“date_part”一个没有时区的时间戳(换句话说,未知时区),并期望收到它与已知时区的固定时间戳(“EPOCH”,1970-01-01 00)之间的秒数差异: 00:00 世界标准时间)。

Postgres 需要 TIMESTAMP WITH TIME ZONE 来计算这个。因此,它会将您的值转换为时区“UTC”(假设它位于您的时区)并计算差值。

就像是:

select ((now() at time zone 'UTC') at time zone '<your_time_zone>') at time zone 'UTC';
Run Code Online (Sandbox Code Playgroud)