Postgres: Wie rundet man einen Zeitstempel auf die nächste Minute hoch oder runter?

83

Gibt es eine Postgresql-Funktion, die einen auf die nächste Minute gerundeten Zeitstempel zurückgibt? Der Eingabewert ist ein Zeitstempel und der Rückgabewert sollte ein Zeitstempel sein.

Dan
quelle

Antworten:

129

Verwenden Sie die integrierte Funktion date_trunc(text, timestamp)zum Beispiel:

select date_trunc('minute', now())

Bearbeiten: Dies wird auf die letzte Minute abgeschnitten . Um ein gerundetes Ergebnis zu erhalten, fügen Sie zuerst 30 Sekunden zum Zeitstempel hinzu, zum Beispiel:

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

Dies gibt die nächste Minute zurück.

Weitere Informationen finden Sie unter Postgres-Datums- / Zeitfunktionen und Operatoren

Böhmisch
quelle
20
+1 für den cleveren Trick, die Hälfte des Intervalls zu addieren und dann abzuschneiden.
Jan KS
14

Antwort auf eine ähnliche (und allgemeinere) Frage:

"... auf das nächste Minutenintervall " (1 Minute, 5 Minuten, 10 Minuten usw.)

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

Angepasst von http://wiki.postgresql.org/wiki/Round_time und an die "exakte Runde", wie @CrowMagnumb gezeigt hat.

Peter Krauss
quelle
6

Beim Versuch, Peters Antwort oben zu verwenden, um Decken- und Bodenfunktionen zu erstellen, stellte ich fest, dass Sie beim Aufrufen der Rundungsfunktion auch die Sekunden berücksichtigen müssen. Dies hier sind meine Funktionen, mit denen Zeitstempel für Runden, Boden und Decke gerundet werden.

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
quelle
Dank der Korrektur (!) Und Erweiterung: Jetzt haben wir eine komplette "ungefähre Minuten" -Bibliothek. PS: Ich denke, Sie können einen int DEFAULT 5(zweiten Parameter) hinzufügen , um die häufigste Verwendung zu vereinfachen.
Peter Krauss
Ops, ein weiteres Problem: Verwenden LANGUAGE SQL IMMUTABLE.
Peter Krauss
3

einen Zeitstempel abrunden

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
quelle
Es rundet die 35 Sekunden jedoch nicht ab, was meiner Meinung nach erwartet wird
Moody_Mudskipper
Ich habe versucht, dies zu verwenden, um alle 2 Stunden zu runden. funktioniert nicht
jpro