begin process at 2012 05 27 21:59:08
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Date / Heure

 > CALCUL DU NOMBRE DE JOURS CONTENUS DANS L'INTERSECTION DE DEUX PÉRIODES

CALCUL DU NOMBRE DE JOURS CONTENUS DANS L'INTERSECTION DE DEUX PÉRIODES


 Description

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

  • /************************************************************
  • * 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
/************************************************************
 * 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.


 Sources de la même categorie

Source avec une capture AGENDA GRAPHIQUE SIMPLE (DÉBUTANT) À INTÉGRER par NicomakM
CALENDRIER EN 70 LIGNES par tchconst
Source avec Zip CALENDRIER par gabay
CALENDRIER SIMPLE par manuche
Source avec Zip Source avec une capture [POO] OBJET CONVERTISSANT UN NOMBRE DE SECONDES EN DIFFÉRENT... par Dariumis

 Sources en rapport avec celle ci

PLANNING DE QUART AUJOURD'HUI par paillette76
Source avec Zip Source avec une capture CALENDRIER - FLOPTWO par floptwo
AFFICHAGE DU DÉCOMPTE D'UNE DATE PAR RAPPORT AVEC LA DATE AC... par GREGPUNK
NOMBRE DE JOUR DEPUIS par erce78
FONCTION DE CALCUL DE JOURS FÉRIÉS par nagrom_om

Commentaires et avis

Commentaire de 007Julien le 15/02/2011 16:55:38

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] <br>".(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>
<body>
<?php echo $chnPge ?>
</body>
</html>  

Commentaire de 007Julien le 15/02/2011 17:06:54

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);

Commentaire de 007Julien le 15/02/2011 18:25:47

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.

Commentaire de 007Julien le 16/02/2011 10:24:31

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] <br>".(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.  

Commentaire de neigedhiver le 16/02/2011 18:43:51

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.

Commentaire de 007Julien le 16/02/2011 20:11:51

Qu'est-ce que c'est que ces sornettes ?
D'abord, le calcul peut consister à inverser les périodes ou a considérer le début et la fin d'une même période si celle-ci est incluse dans l'autre.  
Ensuite, depuis quand mktime ne prend plus en compte les années bissextiles ?
Pour clore le tout, le changement d'heure n'intervient pas lorsque l'on travaille seulement sur les dates à 0 heures 0 minutes 0 secondes !

Commentaire de neigedhiver le 16/02/2011 21:17:49

C'est vrai, mktime sait utiliser le changement d'heure été/hiver. Il faut passer le 7ème paramètre, celui qui est justement omis dans la source.
Mais comme ce paramètre est obsolète depuis PHP 5.1, il faut utiliser le gestionnaire de fuseau horaire à la place, exactement comme cette source ne le fait pas. Ce qui provoquerait très certainement une erreur de type E_STRICT sur mon serveur.

Je me suis donc mal exprimé : cette source qui utilise mktime, ne prend pas en compte le changement d'heure été/hiver.

Là où je me suis mal exprimé également, c'est sur le fait que cette source, qui se contente de compter les jours en divisant le temps obtenu en secondes par 86400 ne donne pas un résultat pertinent.

Bref : je persiste à dire que les classes DateTime et DateInterval fournissent un résultat bien plus pertinent et avec beaucoup moins de lignes de code... Mais comme cela relèguerait la classe au statut de snippet, on admettra que cette source puisse servir d'exemple pour ce qu'il ne faut pas faire.

Commentaire de neigedhiver le 16/02/2011 22:04:00

Juste pour l'aspect didactique :
<?php

function daysIntersection($from1, $to1, $from2, $to2) {
if ($to1 >= $from2 && $to2 >= $from1) { // Intersection des deux périodes
$from = new DateTime(max($from1, $from2));
$to = new DateTime(min($to1, $to2) . ' +1day'); // On ajoute 1 jour, car PHP ne travaille pas sur des journées pleines, mais de minuit à minuit.
$interval = $from -> diff($to);
return $interval -> format('%a');
}
return 0; // Pas d'intersection des deux périodes
}

date_default_timezone_set('Europe/Paris');
echo daysIntersection('2011-01-02', '2011-01-10', '2011-01-08', '2011-01-20');

?>

Notez :
- le test d'intersection simplifié (plus juste aussi, car en tout, il y a 6 cas, l'auteur de la source n'en traite que 5, considérant à tort une configuration comme sans intersection)
- la lisibilité du code (plus facile à comprendre quand on découvre le code)
- la possibilité de formater la période grâce à DateInteval::format() (cf : http://fr.php.net/manual/fr/dateinterval.format.php )

Maintenant, je conçois parfaitement que chacun préfère continuer d'utiliser des méthodes de développement obsolètes et refusent les outils "modernes". Simplement, le code que je présente nécessite PHP5.2, qui est installé même chez Free et OVH, c'est dire si on peut considérer que cette version est la minimum à prendre en compte quand on développe aujourd'hui en PHP. Oubliez un peu le procédural et optimisez votre code, vous verrez, ça fait beaucoup de bien.

Commentaire de 007Julien le 16/02/2011 22:45:47

Encore une fois, nous n'avons rien à faire des changements d'heures pour traiter cette question ! Pour le reste, précisons simplement que mktime reste parfaitement pertinent de 1901 à 2038, ce qui nous laisse quelques délais pour aborder ces fameuses classes...

Un exemple nous permettrait néanmoins de progresser dès maintenant !

Commentaire de 007Julien le 17/02/2011 11:03:33

Merci pour ce morceau de code dont chacun pourra apprécier la lisibilité. Pour ma part, je crains que la grammaire des chaînes de caractères proposée (voir le new DateTime) ait quelques difficultés à s'imposer... À moins qu'elle préfigure la reconnaissance vocale ?

Et puis, un exemple de configuration, considérée à tort par l'auteur comme sans intersection, conforterait là encore des affirmations quelques peu péremptoires...


 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

fonction d'ajout de jour à une date [ par bapti ] bonjour, je recherche d'urgence une fonction qui additionnerait une date avec un nombre de jours et qui retournerait une date, merci d'avance, baptist Récupération de Date, ou Prob Serveur ?? [ par Feebles ] Salut Tous Le Monde, Je débute en PHP, (mais pas en programmation), et j'ai un petit soucis pour récupérer la date du jour encour :j'ai essayer plusie Je trouve pas l'erreur sur mon script [ par Akash ] Salut à tous j'espère que vous pourrez m'aider. Voila le problème :Pour mon script de calendrier evenementiel j'ai besoin d'afficher des évènements pa Gestion de dates [ par tryoruda ] SalutJe souhaite quelques tuyaux pour gérer les dates :- un formulaire avec choix du jour / du mois / de l'année envoie vers un seul champ Mysql date- vérification d'une date [ par vir76 ] Salut tout le monde,Je dispose de la fonction suivante pour vérifier une date :&lt;html&gt;&lt;head&gt; &lt;title&gt; Page de vérification de date en tableau comme calendrier!! [ par titigrou ] kikou a tous!!!pffff j'ai un énorme problème et urgent a règler mais je n'arrive pas a voir l'erreur!!!!au secours!!!!j'ai une liste déroulante semain un lien avec un appel dynamique à un fichier [ par pyranhaz ] Bonjour,je suis pas très fort en php, voire même nul...je cherche à faire fonctionner un lien dans une page qui puisse réagir à la date du jour dans u Pb avec Date() & mktime() [ par LordDaedalus ] BonjourJe suis en train de créer un agenda en utilisant les fonctions date() et mktime().j'utilise $Jour = Date("d",mktime(Date("h")-24*10*7)Le jour e Nombres de jours entre 2 dates! [ par jimmy69 ] Bonjour a tous,Voila j'ai un p'tit stress ....si quelqu'un pouvait m'aider!En fait j'enregistre mes donnees ds une table mysql , des donnees comme le Gestion d'erreurs [ par stailer ] Bonjour,voici ma fonction pour transformer une date MySQL en format français :function date_france($date_saisie){ list ($an , $mois , $jour) =


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,546 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales