【问题标题】:PostgreSQL round timestamp seconds down for a postgres pre-created date with millisecondsPostgreSQL 以毫秒为单位对 postgres 预先创建的日期舍入时间戳秒
【发布时间】:2012-09-12 08:21:53
【问题描述】:

不幸的是,我有一个查询必须比较 2 个时间戳。 PHP date() 函数为数据库提供了一个时间戳,存储为没有时区的时间戳,因此该日期没有添加毫秒。另一个是带有时区的 PG 时间戳。所以这两个日期都已经被创建并插入到表格中,这里是一个日期的例子:

没有时区的时间戳 = 2012-09-19 18:13:26

PG 的时间戳,时区 = 2012-09-19 18:13:26.893878-04

我可以投射 PG date::timestamp(0) 这让我很接近,但正如预期的那样,日期被四舍五入; 2012-09-19 18:13:27

所以我的问题是如何让秒数向下舍入?

【问题讨论】:

    标签: sql postgresql time timestamp zone


    【解决方案1】:

    比较时间戳的相等性很少能很好地工作。如果两个时间戳是在 2012-09-19 18:13:26.99999999 获取的呢?时钟抖动、调度程序抖动、执行时间差异等可能而且经常会将一个推到下一秒。它也不必那么接近边缘发生。您可以尝试使用

    改为与窄范围比较;说 2 秒:

    SET timezone = '+04:00';
    
    SELECT (TIMESTAMP '2012-09-19 18:13:26')::timestamptz 
           BETWEEN TIMESTAMPTZ '2012-09-19 18:13:26.893878-04' - INTERVAL '1' SECOND 
               AND TIMESTAMPTZ '2012-09-19 18:13:26.893878-04' + INTERVAL '1' SECOND;
    

    我不确定你是否可以使用比这更粗的东西,因为你的 PHP 时间戳的精度是 1 秒。

    如果您确定 PHP 总是截断时间戳(向下舍入)而不是舍入,即使它捕获了时间戳,您也可以通过调整括号间隔来粗略地纠正这一点。例如,尝试 1 秒间隔(给定 PHP 的时间戳精度,您可以测试的最窄间隔)尝试,并假设 PHP 总是将时间戳截断:

    SELECT (TIMESTAMP '2012-09-19 18:13:26')::timestamptz 
           BETWEEN TIMESTAMPTZ '2012-09-19 18:13:26.893878-04' - INTERVAL '1' SECOND 
               AND TIMESTAMPTZ '2012-09-19 18:13:26.893878-04';
    

    我个人会在每边至少再增加 0.1 秒以确保:

    SELECT (TIMESTAMP '2012-09-19 18:13:26')::timestamptz 
           BETWEEN TIMESTAMPTZ '2012-09-19 18:13:26.893878-04' - INTERVAL '1.1' SECOND 
               AND TIMESTAMPTZ '2012-09-19 18:13:26.893878-04' + INTERVAL '0.1' SECOND;
    

    如果你真的坚持测试是否相等,请使用:

    regress=# SELECT date_trunc('second', TIMESTAMPTZ '2012-09-19 18:13:26.893878-04');
           date_trunc       
    ------------------------
     2012-09-19 18:13:26-04
    (1 row)
    

    但请注意,测试两个单独捕获的时间戳是否相等是危险和错误的。

    【讨论】:

    • 是的,但与其他可能给我匹配的条件一起,我希望这会起作用,我可能不得不放弃这些值。感谢您的回答和示例代码
    【解决方案2】:

    要向下舍入到第二个,请使用date_trunc('seconds', :timestamp)

    例子:

    select date_trunc('seconds', '2012-09-19 18:13:26.893878-04'::timestamp)
      = '2012-09-19 18:13:26'::timestamp;
    

    这会产生t (true)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-07
      • 1970-01-01
      • 2015-04-29
      • 1970-01-01
      • 2023-03-11
      • 2016-09-06
      • 2020-09-03
      相关资源
      最近更新 更多