Postgres: як округляти відмітку часу вгору або вниз з точністю до хвилини?


83

Чи існує функція postgresql, яка повертає мітку часу, округлену до найближчої хвилини? Вхідне значення є міткою часу, а повернене значення має бути міткою часу.

Відповіді:


131

Використовуйте вбудовану функцію date_trunc(text, timestamp), наприклад:

select date_trunc('minute', now())

Редагувати: це скорочується до останньої хвилини. Щоб отримати округлий результат, додайте спочатку 30 секунд до мітки часу, наприклад:

select date_trunc('minute', now() + interval '30 second')

Це повертає найближчу хвилину.

Див Postgres Дата / Час Функції і оператори для отримання додаткової інформації


20
+1 за розумний трюк додавання половини інтервалу, а потім усічення.
Jan KS

14

Відповідь на подібне (і більш загальне) запитання,

"... з точністю до хвилинного інтервалу " (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

Адаптовано з http://wiki.postgresql.org/wiki/Round_time та до "точного раунду", як показав @CrowMagnumb.


6

Намагаючись використати відповідь Пітера вище для створення стельових та підлогових функцій, я виявив, що при виклику функції округлення теж потрібно враховувати секунди. Це ось мої набори функцій, які оброблятимуть мітки часу, підлоги та стелі.

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)::float + date_part('second',$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;

Завдяки виправленню (!) Та розширенню: тепер у нас є повна бібліотека "приблизних хвилин". PS: Я думаю, ви можете додати int DEFAULT 5(другий параметр) для спрощення найчастішого використання.
Пітер Краус

Оп, ще одне питання: використання LANGUAGE SQL IMMUTABLE.
Пітер Краус

3

для округлення позначки часу

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

Хоча це не
округляє

я намагався використовувати це для округлення кожні 2 години. не працює.
jpro
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.