Développement d'applications Web avec LAMP

Document d'accompagnement pour le cours 420-KB9-LG

Dates et heures

Dernière mise à jour le 6 décembre 2022

La gestion des dates et des heures est une partie non négligeable de la plupart des applications Web.

Cette section a pour but de montrer comment obtenir, transformer et afficher les dates et les heures en PHP.

Mais avant de commencer, rappelons que l'heure n'est en fait qu'une composante de la date. Si on est capable de gérer les dates, on est aussi capable de gérer les heures, les minutes et les secondes.

Le timestamp UNIX

Pour bien appréhender la gestion des dates et des heures en PHP, il est nécessaire de comprendre ce qu’est un timestamp UNIX. D'autant plus que cette valeur est celle utilisée par la plupart des systèmes d'exploitation, langages de programmation, bases de données, etc.

Le mot timestamp se traduit en français par estampille temporelle. Mais étant donné que ce terme est rarement rencontré, nous utiliserons quand même le mot anglais.

Le timestamp UNIX représente le nombre de secondes écoulées depuis le 1er janvier 1970 à minuit UTC.

Mais à sert donc ce nombre? Eh bien c'est un moyen standard, partagé par tous les sytèmes informatiques, de représenter un moment dans le temps. Il assure l'interropérabilité entre les systèmes.

Obtenir le timestamp courant

Pour obtenir le timestamp actuel, il suffit d’utiliser la fonction time(). Cette fonction ne prend aucun argument et retourne la date courante en secondes depuis le 1er janvier 1970.

Dans l'exemple suivant, la fonction a été appelée le jeudi 15 septembre 2022 à 14:04:15 UTC :

echo time();

Sortie :

1663250655

Cela veut dire qu’il s’est écoulé 1663250655 secondes entre le 1er janvier 1970 à minuit UTC et le 15 septembre 2022 à à 14:04:15 UTC.

Obtenir le timestamp à partir d'une date

Intéressons nous maintenant à la fonction mktime(). Cette fonction très pratique retourne, pour une date donnée, le timestamp lui correspondant.

Sa syntaxe est la suivante :

mktime(int $heures, int $minutes, int $secondes, int $mois, int $jour, int $année) : int|false

Vérifions avec les données de l'exemple précédent :

//          14:04:15   septembre 15 2022

echo mktime(14, 4, 15, 9, 15, 2022);

Comme prévu nous obtenons :

1663250655

Obtenir la date

Lorsqu'il est question de date, on ne pense pas généralement à un "timestamp", mais plutôt à une chaîne de catactères significative pour les humains.

La fonction date() permet d'obtenir une telle chaîne.

En voici la syntaxe :

date(string $format [, int $timestamp]) : string

Le premier paramètre représente le format de la date. Le deuxième, optionnel, est un timestamp UNIX.

En l'absence du deuxième paramètre, c'est le timestamp courant qui est utilisé.

Formats de dates

Plusieurs caractères sont possibles pour spécifier le format. Le tableau suivant en regroupe quelques-uns :

Caractère Signification
D Jour de la semaine en trois lettres et en anglais ("Sun" à "Sat")
w Jour de la semaine sur un chiffre ("0" à "6")
d Jour du mois sur deux chiffres ("01" à "31")
j Jour du mois sans les zéros initiaux ("1" à "31")
F Mois en texte, version longue et en anglais ("January" à "December")
M Mois en trois lettres et en anglais ("Jan" à "Dec")
m Mois sur deux chiffres ("01" à "12")
n Mois sans le zéro initial ("1" à "12")
Y Année sur 4 chiffres (ex : "2022")
H Heure au format 24h sur deux chiffres ("00" à "23")
g Heure au format 12h sur un chiffre ("1" à "12")
i Minutes sur deux chiffres ("00" à "59")
s Secondes sur deux chiffres ("00" à "59")
A AM / PM (majuscules)
a am / pm (en minuscules)

Quelques exemples

echo date("Y-m-d H:i:s"); // temps courant

Sortie :

2022-09-15 14:34:08

Dans l'exemple suivant, le timestamp est 0. On devrait donc obtenir "1970-01-01 00:00:00".

echo date("Y-m-d H:i:s", 0);

Et pourtant :

1969-12-31 19:00:00

La date affichée a 5 heures de moins que le 1er janvier 1970 à minuit. Mais pourquoi donc?

Cette différence est simplement dûe à des fuseaux horaires différents. En effet, quand il est minuit dans le fuseau horaire Western European Time (référence du temps UTC), il est 19 heures la veille dans le fuseau horaire Eastern Standard Time (Heure normale de l'Est).

echo "Temps local : " .  date("Y-m-d H:i:s", 1663250655);

echo "<br>";

date_default_timezone_set("UTC");
echo "Temps universel : " . date("Y-m-d H:i:s", 1663250655);

Sortie :

Temps local : 2022-09-15 10:04:15
Temps universel : 2022-09-15 14:04:15

Remarque : selon le temps de l'année, la différence entre notre fuseau horaire et le fuseau horaire de référence peut varier à cause de l'heure d'été.

Un dernier exemple :

$timestamp_noel = mktime(0, 0, 0, 12, 25, 2022);
echo date("F d, g:i a", $timestamp_noel);

Sortie :

December 25, 12:00 am

Valider une date

Pour vérifier si une date est valide (par exemple, lors de la validation des données d'un formulaire), on peut utiliser la fonction checkdate().

Cette fonction vérifie si la date donnée est valide et retourne TRUE ou FALSE selon le cas.

Syntaxe :

int checkdate(int $mois, int $jour, int $annee) : bool

Pour être considérée comme valide, la date doit remplir les conditions suivantes :

Exemple :

$resultat = checkdate(2, 29, 2022); // 2022 n'est pas bissextile

if( $resultat == true ) {
    echo "La date est valide";
} else {
    echo "La date n'est pas valide";
}

Sortie :

La date n'est pas valide

Décortiquer une date

Parfois on souhaite avoir seulement une composante de la date. Par exemple, le mois ou le jour de la semaine.

La fonction getdate() retourne un tableau associatif contenant les informations de date et d'heure du timestamp passé en paramètre ou de la date/heure courante locale si aucun paramètre n'est fourni.

Le tableau suivant présente le nom des clés du tableau associatif retourné :

Clé Contenu
"seconde" Représentation numérique des secondes (0 à 59)
"minutes" Représentation numérique des minutes (0 à 59)
"hours" Représentation numérique des heures (0 à 23)
"mday" Représentation numérique du jour du mois courant (1 à 31)
"wday" Représentation numérique du jour de la semaine courante (de 0 pour dimanche à 6 pour samedi)
"mon" Représentation numérique du mois (1 à 12)
"year" Année sur 4 chiffres (ex : 2022)
"yday" Représentation numérique du jour de l'année (0 à 365)
"weekday" Version texte du jour de la semaine (Sunday à Saturday)
"month" Version texte du mois (January à December)

Exemple :

$timestamp = time(); // date et heure courantes
echo date("Y-m-d H:i:s", $timestamp);
echo "<br>";

$d = getdate($timestamp);
echo "Today is the " . $d['mday'] . "th day of " . $d['month'];

Sortie :

2022-09-15 15:41:38
Today is the 15th day of September

En français S.V.P.

Pour terminer, voyons comment afficher une date en français. D'abord avec date() et getdate(), puis avec strftime().

Avec date() et getdate()

L'approche requiert plusieurs lignes de code :

<?php

$semaine = array(" Dimanche ", " Lundi ",    " Mardi ",   " Mercredi ",
                 " Jeudi ",    " Vendredi ", " Samedi ");
    
$mois = array(1 => " janvier ",  2 => " février ",   3 => " mars ",
              4 => " avril ",    5 => " mai ",       6 => " juin ",
              7 => " juillet ",  8 => " août ",      9 => " septembre ",
             10 => " octobre ", 11 => " novembre ", 12 => " décembre ");
   
// avec getdate()

$jour = getdate();

echo $semaine[$jour['wday']] . $jour['mday'] . $mois[$jour['mon']] . $jour['year'];
//   $semaine[         4   ] .      15       . $mois[        9   ] .     2022
//           Jeudi           .      15             septembre       .     2022

echo "<br>";

// avec date()

echo $semaine[date('w')] . date('j') . $mois[date('n')] . date('Y');
//   $semaine[      4  ] .    15     . $mois[      9  ] .   2022
//           Jeudi       .    15     .     septembre    .   2022

Sortie :

Jeudi 15 septembre 2022
Jeudi 15 septembre 2022

Avec strftime()

AVERTISSEMENT

Cette fonction est OBSOLÈTE à partir de PHP 8.1.0. Il est fortement recommandé de l'éviter puisqu'elle ne pourrait ne plus être disponible dans les prochaines version de PHP. Vous êtes donc invités à passer à la section suivante.

La section sur strftim() n'est conservée ici que pour notre curiosité.

Heureusement il existe une approche plus compacte et plus facilement modifiable :

// définition des informations de localisation
setlocale(LC_TIME, "fr_CA.utf8");

// définition du fuseau horaire
date_default_timezone_set("America/Toronto");

// formater la date, tout en tenant compte de l'encodage
echo utf8_encode(strftime("%A %d %B %Y"));

Sortie :

jeudi 15 septembre 2022

Voici la liste (en anglais, désolé) de tous les codes de formatage :

%a - abbreviated weekday name
%A - full weekday name
%b - abbreviated month name
%B - full month name
%c - preferred date and time representation
%C - century number (the year divided by 100, range 00 to 99)
%d - day of the month (01 to 31)
%D - same as %m/%d/%y
%e - day of the month (1 to 31)
%g - like %G, but without the century
%G - 4-digit year corresponding to the ISO week number (see %V).
%h - same as %b
%H - hour, using a 24-hour clock (00 to 23)
%I - hour, using a 12-hour clock (01 to 12)
%j - day of the year (001 to 366)
%m - month (01 to 12)
%M - minute
%n - newline character
%p - either am or pm according to the given time value
%r - time in a.m. and p.m. notation
%R - time in 24 hour notation
%S - second
%t - tab character
%T - current time, equal to %H:%M:%S
%u - weekday as a number (1 to 7), Monday=1. Warning: In Sun Solaris Sunday=1
%U - week number of the current year, starting with the first Sunday as the
     first day of the first week
%V - The ISO 8601 week number of the current year (01 to 53), where week 1 is
     the first week that has at least 4 days in the current year, and with
     Monday as the first day of the week
%W - week number of the current year, starting with the first Monday as the
     first day of the first week
%w - day of the week as a decimal, Sunday=0
%x - preferred date representation without the time
%X - preferred time representation without the date
%y - year without a century (range 00 to 99)
%Y - year including the century
%Z or %z - time zone or name or abbreviation
%% - a literal % character

Avec la classe IntlDateFormatter

La classe IntlDateFormatter est une nouvelle classe PHP qui permet, entre autres choses, d'afficher des dates dans un format localisé.

Il s'agit de la meilleure façon d'afficher les dates et les heures, mais elle exige que l'extension Intl soit installée sur le serveur (note : c'est le cas pour notre serveur d'hébergement).

Syntaxe du constructeur :

IntlDateFormatter(locale, format_date, format_heure, ...);

Les trois premiers paramètres du constructeur sont obligatoires. Ce sont :

  1. la "locale" (chaîne de localisation);
  2. le format à utiliser pour la date;
  3. le format à utiliser pour l'heure.

La locale est un identificateur qui correspond une position géographique et qui permet d'adapter l'affichage de l'information aux règles en vigueur dans une région donnée du monde.

Le tableau suivant présente quelques-unes de ces chaînes de localisation :

CodeLangueRégion
fr_BEFrançaisBelgique
fr_CAFrançaisCanada
fr_CHFrançaisSuisse
fr_FRFrançaisFrance
en_AUAnglaisAustralie
en_CAAnglaisCanada
en_GBAnglaisGrande-Bretagne
en_USAnglaisÉtats-Unis

Les formats utilisée pour la date et l'heure sont représentés par des constantes dont les plus utilisées sont FULL, LONG, MEDIUM, SHORT et NONE (aucune).

Dans l'exemple suivant, on affiche la date dans le format complet (sans l'heure) pour le Canada français :

// création d'un timestamp pour le mercredi 28 septembre 2022 à 16:25:32
$timestanp = mktime(16, 25, 32, 9, 28, 2022);

// création d'un formateur de date
$formateur = new IntlDateFormatter('fr_CA', IntlDateFormatter::FULL, IntlDateFormatter::NONE);

// affichage du timestamp formaté
echo $formateur->format($timestanp);

Sortie :

mercredi 28 septembre 2022

Un exemple d'affichage minimaliste pour la même date :

$formateur = new IntlDateFormatter('fr_CA', IntlDateFormatter::NONE, IntlDateFormatter::NONE);
echo $formateur->format($timestanp);

Sortie :

20220928 04:25 p.m.

Le tableau suivant donne la chaîne qui sera générée en fonction de la constante utilisée pour la date :

Format de la date Format de l'heure Chaîne générée
IntlDateFormatter::FULL IntlDateFormatter::NONE mercredi 28 septembre 2022
IntlDateFormatter::LONG IntlDateFormatter::NONE 28 septembre 2022
IntlDateFormatter::MEDIUM IntlDateFormatter::NONE 28 sept. 2022
IntlDateFormatter::SHORT IntlDateFormatter::NONE 2022-09-28

Le tableau suivant donne la chaîne qui sera générée en fonction de la constante utilisée pour l'heure :

Format de la date Format de l'heure Chaîne générée
IntlDateFormatter::NONE IntlDateFormatter::FULL 16 h 25 min 32 s temps universel coordonné
IntlDateFormatter::NONE IntlDateFormatter::LONG 16 h 25 min 32 s UTC
IntlDateFormatter::NONE IntlDateFormatter::MEDIUM 16 h 25 min 32 s
IntlDateFormatter::NONE IntlDateFormatter::SHORT 16 h 25

Bien sûr, dans la majorité des cas nous utiliserons à la fois la date et l'heure, en choisissant avec soin la combinaison appropriée.

Exemple :

// la sélection du fuseau horaire peut être nécessaire si le fuseau horaire du serveur n'est pas bien réglé
date_default_timezone_set("America/Toronto");

$formateur = new IntlDateFormatter('fr_CA', IntlDateFormatter::LONG, IntlDateFormatter::MEDIUM);
echo "Prévisions mises à jour le " . $formateur->format(time());

Sortie :

Prévisions mises à jour le 29 septembre 2022 à 10 h 12 min 46 s

Questions et exercices de révision

AVERTISSEMENT

Nous ne fournirons pas les réponses à ces questions pour deux bonnes raisons. La première est que celles-ci se trouvent dans les notes de cours. La seconde est que, dans certains cas, ce serait presque donner la réponse à des questions d'examen. :

Question 1

La plupart des systèmes informatiques conservent les dates et les heures sous forme de "timestamp" UNIX. Que contient essentiellement un timestamp UNIX?

Question 2

Donnez le code PHP pour afficher la valeur du timestamp UNIX demain à la même heure, soit exactement dans 24 heures.

Question 3

Donnez le code pour afficher la valeur du timestamp UNIX le 1er janvier 2023 à minuit (00:00:00).

Question 4

Donnez le code pour afficher la date courante dans le format suivant (en supposant que nous sommes le 3 octobre à 21:30) : "10-03 21:30".

Question 5

La fonction date() a deux paramètres : le premier est le format et le second (facultatif) un timestamp. Qu'arrive-t-il si le second paramètre n'est pas fourni?

Question 6

Donnez la ligne de code pour sélectionner le fuseau horaire de la ville de Ste-Thérèse.

Question 7

D'après la fonction checkdate(), l'année 22222 est valide. Vrai ou faux?

Question 8

Quel nombre affichera le code suivant si nous sommes mercredi?

$d = getdate();
echo $d['wday'];

Question 9

Donnez la sortie du code suivant si nous sommes le lundi 3 octobre à 21:30:52 :

$f = new IntlDateFormatter('fr_CA', IntlDateFormatter::MEDIUM, IntlDateFormatter::LONG);
echo "Nous sommes le " . $f->format(time());