Filtre durée

Un filtre pour calculer la période entre deux dates ou l’âge d’un élément

Utilisation du filtre

Ajouter le code du filtre dans votre fichier mes_fonctions.php

filtre durée
version 0.25

Vous pouvez ensuite utiliser le filtre selon la syntaxe

[(#DATE_DEBUT|duree{#DATE_FIN})]

Il est possible d’ajouter un 2e paramètre pour préciser le formatage de durée

[(#DATE_DEBUT|duree{#DATE_FIN,horaire})]

Différents formatages de durée proposés

Voici les différents formatages proposés

ValeurDéfinitionExemple
court on arrondit à la durée la plus proche (formatage par défaut) 4 semaines
etendu affichage complet en lettres 4 semaines 3 jours 23 heures 2 minutes
horaire affichage heures et minutes 2h04
minute affichage minutes cumulées 124
iso8601 affichage selon la norme iso 8601 P18Y9W4DT11H9M8S
ical même chose que iso8601 P18Y9W4DT11H9M8S

Pour faciliter l’internationalisation, il est aussi possible de sortir un élément inviduellement :

  • Y : année
  • W : semaine
  • D : jour
  • H : heure
  • M : minute
  • S : seconde

Exemple d’utilisation
On veut « un format à l’anglaise » qui affiche la durée de la façon suivante : 4’46’’

[(#DATE_DEBUT|duree{#DATE_FIN,M})']][(#DATE_DEBUT|duree{#DATE_FIN,S})'']

Références techniques

Exemple d’utilisation avec le plugin Agenda

Je programme un site de cinéma qui utilise le plugin Agenda pour saisir les séances. Pour chaque séance, le rédacteur saisit une date de début et fin

Voici ma boucle pour afficher toutes les séance d’un film avec l’heure de début de film et la durée

<B_seance><table>
<tr>
  <td>Jour</td>  
  <td>Séance</td>
  <td>Titre du film</td>
  <td>Durée</td>      
</tr>
<BOUCLE_seance(EVENEMENTS){id_article}{par date_debut}>
<tr>
  <td>[(#DATE_DEBUT|affdate_jourcourt)]</td>
  <td>[(#DATE_DEBUT|heures)h][(#DATE_DEBUT|minutes)]</td>
  <td><a href="#URL_ARTICLE">#TITRE</a></td>
  <td>[(#DATE_DEBUT|duree{#DATE_FIN,minute}) min]</td>      
</tr>
</BOUCLE_seance>
</table></B_seance>

Explications
On utilise une boucle EVENEMENTS pour récupérer les séances liées à l’article grâce au critère {id_article} par ordre chronologique grâce au critère {par date_debut}

<BOUCLE_seance(EVENEMENTS){id_article}{par date_debut}>

L’affichage des résultats se fait dans un tableau
Pour afficher la durée on utilise la filtre duree avec l’option d’affichage minute

[(#DATE_DEBUT|duree{#DATE_FIN,minute}) min]

Utiliser le filtre durée pour calculer l’âge d’un élément

Pour calculer l’âge d’un élément, il faut utiliser comme date de fin, la date actuelle.

[(#DATE|duree{#ENV{date}})]

Développement

Le code du filtre est disponible sur la zone à l’adresse http://zone.spip.org/trac/spip-zone...

Voir aussi

Le filtre date_relative peut aussi très pratique.

Discussion

14 discussions

  • Bonsoir,
    En réponse à
    https://discuter.spip.net/t/filtre-duree-attitude-differente-sur-2-sites/170843
    j’ai créé un nouvel filtre plus court pour calculer les durées que je vous partage
    juillet 2023

    // Définir le fuseau horaire par défaut à utiliser.
    # date_default_timezone_set('UTC');
    /**
     * 
     * Calculer les durées écoulées entre deux dates au format Y-m-d H:i:s
     * @param date $date_debut
     * @param date|string $date_fin
     * Sans le parametre $date_fin == today
     *
     * @param string $type_affichage
     * par defaut court, sinon affichage des durées année/mois/jours/heures …
     *
     * @example dans un squelette
     	#SET{date_debut_brut_sql,2006-05-03 18:30:00}
     	#SET{date_fin_brut_sql,2022-06-23 17:29:56}
    
     	<h3>Durées écoulées</h3>
     	Entre son arrivée le [(#GET{date_debut_brut_sql})] et aujourd'hui<br>
     	<span style="color:red">[(#GET{date_debut_brut_sql}|duree)]</span><br>
     	Ou bien avec la date de fin [(#GET{date_fin_brut_sql})] <br>
     	<span style="color:green">[(#GET{date_debut_brut_sql}|duree{#GET{date_fin_brut_sql}})]</span>
     *
     * @return string
     * par defaut le nombre de jours
     * sinon année/mois/jours/heures
     *
    **/
    function duree($date_debut,$date_fin = '',$type_affichage = 'court') {
    	
    	if(!$date_fin) {
    		$date_fin = date("Y-m-d H:i:s"); 
    	}
    	
    	$origin = new DateTimeImmutable($date_debut);
    	$target = new DateTimeImmutable($date_fin);
    	$interval = $origin->diff($target);
    	
    	if($type_affichage == 'court' ) {
    		$duree_affichage = $interval->format('%R%a jours'); //nb_jours
    	} else {
    		$duree_affichage = $interval->format("%Y". ' ans '. "%m".' mois '."%H".'h'."%I" .'min'.":%S (Total de jours: %a)");
    	}
    	
    	return $duree_affichage;
    
    }

    Répondre à ce message

  • 1
    Frédéric

    Je pense qu’il y a un bug sur la fonction minute : le multiples pour diff_weeks devrait être 7 et non 52. Version corrigée :

          case "minute":    $str = $diff_minutes+($diff_hours*60)+($diff_days*60*24)+($diff_weeks*60*24*7)+($diff_year*60*24*365);                                    
                            break;

    Mais cela ne donne quand même pas la valeur tout à fait exacte, il doit y avoir d’autres bugs en amont.

    Plus simplement, le nombre de minutes sera donné par

          case "minute":    $str = floor(($d_fin - $d_debut)/60);                                    
                            break;

    Cette dernière version a l’avantage de donner une valeur exacte même les années bissextiles.

    • Disons même :

      case "minute":
         $str = floor($diff_seconds / 60);
         break;

    Répondre à ce message

  • suite à une discussion sur IRC, on m’a indiqué un code ’moderne’ qui permet d’utiliser une différence entre deux dates

    dans mes_fonctions.php

    /*
     * Filtre pour donner le nombre de jour entre deux dates selon une méthode moderne
    */
    function diffdate($date_debut,$date_fin) {
    	$interval = date_diff(date_create($date_debut), date_create($date_fin));
    	return intval($interval->format('%R%a'));
    }

    Dans le squelette (par exemple pour filtrer selon un écart de date)

    [(#DATE|diffdate{#AUTRE_DATE}|<={4}|oui)
    	   mon code conditionné
    ]

    Répondre à ce message

  • est-ce que quelqu’un peut me donner la syntaxe pour BOUCLE ARTICLE pour ne pas afficher les artcicles dont la date de fin depasse la date du jour
    merci d’avance
    Mickstone

    Répondre à ce message

  • 1

    Hello,

    Merci pour ce filtre qui m’a aidé à solutionner proprement une demande pour l’affichage d’une date de fin, si et seulement si la durée de l’évènement est supérieure à une journée !

    En utilisant l’affichage au format « D » (pour « jour ») et le filtre de comparaison |>{1} on obtient un code plus concis et efficace qu’avec des #EVAL et autres filtres |moins...

    [(#DATE_DEBUT|affdate)][(#DATE_DEBUT|duree{#DATE_FIN,D}|>{1}|oui) > [(#DATE_FIN|affdate)]]

    Merci !

    • Petit correctif :

      L’attribut ’D’ affiche le nombre de jours en partie restante, et non le cumul des jours, comme l’aurait fait un éventuel attribut ’jour’.

      Pour que la balise ci-dessus fonctionne, il faut afficher une valeur cumulée. La valeur cumulée disponible la plus proche est le nombre de minutes cumulées : ’minute’.

      Pour afficher la partie conditionnelle seulement si la date de fin se situe 1 jour après la date de début, la balise devient :

      [(#DATE_DEBUT|duree{#DATE_FIN,minute}|>{86400}|oui) > [(#DATE_FIN|affdate{'d-m-Y'})]]

    Répondre à ce message

  • 1

    bonjour,
    cette fonction duree m’interesse, mais il me manque qq infos sur l’utilisation
    je suis en spip 212
    1) dans quel répertoire doit-on installer le pgm inc-duree.php ou dans quel fichier php peut-on l’inclure
    2) une fois la réponse à laquestion 1 OK, est-ce que 2 champs de saisie (date debut et date fin) apparaissent.
    merci d’avance pour l’éclairage
    Mickstone

    • Bonjour,

      Si tu as déjà un fichier mes_fonctions.php dans ton dossier squelettes, tu peux simplement y copier/coller les lignes de la fonction « durée ».

      Si tu préfères ne pas mélanger tes fonctions existantes avec le filtre durée, tu peux placer le fichier inc_duree.php dans ton dossier squelettes, et charger ce filtre depuis ton fichier mes_fonctions.php avec la fonction inclure_spip de la manière suivante :

      <?php
      /***
       * Ceci est le fichier mes_fonctions.php
       **/
      include_spip('inc_duree');
      ?>

      Si tu n’as pas encore de fichier mes_fonctions.php dans ton dossier squelettes, copie-y le fichier inc_duree.php puis renomme-le mes_fonctions.php.

      Bonne utilisation !

    Répondre à ce message

  • Sylvano

    Bonjour,
    Petit problème avec le passage « Heure d’hiver/Heure d’été » (et oui nous sommes en mars !) (le problème inverse se produira en octobre). Constaté aujourd’hui sous wamp, je demande le nombre de jours : un calcul de durée sur un intervalle de 10 jours pleins incluant le 25 mars retourne 239 heures, donc 9 jours... logique.

    Résolu en définissant date_default_timezone_set("UTC"); au tout début de la fonction.

    Sylvano
    PS : La doc de PHP dit que lors d’un appel à date_default_timezone_get();, « date_default_timezone » prime sur l’option « date.timezone » du php.ini.
    Du coup, à tout hasard, je redéfinis date_default_timezone_set("Europe/Berlin"); à la fin du script. (est-ce vraiment nécessaire ? plus sûr ?)

    Répondre à ce message

  • Bonjour a tous,

    Si besoin voici ma fonction un peur modifier, elle permet notamment de calculer la différence entre deux date dans un format précis. Comme le nombre de jour entre deux dates.

    Exemple : avec $date_debut=16/11/2008, $date_fin=03/02/2011 $type_affichage=D vous obtiendrez 808, ou encore 2 avec $type_affichage=Y

    Attention, par rapport à la première version, Y devient Years, W devient Weeks, D devient Days, H devient Hours, M devient Minutes et S devient Secondes.

    Toutes les anciennes lettres servent à la nouvelle fonctionnalité.

    Voici la fonction :

    /*
     *   +----------------------------------+
     *    Nom du Filtre : duree   
     *   +----------------------------------+
     *    date : 2008.01.10
     *    auteur :  erational - http://www.erational.org et valentin PERRIN
     *    version: 0.25
     *    licence: GPL
     *   +-------------------------------------+
     *
     *    retourne la duree entre 2 dates
     *    
     *    parametres type_affichage
     *    - court   : 5 jours (par defaut)
     *    - etendu  : 4 semaines 3 jours 23 heures 2 minutes
     *    - horaire : 4h39
     *    - minute  : 124 (minutes cumulees)
     *    - iso8601 : P18Y9W4DT11H9M8S   ref. http://fr.wikipedia.org/wiki/ISO_8601#Dur.C3.A9e
     *    - ical    : P18Y9W4DT11H9M8S   ref. http://tools.ietf.org/html/rfc2445#page-37 (mm chose que iso)
     *         
     *    pour sortir une valeur uniquement (i18n)    
     *    - Years       : (an)
     *    - Weeks       : (semaine)
     *    - Days       : (jour) 
     *    - Hours       : (heure)
     *    - Minutes       : (minute)
     *    - Secondes       : (s)
     *    
     *    pour sortir la différence dans un format précis.
     *    Exemple : avec  $date_debut=16/11/2008, $date_fin=03/02/2011 $type_affichage=D vous obtiendrez 808, ou encore 2 avec $type_affichage=Y  
     *    - Y       : (an)
     *    - W       : (semaine)
     *    - D       : (jour) 
     *    - H       : (heure)
     *    - M       : (minute)
     *    - S       : (s) 
     *                                  
    */
    
    function duree($date_debut,$date_fin,$type_affichage='court') {
      $d_debut = mktime(
                  substr($date_debut,11,2),
                  substr($date_debut,14,2),
                  substr($date_debut,17,2),
                  substr($date_debut,5,2),
                  substr($date_debut,8,2),
                  substr($date_debut,0,4));
      
      $d_fin = mktime(
                  substr($date_fin,11,2),
                  substr($date_fin,14,2),
                  substr($date_fin,17,2),
                  substr($date_fin,5,2),
                  substr($date_fin,8,2),
                  substr($date_fin,0,4));
         
      $diff_seconds  = $d_fin - $d_debut; 
      if ($diff_seconds<0) return "";
      $diff_years    = floor($diff_seconds/31536000);
      $diff_seconds -= $diff_years   * 31536000;  
      $diff_weeks    = floor($diff_seconds/604800);
      $diff_seconds -= $diff_weeks   * 604800;
      $diff_days     = floor($diff_seconds/86400);
      $diff_seconds -= $diff_days    * 86400;
      $diff_hours    = floor($diff_seconds/3600);
      $diff_seconds -= $diff_hours   * 3600;
      $diff_minutes  = floor($diff_seconds/60);
      $diff_seconds -= $diff_minutes * 60;  
      $str = "";
      switch ($type_affichage) {
          case "court" :    if ($diff_years>1) $str = "$diff_years ans";
                            else if ($diff_years>0) $str = "$diff_years an";
                            else if ($diff_weeks>1) $str = "$diff_weeks semaines";
                            else if ($diff_weeks>0) $str = "$diff_weeks semaine";
                            else if ($diff_days>1) $str = "$diff_days jours";
                            else if ($diff_days>0) $str = "$diff_days jour";
                            else if ($diff_hours>1) $str = "$diff_hours heures";
                            else if ($diff_hours>0) $str = "$diff_hours heure";
                            else if ($diff_minutes>1) $str = "$diff_minutes minutes";
                            else if ($diff_minutes>0) $str = "$diff_hours minute";                  
                            break;
                      
          case "etendu" :   if ($diff_years>1) $str .= "$diff_years ans ";
                            else if ($diff_years>0) $str .= "$diff_years an ";
                            if ($diff_weeks>1) $str .= "$diff_weeks semaines ";
                            else if ($diff_weeks>0) $str .= "$diff_weeks semaine ";
                            if ($diff_days>1) $str .= "$diff_days jours ";
                            else if ($diff_days>0) $str .= "$diff_days jour ";
                            if ($diff_hours>1) $str .= "$diff_hours heures ";
                            else if ($diff_hours>0) $str .= "$diff_hours heure ";
                            if ($diff_minutes>1) $str .= "$diff_minutes minutes ";
                            else if ($diff_minutes>0) $str .= "$diff_hours minute ";
                            if ($diff_seconds>1) $str .= "$diff_seconds secondes";
                            else if ($diff_seconds>0) $str .= "$diff_seconds secondes";                   
                            break;
    
          case "horaire":   $str = ($diff_hours+($diff_days*24)+($diff_weeks*24*7)+($diff_year*24*7*365))."h";
                            if ($diff_minutes<10) $str .= "0";
                            $str .= $diff_minutes;                                                       
                            break;
                                        
          case "minute":    $str = $diff_minutes+($diff_hours*60)+($diff_days*60*24)+($diff_weeks*60*24*52)+($diff_year*60*24*365);                                    
                            break;
                            
          case "iso8601":   $str = "P${diff_years}Y${diff_weeks}W${diff_days}DT${diff_hours}H${diff_minutes}M${diff_seconds}S";                                    
                            break;
                            
          case "ical":      $str = "P${diff_years}Y${diff_weeks}W${diff_days}DT${diff_hours}H${diff_minutes}M${diff_seconds}S";  // mm chose que iso                                    
                            break;
                            
                            
          case "Years":     $str = $diff_years;                                    
                            break;                       
          case "Weeks":     $str = $diff_weeks;                                    
                            break;
          case "Days":      $str = $diff_days;                                    
                            break;                  
          case "Hours":     $str = $diff_hours;                                    
                            break;                       
          case "Minutes":   $str = $diff_minutes;                                    
                            break;
          case "Secondes":  $str = $diff_secondes;
                            break;                         
          case "Y":         $str = floor(($d_fin - $d_debut)/31536000);                                   
                            break;                       
          case "W":         $str = floor(($d_fin - $d_debut)/604800);                                    
                            break;
          case "D":         $str = floor(($d_fin - $d_debut)/86400);                                   
                            break;                  
          case "H":         $str = floor(($d_fin - $d_debut)/3600);                                    
                            break;                       
          case "M":         $str = floor(($d_fin - $d_debut)/60);                                    
                            break;
          case "S":         $str = $d_fin - $d_debut;                                    
                            break;                     
             
          default:          break;
          
      }   
    
    	return $str;
    }

    Répondre à ce message

  • Bonjour,

    Le filtre minute me donne un résultat bizarre :

    [(#DEBUT|duree{#DATE,etendu})]
    Resultat : 13 semaines 5 jours 9 heures 49 minutes 58 secondes (ok)
    [(#DEBUT|duree{#DATE,horaire})]
    Résultat : 2313h49 (ok)
    [(#DEBUT|duree{#DATE,minute})]
    Résultat : 981229 (??)
    Si c’est du temps cumulé, il devrait être de 2313*60+49 soit : 138 829 ?
    Ou bien je ne n’ai pas bien compris.
    Merci pour votre explication

    Répondre à ce message

  • Il faut ajouter :

    case « jour » : $str = ($diff_days+($diff_weeks*7)+($diff_years*24*7*365)) ;
    break ;

    afin d’avoir le nombre de jours.

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom