我正在为数据库(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中的'时代'得到纠正?这是一个错误,或者我在这里错过了关于定义/正常行为的事情。
答案 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';