Calendrier mensuel

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Calendrier mensuel

par chrislabricole » 24 oct. 2008, 17:00

Justement ça passé passé pas à cause du &
il faut mettre & ;)

Là je suis en train de l'arranger à ma sauce, et j'ai complété les <td> qui manques à la fin pour que ça soit plus propre ;)

Merci encore !
NB: Je vous donne le code fini après hein :)

EDIT: Voilà ! J'ai fini de modifier ^^
Voilà le code complet et valide W3C ;)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Calendrier</title>
<style type="text/css">
.calendar tr, td { border:#4A4A4A 1px solid; text-align:center; }
.calendar td { width:25px; }
.calendar .caption,.navigation a:link,a:visited { font-weight:bold; }
.caption { text-align:center; }
.calendar .navigation a:link,a:visited { color:#333333; }
.calendar .head { background-color: #E1E1E1; }
.calendar .days_list { background-color: #EEEEEE; }
.calendar .days { background-color:#F9F9F9; }
</style>
</head>

<body>

<?php
date_default_timezone_set('Europe/Paris');

// french ; english
$language_selection = 'french';

### French
$calendar_txt['french']['mois'] = array('', 'Janvier', 'F&eacute;vrier', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Ao&ucirc;t', 'Septembre', 'Octobre', 'Novembre', 'D&eacute;cembre');
$calendar_txt['french']['jours'] = array('Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche');
$calendar_txt['french']['voc'] = array('Ann&eacute;e pr&eacute;c&eacute;dente', 'Mois pr&eacute;c&eacute;dent', 'Mois suivant', 'Ann&eacute;e suivante');
### English
$calendar_txt['english']['mois'] = array('', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October','November', 'December');
$calendar_txt['english']['jours'] = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday');
$calendar_txt['english']['voc'] = array('Last year', 'Last month', 'Next month', 'Next year');


// Récupére la date par GET ou date courante
$jourActuel = (int)( $_GET['jour'] ? $_GET['jour'] : date('d') );
$jourActuel = (int)( $jourActuel < 1902 ? date('d') : $jourActuel );
$jourActuel = (int)( $jourActuel > 2036 ? date('d') : $jourActuel );
$moisActuel = (int)( $_GET['mois'] ? $_GET['mois'] : date('m') );
$anneeActuelle = (int)( $_GET['annee'] ? $_GET['annee'] : date('Y') );

$nomMoisActuel = $calendar_txt[$language_selection]['mois'][$moisActuel];
$dateActuelle = strtotime( sprintf('%s-%s-%s', $anneeActuelle, $moisActuel, $jourActuel) );

// Récupére le nombre de jours dans le mois
$nbJoursMois = date('t', $dateActuelle);

// Menu de navigation annee/mois
$nextAnnee = date('Y', strtotime('+1 year', $dateActuelle) ); // Année suivante
$prevAnnee = date('Y', strtotime('-1 year', $dateActuelle) ); // Année précédente
$nextMois = date('m', strtotime('+1 month', $dateActuelle) ); // Mois suivant
$prevMois = date('m', strtotime('-1 month', $dateActuelle) ); // Mois précédent

// Affichage
$numJourSemaine = 1;
$jour = 1;
$base_jours = $calendar_txt[$language_selection]['jours'];
$base_mois = $calendar_txt[$language_selection]['mois'];
$base_voc = $calendar_txt[$language_selection]['voc'];

// Génération du tableau
echo '<table class="calendar" cellpadding="3" cellspacing="0">
<tr class="head"><td colspan="1" class="navigation">
<a href="?annee='.$prevAnnee.'&mois='.$moisActuel.'" title="'.$base_voc[0].'"><<</a><br /> 
<a href="?annee='.$anneeActuelle.'&mois='.$prevMois.'" title="'.$base_voc[1].'"><</a></td>
<td colspan="5" class="caption">'.$nomMoisActuel.'&nbsp;'.$anneeActuelle.'</td>
<td colspan="1" class="navigation">
<a href="?annee='.$nextAnnee.'&mois='.$moisActuel.'" title="'.$base_voc[3].'">>></a><br />
<a href="?annee='.$anneeActuelle.'&mois='.$nextMois.'" title="'.$base_voc[2].'">></a>

</td></tr>
<tr class="days_list"><td title="'.$base_jours[0].'">'.$base_jours[0][0].'</td><td title="'.$base_jours[1].'">'.$base_jours[1][0].'</td><td title="'.$base_jours[2].'">'.$base_jours[2][0].'</td><td title="'.$base_jours[3].'">'.$base_jours[3][0].'</td><td title="'.$base_jours[4].'">'.$base_jours[4][0].'</td><td title="'.$base_jours[5].'">'.$base_jours[5][0].'</td><td title="'.$base_jours[6].'">'.$base_jours[6][0].'</td></tr><tr class="days">';

// Affichage des jours
while( $jour <= $nbJoursMois ){
    // Date du jour traité
    $dateTraitee = sprintf("%d-%d-%d", $anneeActuelle, $moisActuel, $jour);
    $numJourSemaineDateTraitee = (int)date("N", strtotime($dateTraitee) );
    // Afficher le jour à son emplacement par rapport au jour de la semaine
    if( $numJourSemaineDateTraitee == $numJourSemaine ){
        // Couleur de fond du jour actuel
        if( $jour == $jourActuel && $moisActuel == date('m') ){
			$couleurFond = ' background-color:yellow; font-weight:bold;';
		} else {
			$couleurFond = '';
		}
		
		if( $language_selection == 'french' ){
			$complete_date = $base_jours[$numJourSemaineDateTraitee-1].' '.$jour.' '.$base_mois[$moisActuel].' '.$anneeActuelle;
		} elseif( $language_selection == 'english' ){
			$complete_date = $base_jours[$numJourSemaineDateTraitee-1].', '.$base_mois[$moisActuel].' '.$jour.date('S', $jour).' '.$anneeActuelle;
		} else {
			$complete_date = $base_jours[$numJourSemaineDateTraitee-1].' '.$jour.' '.$base_mois[$moisActuel].' '.$anneeActuelle;
		}
	
        // Afficher le jour à son empalcement
        echo '<td style="'.$couleurFond.'" onclick="alert(\''.$complete_date.'\')" title="'.$complete_date.'">'.$jour.'</td>'; 

        $jour++; // Passer au jour suivant du mois
    } else {
		echo '<td>&nbsp;</td>'; // Emplacement vide
	}
    // Passer au jour suivant de la semaine
    $numJourSemaine++;
	
    if ( $numJourSemaine > 7 ) { // Au-delà de Dimanche 
        echo '</tr><tr class="days">';
        $numJourSemaine = 1; // Retour au Lundi
    }
}

// Complession des dernières cellules 
$fin_tableau = 7-($numJourSemaine-1);
if($fin_tableau < 7) for($i=1;$i<=$fin_tableau;$i++) echo '<td>&nbsp;</td>';

echo '</tr></table>'; 
?>
</body>
</html>
:)
EDIT 2 : ne marche que sous PHP5 ;)

par stopher » 24 oct. 2008, 16:36

Tant que ça passe au w3c c'est bon non ? :)

par caroube » 24 oct. 2008, 16:22

@stopher et sadeq :
Décidément 3 solutions différentes et originales pour le même problème.
Vous me permettrez juste une remarque sur le code HTML généré par vos deux solutions : la dernière ligne de vos tableaux ne contient pas 7 tags TD.

par chrislabricole » 24 oct. 2008, 16:19

:shock:

Alors là bravo les gars ! =D> =D>

En effet c'est BEAUCOUP plus simple... Fallait y penser !
Mais bon, après faut écrire le code :P

Merci à vous !
Je vais mettre ce code à ma sauce :D
Alors là je mets le [Résolu] ^^

par stopher » 24 oct. 2008, 15:27

@sadeq merci ... :)

Bon aller , histoire de compléter pour avoir un code sans "Notice" , on a tous oublié de définir notre time Zone
(si Version de PHP >= 5.1.0)

il faut ajouter en début de code la ligne suivante pour notre cas :
date_default_timezone_set('Europe/Paris');
Sauf si vous l'avez déjà défini dans votre php.ini

http://fr3.php.net/manual/fr/datetime.c ... e.timezone

Et là , plus de notices ...

Voilà c'était juste histoire de compléter :D

par sadeq » 24 oct. 2008, 15:10

=D> Bravo messieurs caroube et stopher pour ces solutions dont j'ai bien aimé le principe simpliste.

Voici une autre solution inspirée des votre, mais qui se différencie par le fait qu'à l'affichage du jour, on trouve son emplacement par rapport au jour de la semaine par la fonction date("N") :
<?php
//base des dates en français
$getNomMoisFr = array('', 'Janvier', 'F&eacute;vrier', 'Mars', 'Avril', 'Mai', 'Juin'
, 'Juillet', 'Ao&ucirc;t', 'Septembre', 'Octobre', 'Novembre', 'D&eacute;cembre');

//récupére la date par GET ou date courante
$jourActuel		= (int)($_GET["jour"]?$_GET["jour"]:date("d"));
$moisActuel		= (int)($_GET["mois"]?$_GET["mois"]:date("m"));
$anneeActuelle	= (int)($_GET["annee"]?$_GET["annee"]:date("Y"));
//
$nomMoisActuel	= $getNomMoisFr[$moisActuel];
$dateActuelle	= strtotime(sprintf("%s-%s-%s", $anneeActuelle, $moisActuel, $jourActuel));
//
//récupére le nombre de jours dans le mois
$nbJoursMois	= date("t", $dateActuelle);
//menu de navigation annee/mois
$nextAnnee = date("Y", strtotime("+1 year", $dateActuelle));        //année suivante
$prevAnnee = date("Y", strtotime("-1 year", $dateActuelle));        //année précédente
$nextMois = date("m", strtotime("+1 month", $dateActuelle));        //mois suivant
$prevMois = date("m", strtotime("-1 month", $dateActuelle));        //mois précédent

//affichage
$numJourSemaine	= 1;
$jour 			= 1;
//
echo "<table>
<tr><th colspan='7'>
<a href='?annee=$prevAnnee&mois=$moisActuel&jour=$jourActuel'><<</a> &nbsp; 
<a href='?annee=$anneeActuelle&mois=$prevMois&jour=$jourActuel'><</a> &nbsp;
<a href='?annee=$anneeActuelle&mois=$nextMois&jour=$jourActuel'>></a> &nbsp; 
<a href='?annee=$nextAnnee&mois=$moisActuel&jour=$jourActuel'>>></a> &nbsp;
</th></tr>
<tr><th colspan='7'>$nomMoisActuel $anneeActuelle</th></tr>
<tr><th>Lu</th><th>Ma</th><th>Me</th><th>Je</th><th>Ve</th><th>Sa</th><th>Di</th></tr><tr>";
//affichage des jours
while($jour <= $nbJoursMois) {
	//date du jour traité
	$dateTraitée 				= sprintf("%d-%d-%d", $anneeActuelle, $moisActuel, $jour);
	$numJourSemaineDateTraitée 	= (int)date("N", strtotime($dateTraitée));
	//afficher le jour à son emplacement par rapport au jour de la semaine
	if ($numJourSemaineDateTraitée == $numJourSemaine){
		//couleur de fond pour sélectionner le jour actuel
		if ($jour == $jourActuel) $couleurFond = "yellow"; else $couleurFond="";
		//ajouter une sélection d'une jour sur clic de l'utilisateur
		$eventSelection = " style='cursor:pointer' onClick = \"alert('$dateTraitée')\" ";
		//Afficher le jour à son empalcement
		echo "<td bgcolor='$couleurFond' $eventSelection >$jour</td>"; 
		$jour ++; //passer au jour suivant du mois
	}
	else echo "<td>&nbsp;</td>"; //emplacement vide
    //passer au jour suivant de la semaine
	$numJourSemaine ++;
    if ($numJourSemaine > 7) { //Audela de Dimance 
    	echo "</tr><tr>";
		$numJourSemaine = 1; //retour au Lundi
	}
}
//
echo "</tr></table>"; 
?>
Edit: J'ai rajouté quelques truc pour la finition.

par caroube » 24 oct. 2008, 12:11

@stopher : tu ne viendrais pas du monde C, toi ? :lol:

par stopher » 24 oct. 2008, 11:54

Une alternative alors .. car moi j'aime les modulos :D et je trouve ça plus simple ..
Maintenant les goûts et les couleurs
//récupére le mois courant
(int)$jour	=	1;
(int)$Mnow	=	date("m");
(int)$Ynow	=	date("Y");

//cree le timestamp du 01/moiscourant/anneecourante
$TtimeStamps	=	mktime(1,1,1,$Mnow,1,$Ynow);

//recupere le nombre de jours dans le mois
$NbDayInMonth	=	date("t",$TtimeStamps);

//le 01/moiscourant/anneecourante est un quel jour ?
//1 => Lun 7=>Dim 
$JStart	=	date("N",$TtimeStamps);

(int)$emplacement	=	1;
//affichage
echo "<table><tr><td>Lu</td><td>Ma</td><td>Me</td><td>Je</td><td>Ve</td><td>Sa</td><td>Di</td></tr><tr>";

		for( ;$jour <= $NbDayInMonth;$emplacement++ )
		{
				if( $JStart-1 > 0 )
				{
					echo '<td>*</td>';
					$JStart--;
					continue 1;
				}
				//affichage du jour 
				echo '<td>'.$jour.'</td>';
				
				$jour++;
				//test si l'on doir changer de ligne
				if( $emplacement%7	==	0 )
				{
					echo '</tr><tr>';
				}
		}
	echo '
	</tr>
</table>
';
Ce qui donne :

Image

par caroube » 24 oct. 2008, 10:47

Le truc, c'est qu'il ne suffit pas de diviser le nombre de jours dans le mois par 7 et d'arrondir le résultat au supérieur...
Je crois que le premier réflexe que l'on a quand on s'attaque à ces problèmes de calendrier, c'est de vouloir entrer dans des calculs avec des arrondis, des divisions, des modulos, des mktime avec le nombre de secondes par jour, ... et que cela devient rapidement très complexe et incompréhensible.

Or, on est dans un cas ici où le dénombrement des possibilités est faible et peut-être traité à la main : 4 longueurs de mois x 7 jours de démarrage = 28 cas possibles pour le nombre de lignes qui peuvent être regroupés dans ce tableau fait en quelques minutes.

Code : Tout sélectionner

Dernier jour et nombre de lignes en fonction du jour de début et du nombre de mois Lu Ma Me Je Ve Sa Di 28 Di(4) Lu(5) Ma(5) Me(5) Je(5) Ve(5) Sa(5) 29 Lu(5) Ma(5) Me(5) Je(5) Ve(5) Sa(5) Di(5) 30 Ma(5) Me(5) Je(5) Ve(5) Sa(5) Di(5) Lu(6) 31 Me(5) Je(5) Ve(5) Sa(5) Di(5) Lu(6) Ma(6)
A partir de là, c'est relativement simple de voir qu'il y a 4 cas "exceptionnels" : 1 à 4 lignes et 3 à 6 lignes. C'est vrai que c'est intellectuellement moins satisfaisant qu'une solution purement mathématique, mais on s'en sort avec un simple switch.
<?php
//Lecture du datetime passé en paramètre ; si vide prendre date courante
$dt = $_GET["dt"]; //Calcul du mois format US + année
if ($dt) {
	$month = date ("F Y", $dt);
} else {
	$month = date ("F Y");
}
$firstdt = strtotime("1 ".$month);
$firstcol = dateEur($firstdt);	//Premier jour du mois 0 Lu, 1 Ma, ...
$days = date("t", $firstdt);		//Nombre de jours du mois
$nextdt = strtotime("+1 month", $firstdt);		//dt du mois suivant
$prevdt = strtotime("-1 month", $firstdt);		//dt du mois précédent


//Calcul du nombre de lignes du calendrier : 5 lignes la plupart du temps
$lines = 5;
switch ($days) {
	case 28: if ($firstcol == 0) {$lines = 4;} break;	//4 lignes si début = Lu
	case 30: if ($firstcol == 6) {$lines = 6;} break;	//6 lignes si début = Di
	case 31: if ($firstcol >= 5) {$lines = 6;} break;	//6 lignes si début = Sa ou Di
}

//Affichage
echo "<table border='1'>\n";
//Ligne de navigation
echo "<tr>";
echo "<td><a href='?dt=$prevdt'><</td>";
echo "<td colspan='5' align='center'>$month</td>";
echo "<td><a href='?dt=$nextdt'>></td>";
echo "</tr>\n";
echo "<tr><td>Lu</td><td>Ma</td><td>Me</td><td>Je</td><td>Ve</td><td>Sa</td><td>Di</td></tr>\n";
$day = 1;
for ($i=0; $i<$lines; $i++) {
	echo "<tr>\n";
	for ($j=0; $j<7; $j++) {
		echo "<td>";
		switch ($i) {
			case 0:		//Première ligne incomplète : remplir à partir du "firstcol"
				if ($j<$firstcol) {echo "&nbsp;";} else {echo $day; $day++;}
			break;
			default:	//Lignes suivantes : remplir jusqu'au dernier jour du mois
				if ($day <= $days) {echo $day; $day++;} else {echo "&nbsp;";}
			break;
		}
		echo "</td>";
	}
	echo "</tr>\n";
}
echo "</table>\n";


//Fonction qui renvoie 0 pour Lu, 1 pour Ma, ...
function dateEur($dt) {
	$d = date('w', $dt);
	if ($d == 0) {return 6;} else {return $d - 1;}
}

?>

par chrislabricole » 23 oct. 2008, 21:01

Oula :?
Le code de la Class est très difficile je trouve ! :shock:
Je pensais pas que le code d'un simple calendrier pouvait être autant difficile !

Je vais étudier comment ça marche exactement ;)

Merci jojolapine et Cobaye qui à dû s'arracher les cheveux :P
Merci quand même à toi stopher pour ton aide :)

par stopher » 23 oct. 2008, 20:27

Avec une date , au format timestamp , tu peux connaître le nombre de jour dans le moi .. c'est déjà une chose .

Tu peux connaitre aussi Jour de la semaine au format numérique par exemple ...
ce qui permet déjà de positionner ton jour sur une colonne.

Imaginons que tu prennes comme référence le premier du moi car il y a toujours un premier du moi ..
tu sais dans quelle colonne le placer imaginons un mercredi ton "tableau commence donc comme ça"
l m m j v s d
* * 1 2 3 4 5

Dans une semaine , il y a aussi toujours 7 jours ... donc , à la construction de ton tableau , toutes les 7 valeurs tu ajoutes une ligne (les * comptent pour une valeur ) ... regardes du coté des modulos pratique dans ces cas là ..

Ainsi de suite jusqu'à la fin du moi :-)

Et voilà sur le principe .. maintenant , il y a certainement , d'autres façons de procéder mais celle ci doit fonctionner sans probléme ..

par jojolapine » 23 oct. 2008, 20:22

Hello!
Si tu veux t'inspirer, ou pas te casser la tête à tout refaire: http://www.phpfrance.com/forums/voir_sujet-22523.php
très bonne source ;)

par chrislabricole » 23 oct. 2008, 20:10

Ouais ouais, elle retourne le nombre de jours dans le mois, mais comme je disais dans mon précédent message, il ne suffit pas de diviser ce nombre par 7 et de l'arrondir au supérieur que ça nous donne le nombre de ligne... regarde le mois de Mars et de Juin tu comprendra ;)

Tu vois, c'est ce genre de choses que ne vois pas comment faire3
Bon ok, ci dessous le code actuel, pas fonctionnel bien sûr :P
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Document sans titre</title>
</head>

<body>

<?php
// french ; english
$language_selection = 'french';

### French
$calendar_txt['french']['mois'] = array('', 'Janvier', 'F&eacute;vrier', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Ao&ucirc;t', 'Septembre', 'Octobre', 'Novembre', 'D&eacute;cembre');
$calendar_txt['french']['jours'] = array('Lundi', 'Mardi', 'Mercredi','Jeudi', 'Vendredi', 'Samedi',	'Dimanche');
### English
$calendar_txt['english']['mois'] = array('', 'January', 'February', 'March',	'April', 'May', 'June', 'July', 'August', 'September', 'October','November', 'December');
$calendar_txt['english']['jours'] = array('Monday', 'Tuesday', 'Wednesday','Thursday', 'Friday', 'Saturday','Sunday');


$annee = '2008';
$mois = '10';

$texte_mois = $calendar_txt[$language_selection]['mois'][date('n')];

// hour minute second month  day  year
$premier_jour_du_mois = date("w", mktime(0, 0, 0, $mois, 01, $annee));
$nb_jours_restants = 7-$premier_jour_du_mois;

$nb_semaines_ds_mois = ceil(date("t", mktime( 0, 0, 0, $mois, 1, $annee))/7);

?>

<table width="200" border="1">
	<tr>
		<td colspan="7"><?php echo $texte_mois.' '.$annee; ?></td>
	</tr>
    
	<tr>
		<td>L</td>
		<td>M</td>
		<td>M</td>
		<td>J</td>
		<td>V</td>
		<td>S</td>
		<td>D</td>
	</tr>
    
    <?php
	for( $i = 0; $i <= $premier_jour_du_mois-2; $i++){
		// "-" voulant dire "rien"
		echo '<td>-</td>';
	}
	for( $i = 0; $i <= $nb_jours_restants; $i++){
		// "J" en attendant... pour dire qu'il y aura quelque chose...
		// Si déjà on arrive à mettre en place les emplacements des jours...
		echo '<td>J</td>';
	}
	?>
    
</table>
</body>
</html>
Pour ce mois-ci, la première ligne fonctionne, mais si je change de mois dans la variable $mois... :roll:
Déjà quand il y aura plus de problème avec ça... on pourra chercher à comprendre comment récupérer le nombre de lignes qu'il faut ;)

Merci de votre aide !

par stopher » 23 oct. 2008, 19:43

une piste , regardes ce que te retourne cette commande ...
date("t",time());
:D

par chrislabricole » 23 oct. 2008, 19:38

c'est un bon exercice pour maîtriser les dates ...
Oui, c'est justement une des raisons pourquoi je me lance dans ça :mrgreen:

Je connais déjà la fonction strtotime(), mais je ne vois pas en quoi elle est vraiment utile dans mon cas :?
le truc, c'est qu'il ne suffit pas de diviser le nombre de jours dans le mois par 7 et d'arrondir le résultat au supérieur... fais le test, tu verras...
C'est pas si simple que ça :P