Gérer/Enregistrer des durées

…pour ensuite les sommer, souvent plus de 839 heures

Le problème exposé dans ce sujet a été résolu.

Bonjour à tous !

Je me posais la question sur la meilleure manière d'enregistrer des durées temporelles en (My-)SQL, dans l'idée de les sommer par la suite. C'est pour un CRM avec système de suivi de temps. On a des tâches qui n'ont pas de date (et encore moins d'heure) de début fixée à l'avance, et évidemment on souhaite pouvoir, à la fin du projet, voir le temps passé sur ces différentes tâches.

Actuellement, le système enregistre séparément les heures et les minutes, mais en creusant un peu, je me rends compte que les éventuelles retenues quand on dépasse les 59 minutes ne sont pas reportées (c'est un système en test, heureusement). Il y a donc encore du travail dessus, mais j'aimerais pouvoir optimiser les calculs et l'enregistrement. De plus, je voudrais bien que le temps puisse être calculé en jours, voire en semaines.

Quel serait la manière la plus pratique d'enregistrer des durées dans ce but ?

Merci  :)

+0 -0

tout dépend à quel niveau tu veux faire tes calculs.

Si tu veux le faire au niveau du code, si tu fais du PHP, une méthode simple est de stocker dans leur format à eux. Par exemple une tâche de 1 jour et 3 h sera P1DT3H, une tâche de 75 minutes sera PT1H15M.

Je pense aussi que de plus en plus de langage, dont le SQL implémentent la conversion "verbose string", qui dit, par exemple "1 days 59 minutes".

Nota, d'après la documentation mysql, mysql accepte un format du style "y m d h:i:s".

ainsi il suffirait que tu stockes ton intervalle sous la forme 0 0 1 0:59:0 et si tu veux faire des calculs

1
UPDATE ta_table_calendrier SET date_fin = DATE_ADD(date_fin, INTERVAL ta_tache.duration YEAR_SECOND)

tout dépend à quel niveau tu veux faire tes calculs.

artragis

Dans l'idéal, j'aimerais le laisser faire à MySQL.

Nota, d'après la documentation mysql, mysql accepte un format du style "y m d h:i:s".

ainsi il suffirait que tu stockes ton intervalle sous la forme 0 0 1 0:59:0 et si tu veux faire des calculs

1
UPDATE ta_table_calendrier SET date_fin = DATE_ADD(date_fin, INTERVAL ta_tache.duration YEAR_SECOND)

artragis

Intéressant, mais il semble que YEAR_SECOND n'existe pas. J'ai essayé ceci

1
SELECT DATE_ADD('2014-12-22', INTERVAL '1 1 1 01:01:01' YEAR_SECOND)

Essai d'ajout d'intervalle

Et j'obtiens «  #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'YEAR_SECOND)' at line 1 » avec MySQL 5.6. Bon, j'aurai rarement des durées de plus de trois jours, c'est au moment de la collecte que je serai au-delà. Du coup, je peux utiliser DAY_SECOND, ça me convient tout à fait, même si les durées venaient à s'étaler sur plus d'une semaine  :)

En revanche, est-ce qu'il est possible de sommer des durées avec sum(), quelque chose dans le goût de ce qui suit ?

1
SELECT sum(INTERVAL `mon_champ` DAY_SECOND) AS total FROM `maTable` 

Tentative de somme de durées, toujours en MySQL

+0 -0

aucune idée. Je pense qu'il faut juste tester.

artragis

Malheureusement, c'est pas concluant… C'est dommage qu'il n'y ait pas un type natif, au même titre que DATETIME par exemple, qui permette ce genre de calculs, ça ferait probablement mon beurre.

Edit

Même simplement SELECT INTERVAL '1 01:01:01' DAY_SECOND ne fonctionne pas, donc apparemment, c'est pas possible.

+0 -0

En bricolant avec time_to_sec et/ou timediff ? Ou j'ai mal compris.

Après, j'ai peut-être très mal compris la problématique, auquel cas désolé, mais selon moi le plus simple serait de tout stocker en tant que timestamp qu'il s'agisse d'une date (si tu l'as) ou de la durée de la tâche.

Soit tu obtiens la durée directement, soit tu fais la différence entre date de fin et date de début qui te donnerait un résultat en ms (donc cohérent). Il suffit ensuite de sommer les durées en ms et de convertir bêtement (soit directement dans une requête SQL, on a le droit de faire des calculs et de formater aussi) soit via le langage que tu utilises côté serveur.

J'espère ne pas être trop à côté de la plaque.

+1 -0

>_< Enregistrer uniquement des secondes, c'est pourtant si simple… Merci Javier  :)

Je vais me débrouiller pour créer un type Doctrine qui prend en paramètre des jours-heures-minutes-secondes et stocke un entier, et son type de formulaire associé

En fait, ma question pourrait aussi porter sur ce point :

Vaut-il mieux calculer des sommes de différences entre date/heure fin et date/heure début ou sommer directement des durées ?

Edit

En fait, le souci avec sec_to_time(), c'est qu'on est limité à peu près à 840 heures, vu qu'on convertit d'un entier à un type TIME, et je sais que j'aurai des sommes qui iront au-delà des 1000 heures. En revanche, je doute que j'aie des durées qui soient de plus de 18446744073709551615 secondes (soit tout de même près de 584942416 millénaires) :D

+0 -0

Pourquoi ne pas faire ta propre fonction ? Il y a d'autres alternatives que sec_to_time()… Pour ne pas s'obstiner à l'utiliser. Diviser par 60, arrondir à l'entier, et concaténer des chaines de caractères, ne devrait pas te causer un problème.

Pour ta question tout dépend de l'usage :

  • Si c'est juste la différence qui t'intéresse.
  • Si tu souhaites afficher un chrono ou connaître la date de début/fin il te faudra les deux dates de début et de fin.

N'hésite pas à regarder comme les autres font sur Google. Avant de foncer dans le code.

Ce qui m'intéresse, ce sont vraiment les durées, et un moyen d'en sommer rapidement, dans l'idéal avec MySQL. A moins qu'on me dise que j'ai meilleur temps de faire ma somme sur les données récupérées en PHP, ou que faire une somme de différences (sum(time_to_sec(`end`) - time_to_sec(`start`))) est plus facile, et qu'il y a moyen de faire en sorte que MySQL retourne directement une chaîne formatée en jours heures minutes, sans le blocage des 838 heures, 59 minutes et 59 secondes. Si c'est de retourner un entier plutôt que d'appeler sec_to_time(), alors autant manipuler directement des entiers, non ?

+0 -0

Si tu ne stockes que des ms, tu as juste besoin d'un trigger qui calcule la valeur de la durée si elle n'est pas déjà présente (ou tu le fais en PHP à chaque INSERT ou UPDATE) à partir des dates de début et de fin de la tâche.

Ensuite tu n'as plus qu'à sommer les différentes durées avec un SUM pour formater le résultat, soit tu le fais en SQL (diviser par 3600 c'est pas la mort) soit tu formates en PHP, comme tu préfères.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte