Calcul du nombre de jours contenus dans l'intersection de deux périodes

Soyez le premier à donner votre avis sur cette source.

Snippet vu 6 422 fois - Téléchargée 15 fois

Contenu du snippet

Cette fonction calcul le nombre de jours contenus dans la période issue de l'intersection de deux périodes, c'est à dire le nombre de jour appartenant à la fois aux deux périodes.

Source / Exemple :


/************************************************************

  • Calcul le nombre de jour contenu dans la période d'intersection
  • entre deux périodes (Nombre de jour appartenant aux deux périodes)
  • $d1 string : Date de début période 1 (format YYYY-MM-DD)
  • $f1 string : Date de fin de la période 1
  • $d2 string : Date de début période 2
  • $f2 string : Date de fin période 2
  • Retour interger : Nombre de jour appartenant aux deux périodes.
                                                                                                                                          • /
function nbJourIntersection ($d1, $f1, $d2, $f2) { if ( ($d1 >= $d2 && $d1 <= $f2) || ($f1 >= $d2 && $f1 <= $f2) || ($d2 >= $d1 && $d2 <= $f1)) { //*** Il y a intesction entre les deux periodes if ($d1 >= $d2 && $f1 <= $f2) { //*** CAS n°1 : periode 1 est inclue dans perdiode 2 $di = $d1; $fi = $f1; } else if ($d1 <= $d2 && $f1 >= $f2) { //*** CAS n°2 : periode 2 est inclue dans perdiode 1 $di = $d2; $fi = $f2; } else if ($d2 >= $d1 && $d2 <= $f1) { //*** CAS n°3 : periode 1 à cheval à gauche sur perdiode 2 $di = $d2; $fi = $f1; } else { //*** CAS n°4 : periode 1 à cheval à droite sur perdiode 2 $di = $d1; $fi = $f2; } // Calcul le nombre de jour sur la periode d'intersection $arr_di = explode ('-', $di); $arr_fi = explode ('-', $fi); $time_di = mktime (0, 0, 0, $arr_di[1], $arr_di[2], $arr_di[0]); $time_fi = mktime (0, 0, 0, $arr_fi[1], $arr_fi[2], $arr_fi[0]); $nbJour = round((($time_fi - $time_di) / 60 / 60 / 24)) + 1; return $nbJour; } else { //*** Il n'y a pas intersection entre les deux periodes return 0; } } // nbJourIntersection

Conclusion :


Exemple :
$nbJour = nbJourIntersection ('2011-01-02', '2011-01-10', '2011-01-08', '2011-01-20');

$nbJour contient la valeur 3.

A voir également

Ajouter un commentaire

Commentaires

007Julien
Messages postés
279
Date d'inscription
mercredi 22 septembre 2010
Statut
Membre
Dernière intervention
8 janvier 2014
2
Un problème intéressant qui devrait pouvoir être résolu, sinon plus clairement, plus élégamment...

Les périodes se recouvrement lorsque la suite des dates classées ne commence par par deux dates de la même période...

Voici une proposition, livrée avec la page de test aléatoire, qui a le mérite de fonctionner même si les dates des périodes sont inversées.

<?php
header("Content-Type: text/html; charset=iso-8859-1");

function nbJourInter($d1,$f1,$d2,$f2) {
$dat=array($d1,$f1,$d2,$f2);
asort($dat,SORT_STRING);
$key=array_keys($dat);
if (0<($key[0]-1)*($key[1]-1)) return "Intersection vide ";
sort($dat);
$arr_di = explode ('-',$dat[1]);
$arr_fi = explode ('-',$dat[2]);
$di = mktime (0,0,0,$arr_di[1],$arr_di[2],$arr_di[0]);
$fi = mktime (0,0,0,$arr_fi[1],$arr_fi[2],$arr_fi[0]);
return "du $dat[1] au $dat[2]
".(round((($fi-$di)/60/60/24))+1)." jours de recouvrement";
}
$ms=explode('|','mois|janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre');
$chnPge='<table border="0" cellspacing="0" cellpadding="5">';
for ($i=0;$i<10;$i++){
// Choisir 4 date au hazard
$chnPge.='<tr><td>';$d=array();
for ($j=0;$j<4;$j++){$jr=rand(1,365);
$dt=mktime(0,0,0,1,$jr,"2011");$d[$j]=date("Y-m-d",$dt);
$chnPge.=($j==2?' et ':' ').(($j%2)?'au':'du').' '.date("j",$dt).' '.$ms[date("n",$dt)];
}
$chnPge.='</td><td>'.nbJourInter($d[0],$d[1],$d[2],$d[3]).'</td></tr>';
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="fr">
<head>
<title>Ajouter</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" href="style.css" type="text/css">
<script type="text/javascript">

</script>
</head>

<?php echo $chnPge ?>

</html>
007Julien
Messages postés
279
Date d'inscription
mercredi 22 septembre 2010
Statut
Membre
Dernière intervention
8 janvier 2014
2
Quelques corrections : Les dates se recouvrent, Choisir 4 dates au hasard et puis plutôt que de trier deux fois le tableau, il suffirait de considérer ses valeurs avec un $val=array_values($dat);
007Julien
Messages postés
279
Date d'inscription
mercredi 22 septembre 2010
Statut
Membre
Dernière intervention
8 janvier 2014
2
Il faut corriger la ligne
if (0<($key[0]-1)*($key[1]-1)) return "Intersection vide ";
en
if (0<($key[0]-1.5)*($key[1]-1.5)) return "Intersection vide ";
pour tester que les deux premières clefs sont toutes deux supérieures à 1 ou toutes deux inférieures à deux.
007Julien
Messages postés
279
Date d'inscription
mercredi 22 septembre 2010
Statut
Membre
Dernière intervention
8 janvier 2014
2
Encore une correction !
Les périodes étant comprises au sens large, c'est-à-dire en incluant les dates limites, il convient encore d'écarter la coïncidence des dates médianes pour affirmer l'absence de recouvrement. La fonction peut alors s'écrire

function nbJourInter($d1,$f1,$d2,$f2) {
$dat=array($d1,$f1,$d2,$f2);
asort($dat,SORT_STRING);
$key=array_keys($dat);
$dat=array_values($dat);
if ($dat[1]!=$dat[2] && ($key[0]$1)+($key[1]$1)!=2) return "Pas de recouvrement";
$arr_di = explode ('-',$dat[1]);
$arr_fi = explode ('-',$dat[2]);
$di = mktime (0,0,0,$arr_di[1],$arr_di[2],$arr_di[0]);
$fi = mktime (0,0,0,$arr_fi[1],$arr_fi[2],$arr_fi[0]);
return "du $dat[1] au $dat[2]
".(round((($fi-$di)/60/60/24))+1)." jours de recouvrement";
}
Mais l'avantage est bien mince ! Serait-il utile d'être bête ? Il convient, en toute hypothèse de ne point être étourdi.
neigedhiver
Messages postés
2483
Date d'inscription
jeudi 30 novembre 2006
Statut
Membre
Dernière intervention
14 janvier 2011
14
En fait, d'après l'exemple donné, ça revient à calculer le nombre de jours entre deux dates : le début de la période 2 et la fin de la période 1.
Par ailleurs, se baser sur mktime() pour se genre de calculs est, rigoureusement, incorrect et donne des valeurs qui sont, rigoureusement, fausses.
En effet, mktime ne prend pas en compte :
- le nombre de jours dans l'année (années bissextiles : rappelons qu'une année tropique conventionnelle dure 365 jours 5 heures 48 minutes 45 secondes)
- le changement d'heure été/hiver

Pour pallier ces problèmes, PHP a introduit dans sa version 5.1 (puis intégré en standard depuis 5.2) les classes DateTime, DatePeriod, DateInterval qui permettent justement de prendre en compte (sous réserve de leur spécifier le fuseau horaire adéquat) les années bissextiles et les changements d'heures.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.