begin process at 2012 05 28 14:20:26
  Trouver un code source :
 
dans
 
Accueil > Forum > 

PHP

 > 

Server Web

 > 

Apache

 > 

Calcul de dates avec PHP


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

Calcul de dates avec PHP

dimanche 3 octobre 2010 à 16:47:12 | Calcul de dates avec PHP

Renald689

Bonjour,


Pour un site web que je suis en train de développer, j'ai besoin de lister toutes les dates comprises dans une période. Sur la première page l'utilisateur saisi une date de début et une date de fin et valide le formulaire. Sur la page de résultat les dates allant de "date_deb" à "date"fin" inclus sont affichées avec un retour chariot entre chaque. (bon en réalité c'est beaucoup plus compliqué, mais je simplifie). Les dates doivent être saisies et affichées au format "Y-m-d" pour être compatible avec ma base SQL.

Mon problème est que certaines dates sont affichées en double dans mon résultat et d'autres manquent. Et bien sur ce ne serait pas drole si le problème était fixe : c'est totalement aléatoire :

Exemple 1 : je demande les dates du 2010-01-01 au 2010-12-31 : aucun problème, j'ai bien 365 dates toutes différentes.
Exemple 2 : je demande les dates du 2010-08-17 au 2010-09-14 : aucun problème, j'ai bien 29 dates toutes différentes
Exemple 3 : je demande les dates du 2011-06-01 au 2011-12-20 : j'ai bien 203 dates, ce qui pourrait paraitre normal, mais en regardant de plus près, je me rend compte que la liste s'arrete au 2011-12-19 et que le 2011-30-10 apparait 2 fois.
Exemple 4 : je demande les dates du 2010-06-01 au 2010-12-31 : même chose que l'exemple 3, mais c'est le 2010-12-31 qui manque et le 2010-10-31 qui est en double.

Voici le code de ma page de résultat :

Code PHP :
<?php
	include("enteteshtml.php") ;

	echo '


	<div id="corps">';


	$date_deb = $_POST['date_deb'];
	$date_fin = $_POST['date_fin'];

	$date_debunix = strtotime($date_deb);
	$date_finunix = strtotime($date_fin);

	for($aunix = $date_debunix; $aunix <= $date_finunix; $aunix = $aunix+86400)
	{
		$a = date('Y-m-d', $aunix);
		echo $a.'<br>';
	}
	echo '

	</div>
</body>

</html>
';

?>


Je vous ai même mis le bouzin en ligne pour tester par vous même si ça peut vous aider à m'aider : http://macqueron.fr/help/

Est-ce que quelqu'un a une idée d'où cela peut venir ? Je ne pense pas avoir fait d'erreur dans le code et je n'ai trouvé aucun bug recensé sur le web qui parle de ça. Bref, je patauge...

--
Rénald
dimanche 3 octobre 2010 à 17:39:35 | Re : Calcul de dates avec PHP

Renald689

Re-bonjour,


J'avance dans l'analyse de mon problème, et j'ai eut l'idée de modifier mon code comme ceci pour voir ce qui se passe exactement :

Code PHP :
<?php
	include("avantcorps.php") ;

	echo '


	<div id="corps">';


	$date_deb = $_POST['date_deb'];
	$date_fin = $_POST['date_fin'];

	$date_debunix = strtotime($date_deb);
	$date_finunix = strtotime($date_fin);

	for($aunix = $date_debunix; $aunix <= $date_finunix; $aunix = $aunix+86400)
	{
		$a = date('Y-m-d H:i', $aunix);
		echo $a.' = '.$aunix.'<br>';
	}
	echo '

	</div>
</body>

</html>
';

?>


On se rend donc bien compte que la date Unix est bien incrémentée de 86400 à chaque fois, y compris quand le problème se pose, mais il semblerait que ce soit la conversion au format "Y-m-d" qui pose problème... Je relis la page de manuel PHP sur la fonction "date" mais je ne vois rien qui me mette sur la voix

--
Rénald
dimanche 3 octobre 2010 à 18:07:08 | Re : Calcul de dates avec PHP

Renald689

Réponse acceptée !
Me revoilà une dernière fois : j'ai trouvé tout seul finalement et le problème vient des deux changements d'heure annuels. J'ai donc mis une rustine à mon code mais ça ne me plait pas beaucoup :

Code PHP :
<?php
	include("avantcorps.php") ;

	echo '


	<div id="corps">';


	$date_deb = $_POST['date_deb'];
	$date_fin = $_POST['date_fin'];

	$date_debunix = strtotime($date_deb)+43200;
	$date_finunix = strtotime($date_fin)+43200;

	for($aunix = $date_debunix; $aunix <= $date_finunix+3600; $aunix = $aunix+86400)
	{
		$a = date('Y-m-d H:i', $aunix);
		echo $a.' = '.$aunix.'<br>';
	}
	echo '

	</div>
</body>

</html>
';

?>


Si quelqu'un a quelque-chose de mieux à me proposer, je suis intéressé.

--
Rénald
dimanche 3 octobre 2010 à 19:47:38 | Re : Calcul de dates avec PHP

neigedhiver

Salut,

Depuis PHP5.1, ne pas préciser le fuseau horaire provoque une erreur.
As-tu essayé de le préciser ? Spécifier le fuseau horaire permet de prendre en compte, dans les calculs de date et heure, le changement d'heure été/hiver (DST).

Exemple :
Code PHP :
<?php
date_default_timezone_set('Europe/Paris');
$debut = strtotime('10/31/2010 01:00');
$fin = strtotime('10/31/2010 04:00');
$diff = $fin - $debut;
echo $diff;
?>

Ce code affichera 14400, en secondes, soit 4h. Ce qui est bien le temps véritablement écoulé, puisqu'à 3h il sera de nouveau 2h...

--
Neige

Souvent la réponse à votre question se trouve dans la doc. Commencez par là ;)
lundi 4 octobre 2010 à 06:04:16 | Re : Calcul de dates avec PHP

jeca

Bonjour,

Personnellement, je trouve plus simple d'utiliser la classe "DateTime" qui existe depuis PHP 5.1.
Essaie ce code :
Code PHP :
<?php
  function calculDate($deb, $fin)
  {
    $tableauDate = array();
    $dateDeb = new DateTime($deb);
    while($deb <= $fin)
    {
      $tableauDate[] = $deb;
      $dateDeb -> modify('+ 1 day');
      $deb = $dateDeb -> format('Y-m-d');
    }
    return $tableauDate;
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  if(isset($_POST['btn']))
  {
    echo implode('<br />', calculDate($_POST['dateDeb'], $_POST['dateFin']));
  }
  else
  {
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <script type="text/javascript"></script>
    <style type="text/css"></style>
  </head>
  <body>
    <form name="date" method="post" action="">
      Date début (AAAA-MM-JJ)&nbsp;<input type="text" name="dateDeb" value="" /><br />
      Date fin (AAAA-MM-JJ)&nbsp;<input type="text" name="dateFin" value="" /><br />
      <input type="submit" name="btn" value="valider" />
    </form>
  </body>
</html>
<?php } ?>

C'est un tout petit peu plus long à l'exécution (l'écart se situe au niveau du millième de seconde), mais pas besoin de se préoccuper du fuseau horaire ni des changements d'heure ni des années bissextiles (dans ce cas particulier, qui ne réclame qu'une liste de jours).

Cordialement.

JC
lundi 4 octobre 2010 à 09:20:40 | Re : Calcul de dates avec PHP

syndrael

Comme Jeca.. on goute une fois aux DateTime, on se prend la tête dessus qqs fois mais fini les questions existencielles sur la gestion et autres fonctions..
S.
lundi 4 octobre 2010 à 09:22:49 | Re : Calcul de dates avec PHP

neigedhiver

@jeca : faux. Avec ton code, j'obtiens :

Code PHP :
Fatal error: Uncaught exception 'Exception' with message 'DateTime::__construct(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function.


C'est bien quand on n'affiche pas les erreurs, mais on ne les voit pas...

Conclusion : il faut TOUJOURS se préoccuper du fuseau horaire, sinon PHP ne sait pas comment calculer les heures.

--
Neige

Souvent la réponse à votre question se trouve dans la doc. Commencez par là ;)
lundi 4 octobre 2010 à 20:04:00 | Re : Calcul de dates avec PHP

Renald689

Bonjour,

Merci pour l'info sur le fuseau horaire neigedhiver, mais celà ne resoud pas le problème : j'ai fait un test en enlevant ma rustine et en mettant le fuseau horaire, et le problème reste le même.

Je garde l'idée du DateTime pour la fin de mon projet, au moment de l'optimisation, parce que pour l'instant ça me parait un peu compliqué à mettre en oeuvre. Donc je reste avec ma rustine pour l'instant.

--
Rénald
lundi 4 octobre 2010 à 21:35:39 | Re : Calcul de dates avec PHP

neigedhiver

L'origine du problème est assez simple à identifier : c'est le passage à l'heure d'hiver.
A partir de là, décortiquons ce qui se passe.
Je ne sais pas dans quel format tu passes la date de début et de fin, mais je suppose, puisque tu souhaites compter des jours, que tu passes une date sans heure. Donc, par défaut, PHP considère que c'est à 00h00:00.
Au passage à l'heure d'hiver en 2010, le 30 octobre, à 3h, il sera de nouveau 2H. La journée du 30 octobre ne compte pas 24h, mais 25. Donc si tu ajoutes 24h à minuit, il est au final... 23h, toujours le 30 octobre 2010. Donc, tu as 2 fois la même date.
Et au final, ta comparaison dans ta boucle ne sera pas satisfaite la fois qui manque (il manquerait 3600 pour que la boucle soit exécutée une fois de plus). Donc, il te manque la dernière date.

La conclusion, c'est que pour calculer des dates, il faut utiliser... des dates. Et pas des secondes.
Au lieu d'ajouter 86400 secondes, il convient d'ajouter des jours... Tu commences avec un compteur à 0 et tu recalcules la date avec strtotime() en ajoutant litéralement le nombre de jours à la date (puisque PHP est capable de calculer ça). Voici un exemple :

Code PHP :
<?php

date_default_timezone_set('Europe/Paris');
$deb_date = '2010-10-01';
$deb = strtotime($deb_date);
$fin = strtotime('2010-11-30');
$curr = $deb;
for ($i = 1; $curr < $fin; $i++) {
	echo date('d-m-Y', $curr), '<br />';
	$curr = strtotime($deb_date.' +'.$i.'days');
}

?>


Une autre solution consiste à prendre la date de début à midi (mais c'est quand même moins propre).

Pour ce qui est de l'utilisation de l'objet DateTime, voici un exemple commenté :

Code PHP :
<?php

$deb = '2010-10-01';
$fin = '2010-11-30';

// On isntancie un nouvel objet DateTime, avec la date de début et le fuseau horaire CET.
$d = new DateTime($deb , new DateTimeZone('Europe/Paris'));

// On crée un objet DateInterval qui correspond à un intervalle d'une journée
// P1D : P pour Period, 1D pour 1 day.
// Cf la liste des paramètres : http://fr2.php.net/manual/fr/dateinterval.construct.php
$di = new DateInterval('P1D');

//On boucle jusqu'à ce que la date de $d soit celle de $fin
while ($d -> format('Y-m-d') != $fin) {
	echo $d -> format('Y-m-d'), '<br />';
	// On ajoute l'intervalle de 1 jour
	$d -> add($di);
}
// On affiche la dernière date
echo $d -> format('Y-m-d');

?>

Dans ce bout de code, le test n'est pas suffisament rigoureux, puisque si la date de fin donnée est antérieure à la date de début, on aura une boucle sans fin. C'est juste pour illustrer le fonctionnement.

J'espère que tu fera bon usage de tout ça, il est assez rare que je prenne autant de temps pour une réponse ;)

--
Neige

Souvent la réponse à votre question se trouve dans la doc. Commencez par là ;)
mardi 5 octobre 2010 à 03:33:14 | Re : Calcul de dates avec PHP

jeca

@neigedhiver

DateTime::__construct(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function.


traduction : Faire confiance aux paramètres timezone du système n'est pas fiable. Il est préférable d'utiliser le paramètre date.timezone (php.ini) ou la fonction date_default_timezone_set().

Donc, pas grand chose à voir avec un problème de code.

Conclusion : il faut TOUJOURS se préoccuper du fuseau horaire, sinon PHP ne sait pas comment calculer les heures.

Faux, puisque le paramètre "timezone" du constructeur "DateTime" est optionnel. Par défaut, celui du php.ini est pris en compte.

Au passage à l'heure d'hiver en 2010, le 30 octobre, à 3h, il sera de nouveau 2H. La journée du 30 octobre ne compte pas 24h, mais 25. Donc si tu ajoutes 24h à minuit, il est au final... 23h, toujours le 30 octobre 2010. Donc, tu as 2 fois la même date.


Faux. L'ajout dans le code n'est pas de 24 heures mais de 1 jour, c'est à dire : 31 oct. + 1 jour = 1er nov.
Petite rectification : Le changement d'heure est le 31 à 3 heures.

Pour finir, l'objet "DateInterval" et la méthode "add" n'existent que depuis PHP 5.3, ce que tout le monde n'a pas (PHP 5.1 non plus, peut-être).

Cordialement.


1 2

Cette discussion est classée dans : fin, date, exemple, dates, deb


Répondre à ce message

Sujets en rapport avec ce message

Comparer des dates [ par Blondy ] Je voudrais comparer des dates pour savoir quel fichier est le plus vieux... Mais lorsque je crée une date avec date("dmy"); par exemple, ça me crée q histoire de dates [ par LaTatadu91 ] Salut (encore pr certains) voila je fais un formulaire avec saisie de dates de départ et date de fin afin de pouvoir faire un checkdate j'ai decider d afficher les dates d'une date de début a une date de fin [ par laura1409 ] bonjourje suis en train de réaliser un site internet en php qui permet la gestion de planning de formationje travaille en ce moment sur la mise en for Différence entre deux dates [ par BiBloOo ] Bonjour a tous !!En cherchant comment faire une différence entre deux dates, je suis tombé sur plusieurs choses dont ce lien ==>http://www.phpcs.com/c Faire une suite d'insctruction à une date précise en php [ par Shikapowa ] Mesdames Mesdemoiselles Messieurs bonjour,Alors qu'il pleut intensément dehors, j'essaie de me consoler avec mon projet dans mon bureau et après moult probleme passage entre les annees [ par nader19 ] salut  . je galere depuis logntemps dans un projet et quand j'ai cru ça termine je tombe sur un beugbref mon beug cette fois çi j'ai decovert c'est pa petit soucis sur PHP/JS [ par oliopur ] Voici les p'tit problemes : Sur une base de donnée j'ai un champ qui contient la date et l'heure de suppression future d'un enregistrement sous la for [PHP] Claculer les date entre deux date [ par michaelminelli1 ] Bonjour, Pourriez vous m'aider car je cherche un bout de code PHP qui me permet de lister toute les dates entre dates connue (borne comprise) par ex comparaison dates [ par noussaa19 ] Bonjour, j'ai un problème dans mon code php je veux comparer 2 dates dont la première récupéré à partir d'une base de donnée mysql mais sous la forme recuperer toutes les dates superieurs a la date du jours [ par fatatra ] Bonjour a tous,je veux faire un truc tous simple apparement et pourtant je n'y arrive pas.Je veux lister toutes les dates contenues dans ma bdd superi


Nos sponsors


Sondage...

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 : 1,357 sec (4)

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