2009-12-26 17 views
37

¿Existe un equivalente TIMESTAMPDIFF() para PostgreSQL?Diferencia de marca de tiempo en horas para PostgreSQL

Sé que puedo restar dos marcas de tiempo para obtener un postgresql INTERVAL. Solo quiero la diferencia entre las dos marcas de tiempo en horas representadas por un INT.

que pueda hacer esto en MySQL como esto:

TIMESTAMPDIFF(HOUR, links.created, NOW()) 

Sólo necesito la diferencia entre dos marcas de tiempo en horas representados como un entero.

La solución funciona para mí:

SELECT "links_link"."created", 
"links_link"."title", 
(EXTRACT(EPOCH FROM current_timestamp - "links_link"."created")/3600)::Integer AS "age" 
FROM "links_link" 

Respuesta

62

Las primeras cosas apareciendo

EXTRACT(EPOCH FROM current_timestamp-somedate)/3600 

Puede que no sea bonita, pero desbloquea el camino. Podría ser más bonito si se definiera la división del intervalo por intervalo.

Editar: si lo quiere más grande que cero, use abs o el más grande (..., 0). Cualquiera que se adapte a tu intención.

Editar ++: la razón por la que no hizo uso de age es que age con un solo argumento, para citar la documentación: Restar de fecha_actual (a medianoche). Lo que significa que no obtienes una "edad" precisa a menos que se ejecute a medianoche. En este momento es casi 01 a.m. aquí:

select age(current_timestamp); 
     age   
------------------ 
-00:52:40.826309 
(1 row) 
5

Puede utilizar el "extracto" o "funciones" en la date_part intervalos, así como marcas de tiempo, pero no creo que eso hace lo que quiere. Por ejemplo, da 3 por un intervalo de '2 días, 3 horas'. Sin embargo, puede convertir un intervalo en una cantidad de segundos especificando 'época' como el elemento de tiempo que desea: extract(epoch from '2 days, 3 hours'::interval) devuelve 183600 (que luego divide por 3600 para convertir segundos a horas).

Así que, juntando todo esto, obtienes básicamente la respuesta de Michael: extract(epoch from timestamp1 - timestamp2)/3600. Dado que no parece que se preocupan por lo que precede, que marca de tiempo, es probable que desee para envolver que en abs:

SELECT abs(extract(epoch from timestamp1 - timestamp2)/3600) 
+0

Este es de hecho el más cercano. Dejar caer todos los decimales no debería ser un problema, aunque me entristece la falta de una función incorporada para hacer esto, como MySQL. – TheLizardKing

+0

No debería haber decimales, ya que estará dividiendo enteros. – araqnid

+0

araqnid, yo también pensé que sí, pero acabo de probar y de hecho float. –

3

Esto podría parecer una locura a una gran cantidad de desarrolladores que les gusta aprovechar las funciones de base de datos,

Pero después de exhaustivos problemas para pensar, crear y corregir las aplicaciones de mysql y postgrsql con php comparando las funciones de fecha, he llegado a la conclusión (para mí), que la manera más sencilla, que es la más simple con menos dolores de cabeza SQL no es aprovecha cualquiera de ellos.

¿Por qué? porque si está desarrollando en un lenguaje de middleware como PHP, PHP tiene todas estas funciones, y son más fáciles de implementar en la aplicación ode que la comparación de enteros. PostgreSQL marca de tiempo no se == marca de tiempo Unix y de marca de tiempo Unix MySQL PostgreSQL no es de marca de tiempo o los oráculos .. se vuelve más difícil al puerto si utiliza marcas de tiempo de bases de datos ..

tan sólo tiene que utilizar un número entero, no una marca de tiempo, ya que el número de segundos desde el 1 de enero de 1970 a medianoche. y no importa las marcas de tiempo de la base de datos. , y usa gmdate() y almacena todo como tiempo gmt para evitar problemas con la zona horaria.

si necesita buscar, ordenar o comparar el día de otros datos, o el mes o el año o el día de la semana, o cualquier cosa, en su aplicación, y tipo de datos INTEGER para time_day, time_hour, time_seconds. .o lo que sea que quieras indexar para buscar, se crearán bases de datos más fluidas y más portátiles. puede simplemente usar un campo, en la mayoría de los casos: INTEGER time_created NO NULO

(más campos en su fila de base de datos es el único inconveniente para esta solución que he encontrado, y eso no causa tantos dolores de cabeza, o tazas de café :)

Las funciones de la fecha php son excepcionales para comparar las fechas, pero en mysql o postgresql, comparando fechas? nah .. use las comparaciones enteras sql

me doy cuenta de que puede parecer más fácil usar CURRENT_TIMESTAMP en una función de inserción. ¡DECIR AH! no se deje engañar.

No puede hacer DELETE FROM SESSION_TABLE WHERE time-initialized < '2 days' si time-intitialized es una marca de tiempo postgresql. pero se puede hacer:

DELETE FROM SESSION_TABLE WHERE time_initialized < '$yesterday'

Mientras configura $ ayer en php como el número entero de segundos desde el año 1970 que fue ayer.

Esto facilita el mantenimiento de los registros de sesión que la comparación de marcas de tiempo en las instrucciones de selección postgresql.

SELECCIONAR edad(), SELECCIONAR extraer(), y asbtime son dolores de cabeza en sí mismos. Esta es sólo mi opinión.

que puede hacer suma, resta, <,>, todas con fecha de objetos PHP

_peter_sysko U4EA Networks, Inc.

+2

Entonces, ¿cómo se asegura de que solo las fechas válidas lleguen a su "fecha entera"? ¿Dónde se verifica si '2012-02-29' es válido o no? ¿Cómo se sabe si el tiempo '02: 14' es válido para el 24 de marzo? (Indicación de que no es válido en todas partes debido a las reglas de horario de verano). Y borrar es bastante fácil: 'ELIMINAR FROM SESSION_TABLE WHERE initialized por el tiempo

1

extract(hour from age(now(),links.created)) le da un recuento de suelo redondeado de la diferencia de hora.

+3

Después de tres años ... lo dudo. Además: Intentando 'seleccionar extracto (hora de '11 mons 30 días 23:00:00 ':: intervalo);' solo' 23 'y no 11 meses, 30 días y 23 horas expresado en horas (aproximadamente 8660) . –

3

PostgreSQL obtener la diferencia entre las marcas de tiempo de segundos

SELECT (
    (extract (epoch from (
     '2012-01-01 18:25:00'::timestamp - '2012-01-01 18:25:02'::timestamp 
         ) 
      ) 
    ) 
)::integer 

que imprime:

-2 

Debido a que las marcas de tiempo de dos segundos de diferencia. Tome el número y divida por 60 para obtener los minutos, divida por 60 nuevamente para obtener horas.

17

Get campos en los que una marca de tiempo es mayor que la fecha en PostgreSQL:

SELECT * from yourtable 
WHERE your_timestamp_field > to_date('05 Dec 2000', 'DD Mon YYYY'); 

Restar minutos de marca de tiempo en PostgreSQL:

SELECT * from yourtable 
WHERE your_timestamp_field > current_timestamp - interval '5 minutes' 

horas Restar de marca de tiempo en PostgreSQL:

SELECT * from yourtable 
WHERE your_timestamp_field > current_timestamp - interval '5 hours' 
9

La respuesta de Michael Krelin no es del todo segura, ya que puede ser incorrecta en situaciones excepcionales. El problema es que los intervalos en PostgreSQL no tienen contexto en lo que respecta a cosas como el horario de verano. Los intervalos almacenan cosas internamente como meses, días y segundos. Los meses no son un problema en este caso, ya que restar dos marcas de tiempo solo usan días y segundos, pero 'días' puede ser un problema.

Si su resta implica cambios en el horario de verano, un día en particular podría considerarse de 23 o 25 horas respectivamente. El intervalo lo tendrá en cuenta, lo cual es útil para conocer la cantidad de días transcurridos en el sentido simbólico, pero daría un número incorrecto de las horas reales que pasaron. La cantidad en el intervalo se multiplicará todos los días por 24 horas.

Por ejemplo, si pasa un día "corto" completo y una hora adicional del día siguiente, el intervalo se registrará como un día y una hora. Cuál convertido a epoch/3600 es 25 horas. Pero en realidad, 23 horas + 1 hora deben ser un total de 24 horas.

lo tanto, el método más seguro es:

(EXTRACT(EPOCH FROM current_timestamp) - EXTRACT(EPOCH FROM somedate))/3600 

Como Michael mencionó en su comentario de seguimiento, usted probablemente también quieren usar piso() o redonda() para obtener el resultado como un valor entero .

Cuestiones relacionadas