Postgres: jak zaokrąglić znacznik czasu w górę lub w dół do najbliższej minuty?

87

Czy istnieje funkcja postgresql, która zwraca znacznik czasu zaokrąglony do najbliższej minuty? Wartość wejściowa to znacznik czasu, a wartość zwracana to znacznik czasu.

dan
źródło

Odpowiedzi:

136

Użyj wbudowanej funkcji date_trunc(text, timestamp), na przykład:

select date_trunc('minute', now())

Edycja: Obcina do ostatniej minuty. Aby otrzymać zaokrąglony wynik, najpierw dodaj 30 sekund do znacznika czasu, na przykład:

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

Zwraca to najbliższą minutę.

Aby uzyskać więcej informacji, zobacz Funkcje daty / czasu Postgres i operatory

Czeski
źródło
20
+1 za sprytną sztuczkę polegającą na dodaniu połowy interwału, a następnie skróceniu.
Jan KS,
14

Odpowiedz na podobne (i bardziej ogólne) pytanie,

„… z dokładnością do najbliższej minuty ” (1 minuta, 5 minut, 10 minut itd.)

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

Zaadaptowano z http://wiki.postgresql.org/wiki/Round_time i do „dokładnej rundy”, jak pokazał @CrowMagnumb.

Peter Krauss
źródło
6

Próbując wykorzystać powyższą odpowiedź Petera do utworzenia funkcji sufitu i podłogi, stwierdziłem, że przy wywoływaniu funkcji zaokrąglania trzeba również wziąć pod uwagę sekundy. Oto moje zestawy funkcji, które będą zaokrąglać, podłogowe i sufitowe znaczniki czasu.

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;
crowmagnumb
źródło
Dzięki poprawce (!) I rozszerzeniu: mamy teraz kompletną bibliotekę "przybliżonych minut". PS: Myślę, że możesz dodać int DEFAULT 5(drugi parametr), aby uprościć najczęstsze użycie.
Peter Krauss,
Ops, inna kwestia: użycie LANGUAGE SQL IMMUTABLE.
Peter Krauss
3

aby zaokrąglić w dół sygnaturę czasową

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
James De Souza
źródło
Nie zaokrągla jednak 35 sekund, co myślę, że jest oczekiwane
Moody_Mudskipper
próbowałem użyć tego do zaokrąglania co 2 godziny. nie działa.
jpro