代码之家  ›  专栏  ›  技术社区  ›  sirlark

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

  •  3
  • sirlark  · 技术社区  · 16 年前

    我正在为一个数据库(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中的date函数来测试,该函数会更正对我时区的补偿)

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

    我已经清楚地知道,去掉“在时区”的“UTC”可以解决我的问题,但我的问题是,如果“epoch”是要返回一个Unix时间戳,而afaik总是要在UTC中,为什么要更正已经在UTC中的时间的“epoch”?这是一个bug,还是我遗漏了一些关于这里定义的/正常行为的信息。

    1 回复  |  直到 9 年前
        1
  •  4
  •   Milen A. Radev    16 年前

    “now()at time zone'utc'”值是当前时间移动到utc,然后转换为 TIMESTAMP WITHOUT TIME ZONE .

    所以给“date_part”一个不带时区的时间戳(也就是说,未知时区),并期望它与已知时区(epoch,1970-01-01 00:00:00 utc)的固定时间戳之间的秒差。

    Postgres需要带时区的时间戳来计算此值。所以它把你的值转换成时区'utc' assuming it's at your time zone 并计算差异。

    类似于:

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