Lorsque j’arrivai dans la petite pièce, G. était un peu en retrait devant son ordinateur. Les sourcils froncés, il lisait. En me voyant, il me lança un « Vos projets avancent ? »
G. savait que depuis peu, je m’étais lancé dans la programmation. Mais je ne voulais pas le déranger dans sa lecture.
Je peux revenir plus tard si je vous dérange...
Il déposa son livre.
Bof ! je ne trouve pas ce que je veux dans ce bouquin.
Rassuré, je lui expliquai la raison de ma présence.
Oui, mes petits projets avancent. Mais j’aimerais pouvoir me programmer un calendrier et je ne sais pas trop comment m’y prendre...
Il m’interrompit par un large sourire. G. était toujours prêt à me dépanner.
« VOUS » voulez le programmer ?
G. était du genre plutôt sarcastique. Il savait très bien que j’avais de la difficulté avec plusieurs aspects du PHP et il aimait bien me piquer un peu...
Je sais que ça doit exister sur le Net, répliquais-je, mais si on passe son temps à copier des scripts, sans trop les comprendre, j’ai l’impression que je n’irai pas loin.
Et vous avez parfaitement raison ! Plusieurs pensent que ça ne vaut pas la peine de réinventer la roue, et je suis bien d’accord avec eux. Mais il faut bien s’exercer sur des petits projets si on veut éventuellement en développer de grands.
Il me fit une place à côté de l’ordinateur. Il lança Apache, et un traitement de texte. Dans ce dernier il écrivit :
<?
$date_depart = getdate();
?>
Il enregistra le tout sous le nom calendrier.php. Je comprenais que mon mini-cours venait de commencer...
Il est assez simple de construire un calendrier, me dit-il. Mais il faut connaître quelques fonctions importantes pour le faire de manière efficace. Ici, j’ai écrit un petit script PHP tout mignon. getdate() est une fonction intégrée dans PHP. Dans la variable $date_depart, on a en fait un tableau associatif relativement à la date du jour. Par exemple, dans $date_depart[mday], on aura le jour du mois.
G. ajouta une ligne au script qui se lisait maintenant ainsi :
<?
$date_depart = getdate();
print $date_depart[mday];
?>
G. exécuta ce fichier du navigateur et, affiché, on vit : 7.
Puisque nous sommes le 7 mai 2002, on voit 7, fit-il en pointant ce dernier.
Puis il ajouta quelques lignes :
<?
$date_depart = getdate();
print $date_depart[mday];
print "<br>";
print $date_depart[mon];
print "<br>";
print $date_depart[year];
?>
Tout en tapant, il m’expliqua qu’on pouvait imprimer l’heure, les minutes, etc.
Ici, on devrait voir le jour du mois, le mois et l’année...
Donc, avec cette fonction, je peux connaître un foule d’informations sur le « aujourd’hui », dis-je.
Exactement. De plus, $date_depart[wday] m’imprimera, en format numérique le jour de la semaine. Dimanche vaut 0, lundi 1, ... et samedi vaut 6.
C’est utile ???
Oui. Car cela permet de savoir par exemple à quel jour de la semaine tombe le premier jour du mois. Si, par exemple, ce premier du mois est un mercredi, cela veut dire que, dans notre éventuel calendrier, les cases dimanche, lundi et mardi de cette première semaine du mois devront être vides.
Je restais perplexe.
Mais la fonction getdate() ne donne que le jour ACTUEL. Je ne suis tout de même pas pour changer la date de mon système pour obtenir cette information...
Bien sûr que non... C’est pour cela qu’une autre fonction vient à notre rescousse.
Il ajouta encore quelques lignes à son fichier source :
<?
$date_depart = getdate();
print $date_depart[mday];
print "<br>";
print $date_depart[mon];
print "<br>";
print $date_depart[year];
print "<br>";
print mktime(0,0,0,1,1,2000);
?>
Puis il l’exécuta. Je vis alors un ligne supplémentaire qui contenait l’énorme nombre suivant : 946702800.
C’est quoi ce nombre ?
mktime() est une fonction qui calcule le nombre de secondes depuis le premier janvier 1970 jusqu’à la date passée en argument. Ici, vous comprendrez qu’il s’agit de 0h0min0sec du mois de janvier, premier jour, 2000. Autrement dit, il y a 946702800 secondes entre le premier janvier 1970 et le premier janvier 2000. Une remarque, le mois arrive AVANT le jour dans les arguments.
Plusieurs questions se bousculaient dans ma tête.
Pourquoi le premier janvier 1970 ? Et en quoi cela vient-il m’aider dans mon calendrier ???
Dans le jaron informatique, « epoch » est la date et l’heure correspondant à la valeur « 0 » du système d’horodatage d’un système d’exploitation. Sous Unix, cela correspond au 1er janvier 1970, sous VMS, au 17 novembre 1858, sous MacOS, au 1er janvier 1904.
Et sous Windows ? demandais-je avec un sourire intérieur.
Je l’ignore, répondit-il un peu sec.
G. n’aimait pas vraiment Windows et préférait la philosophie du logiciel « libre ».
PHP a donc retenu le « UNIX EPOCH », poursuivit-il. Par ailleurs, cela peut nous être très utile car la fonction getdate() prend en argument cette « marque » du temps. Autrement dit, si, dans mon source, je remplace la ligne getdate() par getdate(946702800), le sytème me renverra la premier janvier 2000.
Il modifia le code source :
<?
$date_depart = getdate(946702800);
print $date_depart[mday];
print "<br>";
print $date_depart[mon];
print "<br>";
print $date_depart[year];
print "<br>";
print mktime(0,0,0,1,1,2000);
?>Après exécution dans le navigateur, cela se vérifait.
Hum... mais ... comment faire pour...
G. me coupa.
Il est maintenant très simple de trouver de l’information sur le premier jour de tous les mois de l’année. Il suffit en effet de combiner les deux fonctions.
Il modifia encore une fois le code-source.
Supposons qu’on cherche le jour de la semaine sur lequel tombe le premier mai 2002. Il suffit de faire :
<?
$date_depart = getdate(mktime(0,0,0,5,1,2002));
print "Le premier jour est : $date_depart[wday]";
?>
Diable ! Cela veut donc dire que je n’ai qu’à mettre des variables en arguments pour obtenir des débuts de mois selon mes besoins.
Et pendant que j’énoncais ce principe, G. réécrivait le source.
Bien sûr. Et vous avez compris qu’on peut, à l’aide d’un formulaire, demander à l’internaute le mois de son choix. On va maintenant écrire un petit peu de HTML pour donner de la substance à tout ça. On va écrire les deux premières lignes du calendrier.
Et après une ou deux minutes, voici à quoi ressemblait le code source :
<?
$mois=5;
$date_depart = getdate(mktime(0,0,0,$mois,1,2002));
$premier_jour = $date_depart[wday];
print "Le premier jour est : $premier_jour";
?>
<table border="1" align=center>
<tr>
<td>Dimanche</td>
<td>Lundi</td>
<td>Mardi</td>
<td>Mercredi</td>
<td>Jeudi</td>
<td>Vendredi</td>
<td>Samedi</td>
</tr>
<tr>
<?
print str_repeat("<td> </td>",$premier_jour) ;
?>
<td>1</td>
</TR>
</table>
Avant de le lancer, G. mentionna :
Cela aura l’air un peu fou, mais ça pourra nous servir de base...
À l’écran, on voyait :

G. prit alors le temps de m’expliquer son source :
Dans la variable $premier_jour, nous avons le jour de la semaine correspondant au premier du mois. Dans notre cas, le premier mai 2002 est un mercredi. $premier_jour est donc égal à 3 (dim=0, lun=1,.., merc=3). Or si le calendrier doit commencer un mercredi, cela veut dire que les trois premières cases doivent être vides. Remarquez la logique : le système nous indique qu’il faut commencer un jour « 3 » et, oh ! coïncidence, on doit produire trois case vides. Si, par exemple, le premier jour avait été un vendredi (donc, jour=5 ) il aurait fallu créer 5 cases vides.... DONC la variable $premier_jour correspond AUSSI au nombre de cases vides que doit produire la rangée du calendrier représentant la première semaine du mois.
D’où la ligne print str_repeat("<td> </td>",$premier_jour) ;
Exactement ! str_repeat() est une fonction bien pratique au niveau des chaînes de caractères et vous aurez compris qu’ici elle est utilisée efficacement pour produire la bonne quantité de cellules ne contenant qu’un espace insécable.
Ouais... mais comment compléter le calendrier ?
Mais... en réfléchissant ! me lanca-t-il comme pour me provoquer.
Et, reculant sur sa chaise, il me signala que lorsqu’on se lance dans un projet, il est important de lire la documentation de toutes les fonctions susceptibles de venir en aide lors dudit projet.
Par exemple, lorsqu’on consulte la documentation sous l’item mktime(), il est dit qu’on peut trouver le nombre de jours d’un mois quelconque en mettant "0" comme argument du jour sur le mois suivant...
Pardon ????
Je ne comprenais rien à son charabia.
Calmement, il reprit :
Voici la fonction avec ses arguments :
et il écrivit :
mktime(heure,minute,seconde,lemois,lejour,lannee) ;
Il continua :
Par exemple, mktime(0,0,0,5,1,2002) nous donne le nombre de seconde depuis le 1 janvier 1970 jusqu’au premier mai 2002.
Or, si on fait : mktime(0,0,0,5,0,2002), nous aurons le nombre de seconde depuis le 1 janvier 1970 jusqu’au dernier jour d’avril 2000.
Remarquez bien : 5 pour le mois (donc MAI) et 0 pour le jour... Ce 0 signifie qu’on retourne 1 jour dans le passé par rapport au mois de mai. Nous sommes donc le dernier jour d’avril...
Je vois. Si par exemple ma variable $mois contient le mois alors : mktime(0,0,0,$mois+1,0,2002) contient le nombre de secondes depuis le 1 janvier 1970 jusqu’au dernier jour de ce mois !
C’est bien cela ! Vous voyez bien que c’était facile à comprendre.
Avec un exemple, c’est en effet assez simple, fis-je, ahuri.
Et G. se mit au clavier.
« Donnons-nous une variable pour le mois et une pour l’année. Pour pouvoir tester un peu, nous allons leur donner des valeurs précises. Par la suite, un formulaire pourra les modifier.
$mois=5;
$annee=2002;Par la suite, on va se donner des variables utiles :
$date_depart = getdate (mktime(0, 0, 0, $month, 1, $year));
$jour_depart = $dateinfo["wday"];Et maintenant, pour obtenir le nombre de jours dans le mois courant, on a la variable $date_du_dernier_jour.
$date_fin = getdate (mktime(0, 0, 0, $month+1, 0, $year));
$date_du_dernier_jour = $dateinfo["mday"];
$jour_final = $dateinfo["wday"];Et avec toutes ces données, il faut maintenant utiliser de l’ingéniosité pour programmer le tableau correspondant au calendrier de ce mois. »
Je vois pas trop comment faire.
D’abord, déterminons les difficultés. Vous en voyez ?
En fait, je ne voyais QUE des difficultés.
Hum... au samedi, il faut sauter de ligne... Il faut arrêter le tableau au dernier jour du mois... Il faut prévoir que si ce dernier jour ne se termine pas sur le samedi, alors il faut compléter les cellules par des espaces insécables...
En tout cas, vous avez bien cerné le problème. Clairement, on aura besoin d’un compteur qui commence au premier jour du mois et qui se termine au dernier. Quelque chose comme : for ($i=1;$i<=$date_fin,$i++) print "<td>$j</td>";
J’acquiescai.
Oui, mais comment lui dire de faire un <tr> ???
C’est en effet assez complexe. Mais en y réfléchissant un peu, on voit comment s’en sortir. Il suffit de calculer le "wday" du jour de la date de la case. Si ce "wday" est égal à 6, alors on saute de rangée...
Wash...
Mais c’est assez simple ! Voyez :
$jour_calendrier = mktime(0,0,0, $mois, $i, $annee);
$dateinfo = getdate($jour_calendrier);
print "<td>$i</td>";
if ($dateinfo["wday"] == 6)
{
print "</tr><tr>";
}
J’étais héberlué devant la simplicité du code.
Diable, vous êtes magicien ou quoi ?
Il souriait.
Vous savez, le grand plaisir de la programmation est dans la recherche de solution simple à des problèmes qui semblent complexes au premier abord. C’est surtout regarder la solution et se dire « que c’est beau, la pensée humaine ».
G. était philosophe sur les bords. Pour lui, il est clair qu’une grande joie dans la vie consistait à apprécier l’harmonie des solutions logiques. En le voyant ainsi, tel un enfant, ébloui par son propre code-source, j’étais moi-même heureux.
Et ici, vous voyez en effet une approche assez simple : on met la date dans une cellule. On verifie si cette date tombe sur un jour « 6 » (on se croirait à l’école secondaire) et si oui, on crée une rangée.
Et il continua sur sa lancée.
Bien. Il faut maintenant s’occuper des dernières cases vides du mois. Puisque la variable $jour_final correspond au dernier jour du mois, il suffit de compléter un nombre de cellules correspondant à « 6 moins ce nombre ». Ce qui peut se traduire par :
print str_repeat("<td> </td>",6-$jour-final);
print "</tr></table>";et le tour est joué...
Correctement réarrangé, voici ce que donne le code final :
<?
$mois=5;
$annee=2002;
$date_depart = getdate (mktime(0, 0, 0, $mois, 1, $annee));
$jour_depart = $date_depart[wday];
$date_fin = getdate (mktime(0, 0, 0, $mois+1, 0, $annee));
$date_du_dernier_jour = $date_fin[mday];
$jour_final = $date_fin[wday];
?>
<table border="1" align=center>
<tr>
<td>Dimanche</td>
<td>Lundi</td>
<td>Mardi</td>
<td>Mercredi</td>
<td>Jeudi</td>
<td>Vendredi</td>
<td>Samedi</td>
</tr>
<tr>
<?
print str_repeat("<td> </td>",$jour_depart) ;
for ($i=1;$i<=$date_du_dernier_jour;$i++)
{
$jour_calendrier = mktime(0,0,0, $mois, $i, $annee);
$date_tempo = getdate ($jour_calendrier);
print "<td>$i </td>";
if ($date_tempo[wday] == 6)
{
print "</tr><tr>";
}
}
print str_repeat('<td> </td>',6-$jour_final);
print "</tr></table>";
?>
En quittant, G. me laissa avec quelques défis intéressants :
1- Créer une page web qui affiche le calendrier selon les spécifications de l’internaute. (facile)
2- Donner un beau « look » au calendrier (facile)
3- Créer un calendrier qui permet d’afficher, aux bonnes dates, des événements provenant, par exemple, d’une base de données (intermédiaire).
4- Permettre aux internautes la création d’un agenda personnel (intermédiaire).


