Ajouter, soustraire, comparer des dates

On constate souvent que les gens maîtrise mal les opérations sur les dates..
J'ai donc essayé de concevoir un système simple pour modifier une date.
Avec la classe suivante, vous pourrez :

  • Ajouter, soustraire des jours/mois/années/heures/minute/seconde a vos dates.
  • Comparer deux date et connaître l'intervalle entre elle
  • Changer le format d'une date

Comment ça marche

En 1er lieu, il faut instancier la classe en lui donnant la date de départ ainsi que son format :

php
$madate=new dateOp("14/07/2006 12:30","jj/mm/aaaa hh:ii");
// ou 
$madate=new dateOp("14.7.06 8:10","jj.m.aa h:ii");

La définition du format de date est trés importante.

Dans la définition du format de la date :
'j' représente les jours ('jj' pour avoir le zero initial)
'm' représente les mois ('mm' pour avoir le zero initial)
'aa' représente les années ('aaaa' pour avoir l'année sur 4 chiffres)
'h' représente les heures ('hh' pour avoir le zero initial)
'ii' représente les minutes
'ss' représente les secondes
Cette classe ne fonctionne qu'avec des dates numériques. Il vous sera impossible de travailler avec une date alphanumérique. (ex : “12 septembre 2006” est une mauvaise date).

Ensuite, vous effectuez les opérations désirées.

Ajouter ou soustraire des jours

Pour cela, vous devez utiliser la fonction AjouteJours
Pour additionner 5 jours :

php
$madate->AjouteJours(5);

Pour soustraire 9 jours :

php
$madate->AjouteJours(-9);

Ajouter ou soustraire des mois

Pour cela, vous devez utiliser la fonction AjouteMois
Pour additionner 5 mois :

php
$madate->AjouteMois(5);

Pour soustraire 9 mois :

php
$madate->AjouteMois(-9);

Ajouter ou soustraire des années

Pour cela, vous devez utiliser la fonction AjouteAnnees
Pour additionner 5 années :

php
$madate->AjouteAnnees(5);

Pour soustraire 9 années :

php
$madate->AjouteAnnees(-9);

Ajouter ou soustraire des heures

Pour cela, vous devez utiliser la fonction AjouteHeures
Pour additionner 5 heures :

php
$madate->AjouteHeures(5);

Pour soustraire 9 heures :

php
$madate->AjouteHeures(-9);

Ajouter ou soustraire des minutes

Pour cela, vous devez utiliser la fonction AjouteMinutes
Pour additionner 5 minutes :

php
$madate->AjouteMinutes(5);

Pour soustraire 9 minutes :

php
$madate->AjouteMinutes(-9);

Ajouter ou soustraire des secondes

Pour cela, vous devez utiliser la fonction AjouteSecondes
Pour additionner 5 secondes :

php
$madate->AjouteSecondes(5);

Pour soustraire 9 secondes :

php
$madate->AjouteSecondes(-9);

Connaître la différence entre deux dates

Après avoir instancié la classe avec une date d'origine (comme décrit plus haut) vous pouvez la comparer à une seconde date en utilisant la fonction DiffenrenceEntreDate

php
$difference=$madate->DiffenrenceEntreDate('11/04/2000','jj/mm/aaaa');

la fonction DiffenrenceEntreDate renvoie une variable de type tableau qui contient 4 valeurs. Les 3 premières corresponde au nombre d'années, de mois et de jours qui séparent les deux date. La 4eme valeur correspond au nombre de jour qui sépare les deux dates.
Le code ci-dessous renverra par exemple :

Array
(
    [ans] => 10
    [mois] => 2
    [jours] => 3
    [joursTotal] => 3715.20842593
    [heures] => 5
    [minutes] => 00
    [secondes] => 08
)
La fonction DiffenrenceEntreDate prend 2 paramètres :
La date de comparaison
Le format de la date de comparaison. Ce format est défini de la même façon que précédemment.
Si vous avez effectué des additions ou des soustractions à la date d'origine, il en sera tenu compte lors de la comparaison.

Obtenir la date

Après avoir effectué toutes vos opérations, vous pouvez récupérer la date au format que vous désirez.
Pour cela, utilisez la fonction GetDate

php
echo $madate->GetDate('h:i:s jj-mm-aaaa');
La fonction GetDate prend 1 parametres :
Le format de la date de sortie. Ce format est défini de la même façon que précédemment.

Debogage

Vous pouvez afficher certaines informations de débogage en affichage la variable tableau errno :

php
print_r($madate->errno);
/*
Affichera, par exemple :
Array
(
    [0] => jj/mm/aaaa : Les heures n'ont pas été trouvées... Les heures doivent être précisées par 'hh' ou 'h' (ex: jj/mm/aaaa hh:ii:ss)
    [1] => jj/mm/aaaa : Les minutes n'ont pas été trouvées... Les minutes doivent être précisées par 'ii' ou 'i' (ex: jj/mm/aaaa hh:ii:ss)
    [2] => jj/mm/aaaa : Les secondes n'ont pas été trouvées... Les secondes doivent être précisées par 'ss' ou 's' (ex: jj/mm/aaaa hh:ii:ss)
)
*/

Code

Placez ce code dans un fichier nommé “date.class.php” et pensez à l'inclure dans vos pages (include(“date.class.php”);)

php
<?php
class dateOp {	
	function dateOp($dat,$format="jj/mm/aaaa hh:ii:ss") {
		$this->errno = array();
 
		if (strlen($dat)!=strlen($format)) {
			$this->_error("Format de date incompatible avec la date fournie");
			return false;
		}
 
		$this->dat['origine']=$dat;
		$this->format=strtolower($format);
		return $this->_ExplodeDate($this->dat,$this->format);
	}
 
	function AjouteJours($nb) {
		$this->dat['jj']+=floatval($nb);
		return true;
	}
	function AjouteMois($nb) {
		$this->dat['mm']+=floatval($nb);
		return true;
	}
	function AjouteAnnees($nb) {
		$this->dat['aaaa']+=floatval($nb);
		return true;
	}
	function AjouteHeures($nb) {
		$this->dat['hh']+=floatval($nb);
		return true;
	}
	function AjouteMinutes($nb) {
		$this->dat['ii']+=floatval($nb);
		return true;
	}
	function AjouteSecondes($nb) {
		$this->dat['ss']+=floatval($nb);
		return true;
	}
	function DiffenrenceEntreDate($dat,$format="jj/mm/aaaa hh:ii:ss") {
		if (strlen($dat)!=strlen($format)) {
			$this->_error("Format de date incompatible avec la date fournie");
			return false;
		}
		$this->dat2['origine']=$dat;
		$this->format2=strtolower($format);
		$this->_ExplodeDate($this->dat2,$this->format2);
		$d1=mktime($this->dat['hh'],$this->dat['ii'],$this->dat['ss'],$this->dat['mm'],$this->dat['jj'],$this->dat['aaaa']);
		$d2=mktime($this->dat2['hh'],$this->dat2['ii'],$this->dat2['ss'],$this->dat2['mm'],$this->dat2['jj'],$this->dat2['aaaa']);
 
		if ($d2>$d1)
			$d=$d2-$d1;
		else
			$d=$d1-$d2;
 
		return array("ans"=>date('Y',$d)-1970,"mois"=>date('m',$d)-1,"jours"=>date('d',$d)-1,"joursTotal"=>$d/60/60/24,"heures"=>date("G",$d)-1,"minutes"=>date("i",$d),"secondes"=>date("s",$d));
	}
 
	function GetDate($format="jj/mm/aaaa") {
		$format=str_replace(array('jj','j','m','nn','aaaa','aa','hh','h','ii','ss'),array('d','D','n','m','Y','y','H','G','i','s'),$format);
		return date($format,mktime($this->dat['hh'],$this->dat['ii'],$this->dat['ss'],$this->dat['mm'],$this->dat['jj'],$this->dat['aaaa']));
	}
 
	function _ExplodeDate(&$dat,$format) {
		$j[0]=2;
		if (($j[1]=strpos($format,'jj'))===false) {
			$j[0]=1;
			if (($j[1]=strpos($format,'j'))===false)
				$this->_error($format." : Les jours n'ont pas été trouvés... Les jours doivent être précisés par 'jj' ou par 'j' (ex: jj/mm/aaaa)");	
		}
		$m[0]=2;
		if (($m[1]=strpos($format,'mm'))===false)
			$m[0]=1;
			if (($m[1]=strpos($format,'m'))===false)
				$this->_error($format." : Les mois n'ont pas été trouvés... Les mois doivent être précisés par 'mm' ou par 'm' (ex: jj/mm/aaaa)");
		$a[0]=4;
		if (($a[1]=strpos($format,'aaaa'))===false) {
			//cherche pour un aa au lieu de aaaa
			$a[0]=2;
			if (($a[1]=strpos($format,'aa'))===false)
				$this->_error($format." : Les années n'ont pas été trouvés... Les années doivent être précisés par 'aaaa' ou par 'aa' (ex: jj/mm/aaaa)");
		}
		$h[0]=2;
		if (($h[1]=strpos($format,'hh'))===false)
			$h[0]=1;
			if (($h[1]=strpos($format,'h'))===false)
				$this->_error($format." : Les heures n'ont pas été trouvées... Les heures doivent être précisées par 'hh' ou 'h' (ex: jj/mm/aaaa hh:ii:ss)");
		$i[0]=2;
		if (($i[1]=strpos($format,'ii'))===false)
			$i[0]=1;
			if (($i[1]=strpos($format,'i'))===false)
				$this->_error($format." : Les minutes n'ont pas été trouvées... Les minutes doivent être précisées par 'ii' ou 'i' (ex: jj/mm/aaaa hh:ii:ss)");
		$s[0]=2;
		if (($s[1]=strpos($format,'ss'))===false)
			$s[0]=1;
			if (($s[1]=strpos($format,'s'))===false)
				$this->_error($format." : Les secondes n'ont pas été trouvées... Les secondes doivent être précisés par 'ss' ou 's' (ex: jj/mm/aaaa hh:ii:ss)");
		$dat['jj']	=($j[1]!==false)?floatval(substr($dat['origine'],$j[1],$j[0])):1;
		$dat['mm']	=($m[1]!==false)?floatval(substr($dat['origine'],$m[1],$m[0])):1;
		$dat['aaaa']	=($a[1]!==false)?floatval(substr($dat['origine'],$a[1],$a[0])):1970;
		if ($a[0]==2)
			$dat['aaaa']=floatval(substr(date('Y'),0,2).$dat['aaaa']);
		$dat['hh']	=($h[1]!==false)?floatval(substr($dat['origine'],$h[1],$h[0])):0;
		$dat['ii']	=($i[1]!==false)?floatval(substr($dat['origine'],$i[1],$i[0])):0;
		$dat['ss']	=($s[1]!==false)?floatval(substr($dat['origine'],$s[1],$s[0])):0;
		return true;
	}
	function _error($str) {
		$this->errno[]=$str;
		return true;
	}
}
?>

Voici aussi un petit exemple pour tester :

php
<?php
include("date.class.php");
echo '<pre>';
$a=new dateOp(date('Y.m-d His'),'aaaa.mm-jj hhiiss');
$a->AjouteJours(-800);
echo $a->GetDate('h:i:s jj-mm-aaaa')."\n";
print_r($a->DiffenrenceEntreDate('10/03/1992','jj/mm/aaaa'));
print_r($a->errno);
echo '</pre>';
?>


20/07/2006 12:03 -

Discussion

Benoit, 30/12/2006 12:28:

Impeccable ! ça marche.

 
kechemir younes, 29/05/2007 12:49:

merçi

 
yohann, 01/08/2007 23:49:

Ca ne fonctionne pas pour les heures. (testé sur 2 serveurs)

 
iDo, 02/08/2007 08:26:

Soit plus précis, qu'est ce qui ne marche pas ?
Montre nous un exemple..
Peut-être utilise tu mal la classe ?

 
Stéphane, 22/08/2007 15:13:

Hello, j'ai essayé, pas mal, mais ça fonctionne mieux si on change ces deux lignes dans la fonction de différence de date…

php
$d1=mktime($this->dat['hh'],$this->dat['ii'],$this->dat['ss'],$this->dat['mm'],$this->dat['jj'],$this->dat['aaaa']);
$d2=mktime($this->dat2['hh'],$this->dat2['ii'],$this->dat2['ss'],$this->dat2['mm'],$this->dat2['jj'],$this->dat2['aaaa']);

Les minutes , c'est 'ii' et non pas 'mm'.

A pluche…

 
iDo, 22/08/2007 17:25:

En effet !
erreur de copier coller !
Je viens de mettre a jour les sources !
Merci !

 
adrien, 28/08/2007 11:56:

Bonjours j'aimerai savoir s'il est possible via ce code de calculer la différence entre 2 heures au lieu de 2 date? Si oui comment puis je procéder?

 
iDo, 28/08/2007 19:37:

Salut !
Ce n'était pas possible.
Par contre, je viens de mettre a jour le fichier et maintenant tu peu le faire.
il suffit d'utiliser une date identique en ne faisant varier que l'heure.
Par exemple, pour calculé la différence entre 12h30:25 et 18h15h22 tu pourrais faire :

php
echo '<pre>';
$a=new dateOp('01/01/1970 12:30:25','jj/mm/aaaa hh:ii:ss');
print_r($a->DiffenrenceEntreDate('01/01/1970 18:15:22','jj/mm/aaaa hh:ii:ss'));
print_r($a->errno);
echo '</pre>';

Il est juste important de prendre la même date pour la 1ere et la 2eme heures.

 
adrien, 29/08/2007 18:31:

Merci pour ta réponse mais j'avais trouvé la solution de mon coter ^^ Par ailleur j'avais du modifier le fichier date.class.php au niveau de la ligne 56 mais je vois que tu as toi aussi modifié cette ligne afin de récupérer les valeurs dans le tableau ^^ Ton script est très bien monté mais je ne comprends pas pourquoi il faut mettre -1970 à ans et -1 à mois , jour et heure?

 
jeanpierre, 18/10/2007 13:57:

A cause de la fonction mktime qui renvoie un timestamp Unix, soit le temps écoulé depuis le début de l'époque Unix, qui est le 01/01/1970 à 0h00 heure GMT, donc à 1h00 heure française -puisque l'heure d'été n'avait aps été rétablie à cette époque et de de toute façon on aurait été en heure d'hiver ;o)-.

 
jeanpierre, 18/10/2007 16:11:

A cause de la fonction mktime qui renvoie un timestamp Unix, soit le temps écoulé depuis le début de l'époque Unix, qui est le 01/01/1970 à 0h00 heure GMT, donc à 1h00 heure française -puisque l'heure d'été n'avait aps été rétablie à cette époque et de de toute façon on aurait été en heure d'hiver ;o)-.

 
jeanpierre, 18/10/2007 16:14:

Désolé du doublon, j'ai rechargé la page sans faire gaffe…

 
Slayer418, 18/10/2007 05:29:

marche pas chez multimania.lycos.fr , j'ai copie marquer

<php $madate=new dateOp(“14/07/2006 12:30”,”jj/mm/aaaa hh:ii”1;; echo($madate) ?>

Et ca me sorte Parse error: syntax error, unexpected T_LNUMBER in /data/members/free/multimania/fr/s/l/a/slayer418/htdocs/date2.php on line 2

 
Slayer418, 18/10/2007 05:37:

Non enfaite y'avais une erreur d'affichage sur le site (ici) parce que depuis que j'ai envoyer mon dernier message (la page s'est reloadé)

se n'est plus marquer ca: $madate=new dateOp(“14/07/2006 12:30”,”jj/mm/aaaa hh:ii”1;; mais ca: $madate=new dateOp(“14/07/2006 12:30”,”jj/mm/aaaa hh:ii”);

Bisard non mais bon ca marche toujours pas sur multimania.lycos.fr DateOp n'est pas une fonction défini

 
ka23y, 25/10/2007 14:36:

J'ai constaté un beug sur cette classe: lorsqu'on instancie un objet à la date du 31 janvier et qu'on souhaite lui ajouter 1 mois on obtiens le 31 Décembre 1999 ! Il serait plus logique d'obtenir le 28 ou 29 Février de la même année, suivant qu'il s'agisse d'une année bissextile ou non.

Le code en question : $madate = new dateOpPerso(“31/01/2007 12:30”, “jj/mm/aaaa hh:ii”); $madate→AjouteMois(1); echo $madate→GetDate('h:i:s jj-mm-aaaa');

=⇒ 0:00:00 31-12-1999

Je conseille aux personnes qui souhaitent faire des traitements avancés sur les dates de regarder du coté du framework Zend, qui gère une classe Zend_Date, et qui prends en compte toutes les petites subtilités des dates.

 
iDo, 26/10/2007 08:42:

Salut, je viens de copier/coller ton code et j'obitens :
12:30:00 03-03-2007
Ce qui me parais normal puisque un mois de plus donnerais le 31 février, php compense automatiquement et se place en mars.
Je ne comprend pas comment tu a obtenu 31-12-1999
Quel version de php utilise-tu ?

 
Noodle Juice, 21/01/2008 10:46:

C'est bien mais plein de bug …

code :

<?php include(“date.class.php”);

$madate=new dateOp('01/01/2007','jj/mm/aaaa');

print_r($madate→DiffenrenceEntreDate('01/01/2009','jj/mm/aaaa')); ?>

Résultat :

Array ( [ans] ⇒ 2 [mois] ⇒ 0 [jours] ⇒ 1 [joursTotal] ⇒ 731 [heures] ⇒ 0 [minutes] ⇒ 00 [secondes] ⇒ 00 )

D'où vient le 1jour ???? Ta classe ne prend pas en compte les années bisextilles je pense. tu te bases sur le nombre de jour et tu divises par 365 pour avoir le nombre d'année ??

J'ai pas eu envie de ragarder ton code mais je pense qu'il y a des problèmes à droite et à gauche.

 
iDo, 21/01/2008 16:37:

Salut,
non non il n'y a pas de -365 de fait.
Les opérations se font via les fonctions native de php.
Les données renvoyées sont celles fournis par date
En effet, la logique voudrait que l'on affiche 2 ans (dont une année bissextile)
Mais je ne vois pas comment exprimer ça clairement dans un retour de fonction.
En revanche, 2 années (dite normales) + 1 jours pour l'année bissextile, ça correspond bien.
D'autant que 365+365+1=365+366=731, le compte est bon.

 
elarsoft.com, 14/02/2008 11:49:

salut, en fait je crois que ça marche pas (la soustraction) pour les dates < 1940 ? exemple(2008 et 1920).

 
Psychoblade, 14/02/2008 14:48:

Pour le cas où l'on voudrait avoir des jours dégatifs pour la différence entre date, donc pour savoir si c'est avant ou après la date de référence. il convient de modifier le code comme ceci:

if ($d2>$d1) $d=d1; else $d=-(d2); // modification pour avoir des jours négatifs

 
lelectronique, 14/03/2008 11:50:

bonjour, j'ai voulu installer ce petit script qui à l'air d'être très pratique mais j'obtiens l'erreur suivante : Catchable fatal error: Object of class dateOp could not be converted to string in D:\Site\rebelco\admin\test\test.php on line 121 voici le code de la ligne 120 et 121: echo $date_encours = date(“Y-m-d H:i:s”); echo $madate=new dateOp($date_encours,”aaaa-mm-jj hh:ii:ss”); merci pour votre aide, test en local avec easyphp 2

 
iDo, 14/03/2008 14:58:

Salut,
C'est le “echo” devant $madate qui pose probleme…
Tu ne peu pas faire un echo d'un objet…
A la limite un print_r… mais pas un echo.

 
nicolas, 09/04/2008 19:53:

Bonjour je cherchais ce type de fonction!

cependant je ne dois pas tres tres fort je n'arrive pas a recuperer les valeur du tableau [ans] [mois] [jours] [jourstotal] dans des variable qqun pourrai m'aider?

merci

 
iDo, 10/04/2008 10:56:

salut, Par exemple :

php
list($ans,$mois,$jours,$joursTotal,$heures,$minutes,$secondes)=$madate->DiffenrenceEntreDate('11/04/2000','jj/mm/aaaa');
echo $ans;
 
julien, 22/04/2008 13:45:

bonjour très bon script c'est ce que je cherchais! mais apperement il ne gère plus les dates au dela de 2037 lorsque j'ajoute trop de jour a une date il me sort 01-01-1970 ou 31-12-1969 ou desfois nimporte quoi es ce normal? ou es ce qu'il y a une solution? ju

 
iDo, 22/04/2008 14:36:

salut,
il s'agit d'une limitation des OS 32bit (probablement que sur un 64bit ça ira plus loin).
trouvé sur php.net :
“L'intervalle de validité d'un timestamp va généralement du Vendredi 13 Décembre 1901 20:45:54 GMT au Mardi 19 Janvier 2038 03:14:07 GMT. (Ces dates correspondent aux valeurs minimales et maximales des entiers 32 bits non-signés). Cependant, avant PHP 5.1.0, cette intervalle va du 01-01-1970 au 19-01-2038 sur quelques systèmes (e.g. Windows).”

 
mouna/sos, 14/05/2008 14:24:

bonjour,je vous remercie vraiment pour cette classe qui simplifie les operations sur les dates mais j'ai un probleme je serai heureuse si tu m'aider pour trouver la solution. j'ai une bdd avec un chomp date de type caractere(char 12)de la forme “jj/mm/aaaa” et j 'ai essayé d'utiliser la fonction function DiffenrenceEntreDate($dat,$format=“jj/mm/aaaa”) pour comparer entre date systeme et date extraite de la bdd(donc est variable) mais pour quoi cette constante '10/03/1992' dans la fonction et j'ai pas pu la remplacer par date extraite de la bdd($madat) exempl:

<?php include(“date.class.php”); echo '<pre>'; $a=new dateOp(date('Y.m-d His'),'aaaa.mm-jj hhiiss'); $a→AjouteJours(-800); echo $a→GetDate('h:i:s jj-mm-aaaa').”\n”; print_r($a→DiffenrenceEntreDate('$madat','jj/mm/aaaa')); print_r($a→errno); echo '</pre>'; ?>

Merci…..

 
iDo, 14/05/2008 16:00:

salut,
Enlève les simple quote autour de $madat, ça fonctionnera mieux :)
Php n'évalue le contenu des variable que si elle se trouve entre double quote. Par entre simple quote.
$a→DiffenrenceEntreDate($madat,'jj/mm/aaaa')

 
Si vous ne pouvez pas lire les lettres, tlchargez ce fichier WEV et coutez les.