Tutoriel
Partie 14 — Dates & heures : gérer le temps en PHP

Partie 14 — Dates & heures : gérer le temps en PHP

Apprends à gérer dates et heures en PHP : date(), strtotime(), DateTime/DateInterval, fuseaux horaires, formats, calculs, différences, “il y a X minutes”, exemples réels.

PHP 54 Mis à jour 11 hours ago
Conseil : lisez d’abord les sections clés, puis essayez un QCM lié à la même notion pour valider votre compréhension.

Partie 14 — Dates & heures : gérer le temps en PHP

Si tu développes un site ou une application, tu vas manipuler le temps partout : inscription, connexion, expiration de token, réservation, horaires, logs, factures, planning… et pourtant, la gestion des dates est l’un des sujets où même les devs expérimentés se font piéger.

Pourquoi ? Parce que le temps, ce n’est pas juste “un texte”. Il y a des formats, des fuseaux horaires, des heures d’été, des calculs (ajouter 1 mois n’est pas toujours “+30 jours”), des différences et des affichages qui doivent être compréhensibles pour l’utilisateur.

👉 Objectif de cette partie : te rendre autonome sur date(), strtotime(), et surtout DateTime / DateInterval, avec des exemples réels.


1) Comprendre l’essentiel : timestamp, format, timezone

1.1 Le timestamp (temps “machine”)

Un timestamp Unix est un nombre : le nombre de secondes écoulées depuis le 1er janvier 1970 (UTC). C’est la forme la plus pratique pour comparer et calculer.

<?php
echo time(); // ex: 1700000000
?>
  

Avantage : simple à comparer (>, <), simple à stocker en base. Inconvénient : pas lisible pour un humain (on doit le formater).

1.2 Le format (temps “humain”)

Pour afficher une date, on la met en forme. Exemple classique : 2026-02-10 20:15:00.

<?php
echo date("Y-m-d H:i:s"); // format courant
?>
  

Dans date(), chaque lettre représente une partie : Y année, m mois, d jour, H heure (24h), i minutes, s secondes.

1.3 Le fuseau horaire (timezone)

Le fuseau horaire, c’est la règle qui dit “quelle heure est-il ici ?”. Une même seconde (timestamp) peut s’afficher différemment selon le pays.

⚠️ Piège fréquent : si ton serveur est en UTC, mais que tes utilisateurs sont au Maroc, l’affichage peut être décalé si tu ne gères pas la timezone.

<?php
date_default_timezone_set("Africa/Casablanca");
echo date("Y-m-d H:i:s");
?>
  

Astuce pro : configure la timezone une seule fois (dans un fichier de config global), plutôt que de la répéter dans chaque page.


2) date() : afficher une date facilement

date() prend un format et un timestamp (optionnel). Si tu ne passes pas de timestamp, PHP utilise l’heure actuelle (time()).

2.1 Exemples de formats utiles

Format Résultat Utilisation
Y-m-d 2026-02-10 Stockage / API
d/m/Y 10/02/2026 Affichage simple
H:i 20:15 Heure
Y-m-d H:i:s 2026-02-10 20:15:00 Logs / back-office
l d F Y Tuesday 10 February 2026 Texte complet (anglais)

2.2 Afficher un timestamp précis

<?php
$ts = 1700000000;
echo date("Y-m-d H:i:s", $ts);
?>
  

Très utile quand tu récupères un timestamp depuis une base de données, un token, ou un log.


3) strtotime() : convertir une date “texte” en timestamp

strtotime() est pratique pour transformer un texte en timestamp : "2026-02-10 10:30" ou même "next monday". Mais attention : plus ton entrée est “floue”, plus tu prends un risque.

3.1 Conversions simples

<?php
$ts = strtotime("2026-02-10 10:30:00");
echo date("Y-m-d H:i:s", $ts);
?>
  

3.2 Expressions relatives (super pratique)

<?php
echo date("Y-m-d", strtotime("+7 days"));
echo "\n";
echo date("Y-m-d H:i", strtotime("tomorrow 08:00"));
?>
  

Ça sert pour : “rendez-vous demain à 8h”, “expiration dans 7 jours”, “relance dans 48h”.

⚠️ Piège : strtotime() dépend de la locale/timezone et n’est pas parfait pour toutes les chaînes. Pour un projet sérieux, préfère DateTime quand tu peux.


4) DateTime : l’approche “pro” (solide, lisible, maintenable)

DateTime est la classe recommandée : elle gère mieux les fuseaux horaires, les calculs, et rend le code plus clair. Si tu veux coder proprement, c’est là que tu dois investir.

4.1 Créer une date (maintenant)

<?php
date_default_timezone_set("Africa/Casablanca");

$now = new DateTime();
echo $now->format("Y-m-d H:i:s");
?>
  

4.2 Créer une date depuis une chaîne

<?php
$dt = new DateTime("2026-02-10 14:30:00");
echo $dt->format("d/m/Y à H:i");
?>
  

4.3 Créer une date avec timezone explicitement

<?php
$tzParis = new DateTimeZone("Europe/Paris");
$paris = new DateTime("now", $tzParis);

$tzCasa = new DateTimeZone("Africa/Casablanca");
$casa = new DateTime("now", $tzCasa);

echo "Paris: " . $paris->format("Y-m-d H:i:s") . "\n";
echo "Casa:  " . $casa->format("Y-m-d H:i:s") . "\n";
?>
  

Cas réel : ton back-office est en Europe, mais tes utilisateurs au Maroc. Tu affiches selon leur timezone, sans casser ton stockage.


5) Calculs de dates : ajouter / soustraire proprement

Les calculs “à la main” avec des secondes peuvent devenir dangereux (mois, DST, etc.). Avec DateInterval, c’est propre et clair.

5.1 Ajouter 7 jours, 2 heures, 1 mois

<?php
$dt = new DateTime("2026-02-10 10:00:00");

$dt->add(new DateInterval("P7D"));  // +7 jours
echo $dt->format("Y-m-d H:i:s") . "\n";

$dt->add(new DateInterval("PT2H")); // +2 heures
echo $dt->format("Y-m-d H:i:s") . "\n";

$dt->add(new DateInterval("P1M"));  // +1 mois
echo $dt->format("Y-m-d H:i:s") . "\n";
?>
  

Syntaxe ISO 8601 de DateInterval :

  • P = “période” (jours/mois/années) : P7D, P1M, P1Y
  • T = partie “temps” : PT15M (15 minutes), PT2H (2 heures)

5.2 Soustraire (expiration, délai, etc.)

<?php
$expiry = new DateTime();
$expiry->add(new DateInterval("PT30M")); // expire dans 30 minutes

$check = new DateTime();
$check->sub(new DateInterval("PT10M"));  // on recule de 10 minutes

echo "Expiry: " . $expiry->format("H:i:s") . "\n";
echo "Check:  " . $check->format("H:i:s") . "\n";
?>
  

Exemple réel : tu génères un code OTP (valide 10 minutes) ou un lien de reset (valide 30 minutes).


6) Différence entre deux dates : diff() et cas pratiques

Quand tu veux répondre à : “combien de jours restants ?”, “depuis combien de temps ?” ou “est-ce que c’est expiré ?”, tu as deux approches : comparaison ou différence.

6.1 Comparer deux dates (simple et efficace)

<?php
$now = new DateTime();
$deadline = new DateTime("2026-02-15 23:59:59");

if ($now > $deadline) {
    echo "Délai dépassé";
} else {
    echo "Encore valide";
}
?>
  

6.2 Calculer la différence (jours/heures/minutes)

<?php
$start = new DateTime("2026-02-10 10:00:00");
$end   = new DateTime("2026-02-12 14:30:00");

$interval = $start->diff($end);

// %a = total de jours, %h heures, %i minutes
echo $interval->format("%a jours, %h heures, %i minutes");
?>
  

Très utile pour un module de réservation, un plan d’étude, une gestion de projet, ou un “compte à rebours”.


7) “Il y a 5 minutes” : afficher du temps relatif (UX moderne)

Sur un site, afficher “2026-02-10 20:11:42” c’est parfois trop technique. Les apps modernes montrent souvent : “à l’instant”, “il y a 5 minutes”, “il y a 2 heures”, “hier”.

Voici une fonction simple (sans librairie) pour couvrir 90% des besoins.

<?php
function timeAgo(DateTime $date): string
{
    $now = new DateTime();
    $diff = $now->getTimestamp() - $date->getTimestamp();

    if ($diff < 10) return "à l’instant";
    if ($diff < 60) return "il y a " . $diff . " secondes";

    $minutes = intdiv($diff, 60);
    if ($minutes < 60) return "il y a " . $minutes . " minutes";

    $hours = intdiv($diff, 3600);
    if ($hours < 24) return "il y a " . $hours . " heures";

    $days = intdiv($diff, 86400);
    if ($days === 1) return "hier";
    if ($days < 30) return "il y a " . $days . " jours";

    // au-delà, on affiche une date lisible
    return $date->format("d/m/Y");
}

$postDate = new DateTime("-3 hours");
echo timeAgo($postDate);
?>
  

✅ Exemple réel : afficher le temps d’un commentaire, d’un post, d’un article, d’une notification.


8) Dates en base de données : bonnes pratiques (indispensable)

La meilleure stratégie pour éviter les bugs : stocke le temps dans un format stable, puis affiche selon l’utilisateur.

8.1 Format recommandé pour stocker

  • DATETIME en SQL avec format YYYY-MM-DD HH:MM:SS
  • ou un timestamp (INT)

Pour les API, le standard moderne est souvent ISO 8601 : 2026-02-10T20:15:00+01:00.

8.2 UTC ou timezone locale ?

Beaucoup de systèmes stockent en UTC (universal), puis convertissent à l’affichage. Avantage : uniforme, surtout si tu as des utilisateurs dans plusieurs pays.

⚠️ Cas où “UTC partout” est quasiment obligatoire : plateformes internationales, réservation multi-pays, événements en ligne, dashboards globaux, logs serveur.

8.3 Exemple : stocker et afficher proprement

<?php
// Stockage (ex: UTC)
$utc = new DateTime("now", new DateTimeZone("UTC"));
$toStore = $utc->format("Y-m-d H:i:s");

// Affichage pour utilisateur Casablanca
$userTz = new DateTimeZone("Africa/Casablanca");
$fromDb = new DateTime($toStore, new DateTimeZone("UTC"));
$fromDb->setTimezone($userTz);

echo "DB(UTC): " . $toStore . "\n";
echo "User:    " . $fromDb->format("d/m/Y H:i");
?>
  

9) Cas réels (très importants) : expiration, réservation, horaires

9.1 Expiration d’un token (reset password, OTP, etc.)

Supposons que tu génères un token valable 30 minutes. Tu l’enregistres en base avec une date d’expiration.

<?php
$expiresAt = new DateTime();
$expiresAt->add(new DateInterval("PT30M"));

echo "Expire à: " . $expiresAt->format("Y-m-d H:i:s");

// Vérification plus tard
$now = new DateTime();
if ($now > $expiresAt) {
    echo " - Token expiré";
} else {
    echo " - Token valide";
}
?>
  

Dans une vraie app, tu compareras maintenant avec expires_at venant de la base.

9.2 Réservation : vérifier si un créneau est dans le futur

Exemple : un utilisateur choisit “2026-02-12 09:00”. Tu dois empêcher les réservations dans le passé (et afficher un message clair).

<?php
$input = "2026-02-12 09:00:00";
$booking = new DateTime($input);
$now = new DateTime();

if ($booking <= $now) {
    echo "Choisis une date dans le futur.";
} else {
    echo "Réservation OK : " . $booking->format("d/m/Y à H:i");
}
?>
  

9.3 Horaires d’ouverture : “Est-ce ouvert maintenant ?”

Cas concret très demandé : un magasin ou un service a des horaires. On veut savoir si c’est ouvert à cet instant.

<?php
date_default_timezone_set("Africa/Casablanca");

$now = new DateTime();
$todayOpen  = new DateTime($now->format("Y-m-d") . " 09:00:00");
$todayClose = new DateTime($now->format("Y-m-d") . " 18:00:00");

if ($now >= $todayOpen && $now <= $todayClose) {
    echo "✅ Ouvert (jusqu’à " . $todayClose->format("H:i") . ")";
} else {
    echo "❌ Fermé";
}
?>
  

Tu peux ensuite ajouter des exceptions (week-end, jours fériés, pause déjeuner…).


10) Validation d’une date utilisateur : éviter les bugs et les “Invalid date”

Quand un utilisateur remplit un formulaire, il peut envoyer une date invalide : 32/13/2026, ou un format incorrect. Une bonne appli valide toujours.

10.1 parse strict avec createFromFormat()

Si ton formulaire envoie 10/02/2026 (format français), utilise :

<?php
$input = "10/02/2026";

$dt = DateTime::createFromFormat("d/m/Y", $input);
$errors = DateTime::getLastErrors();

if ($dt === false || $errors["warning_count"] > 0 || $errors["error_count"] > 0) {
    echo "Date invalide";
} else {
    echo "Date OK : " . $dt->format("Y-m-d");
}
?>
  

✅ C’est la méthode la plus propre quand tu maîtrises le format attendu. Idéal pour les formulaires.


11) Les pièges classiques (et comment les éviter)

  • Mélanger formats et stockage : stocke en format stable (Y-m-d H:i:s), affiche en format utilisateur (d/m/Y).
  • Oublier la timezone : si serveur UTC et utilisateur local, tu auras des décalages.
  • Ajouter “+30 jours” au lieu de “+1 mois” : un mois n’a pas toujours 30 jours. Utilise DateInterval("P1M").
  • Utiliser strtotime() sur du flou : mieux vaut createFromFormat pour les formulaires.
  • Comparer des strings : comparer “10/02/2026” et “09/02/2026” en texte peut échouer. Compare des objets DateTime ou des timestamps.

✅ Règle simple : en interne tu manipules des DateTime (ou des timestamps), et tu ne formates en texte qu’au moment d’afficher.


12) Mini-projet guidé : système de “deadline” pour un concours

Prenons un mini scénario très réaliste : tu as une page “Concours” (comme sur un site de QCM), et tu veux afficher :

  • la date limite (deadline)
  • un message “encore X jours”
  • et l’état “ouvert/fermé”
<?php
date_default_timezone_set("Africa/Casablanca");

// Exemple : deadline stockée en base
$deadlineStr = "2026-02-20 23:59:59";

$deadline = new DateTime($deadlineStr);
$now = new DateTime();

// Affichage date lisible
echo "Date limite : " . $deadline->format("d/m/Y à H:i") . "<br>";

if ($now > $deadline) {
    echo "❌ Statut : Fermé";
} else {
    $interval = $now->diff($deadline);
    echo "✅ Statut : Ouvert<br>";
    echo "⏳ Il reste : " . $interval->format("%a jours, %h heures");
}
?>
  

Voilà un exemple de “feature” simple mais très utile. Et surtout : c’est propre, lisible, et facile à étendre (ex : afficher un compte à rebours en JS côté front).


13) Exercices (pour pratiquer vraiment)

  1. Écris une fonction qui reçoit une date (format Y-m-d) et retourne si elle est dans le futur ou dans le passé.
  2. Crée un script qui affiche “il y a X minutes/heures/jours” pour une date donnée.
  3. À partir de “2026-02-10 10:00”, calcule la date/heure exacte après : 1 mois, puis après 45 minutes.
  4. Valide une date entrée au format d/m/Y et refuse les dates impossibles.

Conclusion

La gestion des dates en PHP devient simple quand tu appliques une méthode : timezone claire + DateTime + formatage à l’affichage. Les fonctions comme date() et strtotime() sont utiles, mais DateTime t’évitera la majorité des pièges sur un projet réel.

Dans la prochaine partie, on pourra enchaîner sur un thème très lié : fichiers (upload), logs, ou gestion d’événements — selon ton plan de cours.