Nombre de mois entre 2 dates

Soyez le premier à donner votre avis sur cette source.

Snippet vu 20 319 fois - Téléchargée 32 fois

Contenu du snippet

Enfin une fonction en php pour ce problème. J'ai pas encore testé à fond car je dois cette fonction à Grenard que je salue au passage !

Pour ma part j'avais initalement présenté un moyen de calculer le nb de mois entre 2 date grace à mysql, je laisse donc ces qq lignes, au cas ou.

Source / Exemple :


// La fonction qui utilise seulement php (il semblerait que ca aille à peu près 4x plus vite que la fct mysql... meme en local)

function datediff($a,$b)
{
$date1 = intval(substr($a,0,4))*12+intval(substr($a,4,2));
$date2 = intval(substr($b,0,4))*12+intval(substr($b,4,2));
return abs($date1-$date2); //abs pour éviter les résultas négatifs suivant l'ordre des arguments de la fonction
}
echo datediff('200402','200312'); // les arguments sont YYYYMM, dans cet exemple : février 2004 et décembre 2003

--> ici le résultat est 2

--------------------------------------------------------

// Pour le plaisir des yeux (!!!) et peur ceux qui aiment mysql, comme moi, la fonction identique :

// la requete sql
$sql_select_interval="SELECT PERIOD_DIFF(200402,200312) AS nb_de_mois;"; // arguments au format YYMM ou YYYYMM, ici février 2004 et décembre 2003
$req_interval= mysql_query($sql_select_interval) or die('Erreur SQL !<br>'.$sql_select_interval.mysql_error());	
if($data_interval= mysql_fetch_assoc($req_interval))
	{
	echo "Nombre de mois entre les deux dates: ".abs($data_interval['nb_de_mois']); // ici ca donne 2, j'ai mis abs sinon, suivant l'ordre des dates ca donne -2
	}

Conclusion :


moi j'utilise cette fonction pour savoir depuis combien de mois est ouvert mon site pex. Ca pourrait aussi servir à faire des statistics genre "nb moyen de visiteurs par mois" ou "chiffre d'affaire moyen mensuel" calculé tout au long de l'année. bref

A voir également

Ajouter un commentaire

Commentaires

nihilis
Messages postés
2
Date d'inscription
vendredi 4 mars 2005
Statut
Membre
Dernière intervention
18 juillet 2006

Merci beaucoup RDave pour cette petite fonction, elle m'a evité une bonne heure de crise de nerfs.
cs_GRenard
Messages postés
1662
Date d'inscription
lundi 16 septembre 2002
Statut
Membre
Dernière intervention
30 juillet 2008
1
intval permet de passer une chaine de caractères en type integer... (entier).
Pourquoi faire ca ? ca se fait tout seul tu vas me dire ! mais c'est mieux de programmer ainsi de de définir ses types correctement.

Pour la vitesse de mySQL je ne prouve rien... il est plus lent tout simplement, je ne dis pas que c'est 4x plus lent ! Parce que sur un autre ordi, ca pourrait être seulement 2x ou 6x on sait pas...
RDave
Messages postés
30
Date d'inscription
vendredi 9 avril 2004
Statut
Membre
Dernière intervention
19 novembre 2007

ah ouais...

aurais-tu gagné mon estime =)

je teste, à première vue ca à l'air de jouer.. par contre je pige pas à quoi sert intval ?

merci pour ta fontion en tout cas, si elle fonctionne bien je la mets dans ma source.

pour le benchmark, intéressant, tu prouve que mysql est 4x plus lent que php pour une fonction date... ETONNANT
je ferai aussi mes tests, d'ailleurs à l'occaz avec oracle aussi

@ plus
cs_GRenard
Messages postés
1662
Date d'inscription
lundi 16 septembre 2002
Statut
Membre
Dernière intervention
30 juillet 2008
1
Ok regarde bien tit gars, moi je n'ai pas toujours que ca à faire programmer et trouver des choses qui existent déjà en plus ! Si tu cherches bien sur php.net bah tu trouves la solution facile à ton problème...
Ensuite, pour te faire plaisir, je l'ai fait ton benchmark... Je veux juste rajouter par contre que avec mySQL si tu n'est pas sur le même serveur, ca te fait utiliser de la bandwidth pour ton site web (ce qui est généralement compté sur un hébergement pro). (Oh et pour faire des benchmark, j'ai mis des apostrophe plutot que des guillemets à ton truc la...)

Windows, mySQL distant (10000 itérations) :
PHP : 1.75sec
mySQL : 9.05sec

Linux RedHat9, mySQL local (10000 itérations) :
PHP : 1.31sec
mySQL : 1.23sec

Donc, ce qui faut en tirer, c'est que la fonction PHP que j'ai fournie LA est beaucoup plus complète que celle de mySQL... donc ici c'est normal que cela soit un peu plus lent...
Par contre, côté mySQL tu vois bien que si tu n'est pas connecté en local c'est extrèmement plus long. Mais je persiste à dire que php est beaucoup plus rapide que mySQL... car tu vois ici la différence est très minime (même pas 10 centième) et la fonction PHP est plus complète.

J'ai réessayer la même chose avec une fonction nowhere super petite...
Avec ce nouveau code regarde le benchmark que ca me fait :
0.34 secondes

Alors c'est lequel le plus rapide ? cette fonction fait bel et bien ce que tu désirais en plus...


Donc j'espère que ma réponse ne va pas être critiqué dans le sens que je réponds mal, parce que j'ai passé pas mal de temps à faire ca la !



Fonction 1 (de PHP.net) :
<?php

//-----------------------------------------------------------
function date_diff($date_from,$date_to,$unit='d')
/*
Calculates difference from date_from to date_to, taking into account leap years
if date_from > date_to, the number of days is returned negative
date_from and date_to format is: "dd-mm-yyyy"
It can calculate ANY date difference, for example between 21-04-345 and 11-11-3412
This is possible by mapping any date to the "range 0" dates, as this table shows:

INI END RANGE LEAP YEARS
... ... ... ...
01/01/1920 01/01/1939 -3 5
01/01/1940 01/01/1959 -2 5
01/01/1960 01/01/1979 -1 5
01/01/1980 01/01/1999 0 5 * this is the range used for calculations with mktime
01/01/2000 01/01/2019 1 5
01/01/2020 01/01/2039 2 5
01/01/2040 01/01/2059 3 5
01/01/2060 01/01/2079 4 5
... ... ... ...

The difference is calculated in the unit specified by $unit (default is "days")
$unit:
'd' or 'D' = days
'y' or 'Y' = years
*/

{
//get parts of the dates
$date_from_parts = explode('-', $date_from);
$date_to_parts = explode('-', $date_to);
$day_from = $date_from_parts[0];
$mon_from = $date_from_parts[1];
$year_from = $date_from_parts[2];
$day_to = $date_to_parts[0];
$mon_to = $date_to_parts[1];
$year_to = $date_to_parts[2];

//if date_from is newer than date to, invert dates
$sign=1;
if ($year_from>$year_to) $sign=-1;
else if ($year_from==$year_to)
{
if ($mon_from>$mon_to) $sign=-1;
else if ($mon_from==$mon_to)
if ($day_from>$day_to) $sign=-1;
}

if ($sign==-1) {//invert dates
$day_from = $date_to_parts[0];
$mon_from = $date_to_parts[1];
$year_from = $date_to_parts[2];
$day_to = $date_from_parts[0];
$mon_to = $date_from_parts[1];
$year_to = $date_from_parts[2];
}

switch ($unit)
{
case 'd': case 'D': //calculates difference in days
$yearfrom1=$year_from; //actual years
$yearto1=$year_to; //(yearfrom2 and yearto2 are used to calculate inside the range "0")
//checks ini date
if ($yearfrom1<1980)
{//year is under range 0
$deltafrom=-floor((1999-$yearfrom1)/20)*20; //delta t1
$yearfrom2=$yearfrom1-$deltafrom; //year used for calculations
}
else if($yearfrom1>1999)
{//year is over range 0
$deltafrom=floor(($yearfrom1-1980)/20)*20; //delta t1
$yearfrom2=$yearfrom1-$deltafrom; //year used for calculations
}
else {//year is in range 0
$deltafrom=0;
$yearfrom2=$yearfrom1;
}

//checks end date
if ($yearto1<1980) {//year is under range 0
$deltato=-floor((1999-$yearto1)/20)*20; //delta t2
$yearto2=$yearto1-$deltato; //year used for calculations
}
else if($yearto1>1999) {//year is over range 0
$deltato=floor(($yearto1-1980)/20)*20; //delta t2
$yearto2=$yearto1-$deltato; //year used for calculations
}
else {//year is in range 0
$deltato=0;
$yearto2=$yearto1;
}

//Calculates the UNIX Timestamp for both dates (inside range 0)
$ts_from = mktime(0, 0, 0, $mon_from, $day_from, $yearfrom2);
$ts_to = mktime(0, 0, 0, $mon_to, $day_to, $yearto2);
$diff = ($ts_to-$ts_from)/86400;
//adjust ranges
$diff += 7305 * (($deltato-$deltafrom) / 20);
return $sign*$diff;
break;

case 'y': case 'Y': //calculates difference in years
$diff=$year_to-$year_from;
$adjust=0;
if ($mon_from>$mon_to) $adjust=-1;
else if ($mon_from==$mon_to)
if ($day_from>$day_to) $adjust=-1;

return $sign*($diff+$adjust);
break;
}
}
?>

Fonction 2 (celle qui s'adapte à ton besoin) :
function datediff($a,$b){
$date1 = intval(substr($a,0,4))*12+intval(substr($a,4,2));
$date2 = intval(substr($b,0,4))*12+intval(substr($b,4,2));
return $date1-$date2;

}
datediff('200402','200312');
RDave
Messages postés
30
Date d'inscription
vendredi 9 avril 2004
Statut
Membre
Dernière intervention
19 novembre 2007

Je dis pas que c'est pas faisable en php, juste que ca a l'air (et finallement c'est !) plus compliqué que d'utiliser la fct toute fairte de mysql.

Je suis certain que c'est faisable en php, je crois d'ailleurs que je suis sur la bonne voie...
en tout cas, et c'est bien ce qui m'intéresse sur ce coup-là, c'est plus facile en php ou mysql ? je suis meme partant pour benchmarker les 2 solutions, quand y en aura, et voir qui va le plus vite =)

Je continue sur la fct php et ne manquerai pas de mettre à jour la source si une solution se profile !

Grenard : on cause on cause, mais j'attends tjr ta proposition !

malalam : vois pas une fct php est plus pratique qu'une utilisant mysql ? je me pencherai sur ta fonction dès que j'ai le temps !

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.