web-dev-qa-db-fra.com

Différence d'horodatage en heures pour PostgreSQL

Existe-t-il une TIMESTAMPDIFF() équivalente pour PostgreSQL?

Je sais que je peux soustraire deux horodatages pour obtenir un postgresql INTERVAL. Je veux juste la différence entre les deux horodatages en heures représentés par un INT.

Je peux le faire dans MySQL comme ceci:

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

J'ai juste besoin de la différence entre deux horodatages en heures représentés sous forme d'entier.

La solution fonctionne pour moi:

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

Les premières choses surgissent

EXTRACT(Epoch FROM current_timestamp-somedate)/3600

Peut-être pas joli, mais débloque la route. Pourrait être plus joli si la division de l'intervalle par intervalle était définie.

Edit: si vous voulez qu'il soit supérieur à zéro, utilisez abs ou le plus grand (..., 0). Celui qui convient à votre intention.

Edit ++: la raison pour laquelle je n'ai pas utilisé age est que age avec un seul argument, pour citer la documentation: Soustraire de current_date (at minuit). Cela signifie que vous n'obtenez pas un "âge" précis à moins de courir à minuit. En ce moment, il est presque 1h du matin ici:

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

Récupère les champs où un horodatage est supérieur à la date dans postgresql:

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

Soustraire les minutes de l'horodatage en postgresql:

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

Soustraire des heures de l'horodatage en postgresql:

SELECT * from yourtable 
WHERE your_timestamp_field > current_timestamp - interval '5 hours'
26
Eric Leschinski

La réponse de Michael Krelin est proche n'est pas entièrement sûre, car elle peut être erronée dans de rares situations. Le problème est que les intervalles dans PostgreSQL n'ont pas de contexte en ce qui concerne des choses comme l'heure d'été. Les intervalles stockent les choses en interne sous forme de mois, jours et secondes. Les mois ne sont pas un problème dans ce cas, car la soustraction de deux horodatages utilise simplement des jours et des secondes, mais les "jours" peuvent être un problème.

Si votre soustraction implique des changements d'heure d'été, un jour particulier peut être considéré respectivement 23 ou 25 heures. L'intervalle en tiendra compte, ce qui est utile pour connaître le nombre de jours qui se sont écoulés au sens symbolique, mais il donnerait un nombre incorrect d'heures réelles qui se sont écoulées. L'époque sur l'intervalle multipliera tous les jours par 24 heures.

Par exemple, si une journée "courte" complète passe et une heure supplémentaire du lendemain, l'intervalle sera enregistré comme un jour et une heure. Ce qui a été converti en Epoch/3600 est de 25 heures. Mais en réalité, 23 heures + 1 heure devraient être un total de 24 heures.

La méthode la plus sûre est donc:

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

Comme Michael l'a mentionné dans son commentaire de suivi, vous voudrez probablement aussi utiliser floor () ou round () pour obtenir le résultat sous forme de valeur entière.

14
ShawnFumo

Vous pouvez utiliser les fonctions "extraire" ou "date_part" sur des intervalles ainsi que des horodatages, mais je ne pense pas que cela fasse ce que vous voulez. Par exemple, il donne 3 pour un intervalle de "2 jours, 3 heures". Cependant, vous pouvez convertir un intervalle en un nombre de secondes en spécifiant 'Epoch' comme l'élément de temps que vous souhaitez: extract(Epoch from '2 days, 3 hours'::interval) renvoie 183600 (que vous divisez ensuite par 3600 pour convertir les secondes en heures).

Donc, en rassemblant tout cela, vous obtenez essentiellement la réponse de Michael: extract(Epoch from timestamp1 - timestamp2)/3600. Puisque vous ne semblez pas vous soucier de l'horodatage qui le précède, vous voudrez probablement envelopper cela dans abs:

SELECT abs(extract(Epoch from timestamp1 - timestamp2)/3600)
6
araqnid

postgresql obtient la différence en secondes entre les horodatages

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

qui imprime:

-2

Parce que les horodatages sont séparés de deux secondes. Prenez le nombre et divisez par 60 pour obtenir les minutes, divisez à nouveau par 60 pour obtenir les heures.

3
Eric Leschinski

Cela peut sembler fou à beaucoup de développeurs qui aiment profiter des fonctions de base de données,

Mais après des problèmes exhaustifs de réflexion, de création et de correction d'applications pour mysql et postgrsql avec php en comparant les fonctions de date, je suis arrivé à la conclusion (pour moi), que la façon la plus simple, la plus simple avec moins de maux de tête SQL, n'est pas de profiter de l'un d'eux.

Pourquoi? parce que si vous développez dans un langage middleware comme PHP, PHP a toutes ces fonctions, et elles sont plus faciles à implémenter dans l'ode d'application en comparant les entiers. L'horodatage PostgreSQL n'est PAS == UNIX TIMESTAMP et UNIX TIMESTAMP de MySQL n'est PAS l'horodatage de PostgresQL ou d'Oracles .. il devient plus difficile à porter si vous utilisez des horodatages de base de données ..

il suffit donc d'utiliser un nombre entier, pas un horodatage, comme le nombre de secondes depuis le 1er janvier 1970 à minuit. et peu importe les horodatages de la base de données. , et utilisez gmdate () et stockez tout comme heure gmt pour éviter les problèmes de fuseau horaire.

si vous devez rechercher, trier ou comparer le jour à partir d'autres données, ou le mois ou l'année ou le jour de la semaine, ou quoi que ce soit, dans votre application, et le type de données INTEGER pour time_day, time_hour, time_seconds .. ou tout ce que vous voulez indexer pour rechercher rendra les bases de données plus fluides et plus portables. vous pouvez simplement utiliser un champ, dans la plupart des cas: INTEGER time_created NOT NULL

(plus de champs dans votre ligne de base de données est le seul inconvénient de cette solution que j'ai trouvée, et qui ne cause pas autant de maux de tête ou de tasses de café :)

les fonctions de date de php sont exceptionnelles pour comparer les dates, mais dans mysql ou postgresql, comparer les dates? nah .. utiliser des comparaisons sql entières

je me rends compte qu'il peut sembler plus facile d'utiliser CURRENT_TIMESTAMP sur une fonction d'insertion. HA! ne vous laissez pas berner.

Vous ne pouvez pas faire DELETE FROM SESSION_TABLE WHERE time-initialized < '2 days' si time-intitialized est un horodatage postgresql. mais vous POUVEZ faire:

DELETE FROM SESSION_TABLE WHERE time_initialized < '$yesterday'

Tant que vous définissez $ hier en php comme l'entier des secondes depuis 1970 cet hier était.

Il est plus facile de gérer les enregistrements de session que de comparer les horodatages dans les instructions select postgresql.

SELECT age (), SELECT extract () et asbtime sont des maux de tête en soi. C'est juste mon opinion.

vous pouvez faire l'addition, la soustraction, <,>, le tout avec des objets date php

_peter_sysko U4EA Networks, Inc.

2
Peter Sysko

extract(hour from age(now(),links.created)) vous donne un décompte arrondi au sol de la différence d'heures.

1
Danix D5