“date_part('epoch',now()在时区'UTC')”与postgresql中时区'UTC'的“now()不同时”

时间:2010-04-11 23:27:23

标签: php postgresql datetime timezone

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

CONSTRAINT not_future 
    CHECK (timestamp-300 <= date_part('epoch', now() at time zone 'UTC'))

如果浏览器和服务器之间略有不同步的时间,-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时间戳。

我已经明白,放弃“在时区'UTC'”将解决我的问题,但我的问题是,'epoch'是否意味着返回一个unix时间戳,AFAIK总是以UTC为单位,为什么已经在UTC中的'时代'得到纠正?这是一个错误,或者我在这里错过了关于定义/正常行为的事情。

1 个答案:

答案 0 :(得分:4)

“now()在时区'UTC'”值是您当前时间移至UTC然后转换为TIMESTAMP WITHOUT TIME ZONE

所以你给“date_part”一个没有时区的TIMESTAMP(换句话说是未知的时区),并期望得到它与已知时区的固定时间戳之间的差值(“EPOCH”,1970-01- 01 00:00:00 UTC)。

Postgres需要TIMESTAMP WITH TIME ZONE来计算这个。因此,它会将您的值转换为时区“UTC”assuming it's at your time zone并计算差异。

类似的东西:

select ((now() at time zone 'UTC') at time zone '<your_time_zone>') at time zone 'UTC';