Postgres:如何将时间戳向上或向下舍入到最近的分钟?

问题描述

| 是否有一个postgresql函数将返回四舍五入到最接近分钟的时间戳?输入值是一个时间戳,返回值应该是一个时间戳。     

解决方法

        使用内置功能
date_trunc(text,timestamp)
,例如:
select date_trunc(\'minute\',now())
编辑:这将截断到最近的分钟。要获得四舍五入的结果,请先将时间戳记添加30秒,例如:
select date_trunc(\'minute\',now() + interval \'30 second\')
这将返回最近的分钟。 有关更多信息,请参见Postgres日期/时间函数和运算符。     ,        回答类似(更通用)的问题,   \“ ...到最近的分钟间隔\”(1分钟,5分钟,10分钟等)
CREATE FUNCTION round_minutes(TIMESTAMP WITHOUT TIME ZONE,integer) 
RETURNS TIMESTAMP WITHOUT TIME ZONE AS $$ 
  SELECT 
     date_trunc(\'hour\',$1) 
     +  cast(($2::varchar||\' min\') as interval) 
     * round( 
     (date_part(\'minute\',$1)::float + date_part(\'second\',$1)/ 60.)::float 
     / $2::float
      )
$$ LANGUAGE SQL IMMUTABLE;

CREATE FUNCTION round_minutes(TIMESTAMP WITHOUT TIME ZONE,integer,text) 
RETURNS text AS $$ 
  SELECT to_char(round_minutes($1,$2),$3)
$$ LANGUAGE SQL IMMUTABLE;

SELECT round_minutes(\'2010-09-17 16:23:12\',5);
-- 2010-09-17 16:25:00

SELECT round_minutes(\'2010-09-17 16:23:12\',10,\'HH24:MI\');
-- 16:20
如@CrowMagnumb所示,改编自http://wiki.postgresql.org/wiki/Round_time,并适应了“精确回合”。     ,        在尝试使用上面的Peter \'s答案创建天花板和地板函数时,我发现调用舍入函数时还必须考虑秒数。这是我将要进行舍入,舍入和上限时间戳记的函数集。
CREATE OR REPLACE FUNCTION round_minutes( TIMESTAMP WITHOUT TIME ZONE,integer) 
RETURNS TIMESTAMP WITHOUT TIME ZONE AS $$ 
  SELECT date_trunc(\'hour\',$1) + (cast(($2::varchar||\' min\') as interval) * round( (date_part(\'minute\',$1)/ 60.)::float / cast($2 as float)))
$$ LANGUAGE SQL IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION floor_minutes( TIMESTAMP WITHOUT TIME ZONE,integer ) 
RETURNS TIMESTAMP WITHOUT TIME ZONE AS $$ 
    SELECT round_minutes( $1 - cast((($2/2)::varchar ||\' min\') as interval ),$2 );
$$ LANGUAGE SQL IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION ceiling_minutes( TIMESTAMP WITHOUT TIME ZONE,integer ) 
RETURNS TIMESTAMP WITHOUT TIME ZONE AS $$ 
    SELECT round_minutes( $1 + cast((($2/2)::varchar ||\' min\') as interval ),$2 );
$$ LANGUAGE SQL IMMUTABLE STRICT;
    ,        舍入时间戳
CREATE or replace FUNCTION date_round_down(base_date timestamptz,round_interval INTERVAL) 
RETURNS timestamptz AS $BODY$
            SELECT TO_TIMESTAMP(EXTRACT(epoch FROM date_trunc(\'hour\',$1))::INTEGER + trunc((EXTRACT(epoch FROM $1)::INTEGER - EXTRACT(epoch FROM date_trunc(\'hour\',$1))::INTEGER) / EXTRACT(epoch FROM $2)::INTEGER) * EXTRACT(epoch FROM $2)::INTEGER) 
$BODY$ LANGUAGE SQL STABLE;

SELECT date_round_down(\'2017-06-02 16:39:35\',\'15 minutes\') -- 2017-06-02 16:30:35