Comparer des dates en PHP - Évitez les erreurs courantes

Alfred Jacques .

8 mai 2026

Avant : caractères illisibles dans un fichier HTML. Après : "Bonjour à tous !" dans un fichier PHP, converti en UTF-8. Comparez la date PHP.

Comparer deux dates en PHP paraît simple tant qu’on travaille avec des valeurs propres et un seul fuseau horaire. Dès qu’on mélange format français, heures, timestamps et saisie utilisateur, les erreurs deviennent discrètes mais coûteuses. Je vais montrer ici les méthodes fiables, les cas où strtotime() suffit encore, et la manière de gérer correctement les écarts, les fuseaux et les formats d’entrée.

L’essentiel pour comparer deux dates sans faux résultat

  • DateTimeImmutable est mon choix par défaut pour comparer des dates ou des instants.
  • Les opérateurs <, >, <= et >= sont les plus lisibles pour l’ordre chronologique.
  • diff() sert à mesurer un écart, pas à décider quelle date est la plus ancienne.
  • strtotime() reste utile pour des cas simples, mais il devient fragile dès que le format est ambigu.
  • Pour une date seule, il faut neutraliser l’heure et le fuseau horaire avant de comparer.

Choisir la bonne approche selon le type de comparaison

Avant d’écrire une ligne de code, je décide ce que je veux comparer exactement : deux instants précis, deux dates sans heure, ou un écart de durée. La bonne méthode change selon la réponse, et c’est là que beaucoup de bugs commencent.

Méthode Quand l’utiliser Forces Limites Mon usage
DateTimeImmutable + opérateurs Comparer l’ordre de deux dates ou heures Lisible, stable, robuste avec les fuseaux Demande une normalisation de l’entrée Par défaut dans les projets web
diff() Mesurer un écart en jours, mois, heures ou minutes Donne un intervalle détaillé Ne sert pas à classer deux dates entre elles Délais, SLA, échéances
strtotime() + timestamp Conversion rapide d’une chaîne connue Simple, rapide, pratique pour du legacy Parsing ambigu, dépend du fuseau par défaut Cas simples et contrôlés
createFromFormat() Entrée utilisateur avec format défini Contrôle strict du format Plus verbeux Formulaires, import de données, formats français

La documentation PHP recommande clairement DateTimeImmutable pour les calculs de date, et ce n’est pas un conseil cosmétique : c’est ce qui évite une partie des effets de bord dès que l’on manipule plusieurs objets. Une fois ce choix posé, je peux comparer les valeurs sans transformer le code en usine à timestamps.

Comparer deux dates avec DateTimeImmutable

Quand je travaille sur une application web moderne, je pars presque toujours de deux objets DateTimeImmutable. L’intérêt est simple : l’objet ne se modifie pas en place, donc le code reste plus prévisible, surtout dans des traitements en chaîne.

$deadline = new DateTimeImmutable('2026-06-15 18:00:00', new DateTimeZone('Europe/Paris'));
$now = new DateTimeImmutable('2026-06-09 09:00:00', new DateTimeZone('Europe/Paris'));

if ($now < $deadline) {
    echo 'Encore dans les temps';
} else {
    echo 'Échéance dépassée';
}

Comparer l’ordre chronologique

Les opérateurs <, >, <= et >= sont suffisants si votre objectif est de savoir quelle date arrive avant l’autre. Je les trouve plus lisibles qu’une cascade de conversions en timestamp, surtout dans un code métier où la logique doit rester immédiate.

Vérifier le même moment

Pour l’égalité, je me méfie de ===. Cet opérateur dit seulement si deux variables pointent vers le même objet, pas si elles représentent le même instant. Si je veux comparer la valeur temporelle, je passe par getTimestamp() pour une précision à la seconde, ou par format('U.u') si les microsecondes comptent réellement.

$sameSecond = $a->getTimestamp() === $b->getTimestamp();

Cette distinction paraît technique, mais elle évite des erreurs très bêtes dans les validations, les réservations ou les règles de publication. Quand je dois connaître non pas quel instant vient avant l’autre, mais de combien il s’en éloigne, je passe à diff().

Mesurer l’écart avec diff()

diff() ne répond pas à la question « laquelle est la plus grande ? », mais à la question « quelle est la distance entre les deux ? ». C’est idéal pour afficher un délai, calculer une ancienneté ou contrôler une fenêtre de validité.

$start = new DateTimeImmutable('2026-06-01 08:30:00', new DateTimeZone('Europe/Paris'));
$end   = new DateTimeImmutable('2026-06-10 11:15:00', new DateTimeZone('Europe/Paris'));

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

echo $interval->days; // 9
echo $interval->h;    // 2
echo $interval->i;    // 45

Le point utile ici, c’est que DateInterval décrit un écart, mais ne remplace pas un vrai test d’ordre. Si je veux savoir si l’intervalle est négatif, j’inspecte aussi $interval->invert plutôt que d’interpréter le résultat à l’aveugle.

Pour un calcul vraiment indépendant du fuseau, je convertis d’abord les deux objets vers UTC avant d’appeler diff(). La documentation PHP insiste sur ce point, et dans les systèmes distribués c’est une précaution que je considère comme non négociable. Une fois ce cadre posé, le vrai sujet devient la conversion des chaînes d’entrée, et c’est souvent là que les problèmes commencent.

Quand strtotime() suffit encore et quand je l’évite

strtotime() reste pratique quand la chaîne est simple, connue et contrôlée. En revanche, dès que le format est ambigu ou que l’entrée vient d’un formulaire utilisateur, je préfère une méthode plus stricte. La documentation PHP précise d’ailleurs que cette fonction parse une description textuelle et qu’elle travaille avec le fuseau horaire par défaut si rien n’est explicite.

$a = strtotime('2026-06-01');
$b = strtotime('2026-06-10');

if ($a < $b) {
    echo 'Ordre correct';
}

Ce code fonctionne, mais il ne me rassure que dans un contexte très fermé. Le problème apparaît vite avec des formats comme 01/02/2026, qui peuvent prêter à confusion selon la convention attendue, ou avec des chaînes incomplètes qui héritent de composants implicites.

Quand le format est connu, je préfère createFromFormat() parce qu’il me force à expliciter l’attendu. C’est plus verbeux, mais beaucoup plus sain pour un formulaire en français ou un import CSV où la structure des données doit rester sous contrôle.

$input = '09/06/2026 14:30';

$date = DateTimeImmutable::createFromFormat(
    'd/m/Y H:i',
    $input,
    new DateTimeZone('Europe/Paris')
);

$errors = DateTimeImmutable::getLastErrors();

if ($date === false || $errors['warning_count'] > 0 || $errors['error_count'] > 0) {
    throw new RuntimeException('Date invalide');
}

Je considère cette approche comme plus sérieuse parce qu’elle me donne un vrai contrat d’entrée. À partir de là, le point suivant n’est plus le parsing, mais la manière dont je traite le fuseau horaire et le fait de comparer une date seule ou un instant complet.

Gérer fuseaux horaires, heures et dates seules

Dans un projet web, je vois souvent deux besoins différents mélangés dans le même code : comparer une date de calendrier et comparer un moment précis. Ces deux logiques ne produisent pas les mêmes résultats, surtout dès qu’un horaire franchit minuit ou qu’un changement d’heure intervient.

Comparer une date sans tenir compte de l’heure

Si le métier ne s’intéresse qu’au jour, je normalise les deux objets sur une heure commune, souvent minuit, puis je compare une représentation stable. Une comparaison de type Y-m-d est alors plus claire qu’une comparaison brute des objets complets.

$tz = new DateTimeZone('Europe/Paris');

$day1 = (new DateTimeImmutable('2026-06-09 18:45:00', $tz))->setTime(0, 0, 0);
$day2 = (new DateTimeImmutable('2026-06-09 07:10:00', $tz))->setTime(0, 0, 0);

if ($day1->format('Y-m-d') === $day2->format('Y-m-d')) {
    echo 'Même jour';
}

Lire aussi : Gérer l'IP en PHP - Évitez les pièges, sécurisez vos apps

Comparer un instant absolu

Si je veux comparer l’instant réel, je fixe d’abord le fuseau horaire des deux valeurs, puis je les ramène dans une base commune, souvent UTC. C’est particulièrement important si l’application manipule des utilisateurs répartis sur plusieurs pays ou si les données viennent d’API différentes.

$paris = new DateTimeZone('Europe/Paris');
$utc = new DateTimeZone('UTC');

$a = (new DateTimeImmutable('2026-10-25 01:30:00', $paris))->setTimezone($utc);
$b = (new DateTimeImmutable('2026-10-25 02:30:00', $paris))->setTimezone($utc);

if ($a < $b) {
    echo 'A précède B';
}

Ce réglage paraît secondaire, mais c’est exactement le genre de détail qui crée des écarts de 1 heure, 24 heures ou plus lors d’un changement d’heure. Une fois ce cadre stabilisé, il reste à éliminer les erreurs de logique les plus courantes.

Les erreurs qui cassent une comparaison en silence

Les bugs de dates sont rarement spectaculaires. Ils ne font pas toujours planter l’application, mais ils faussent discrètement une validation, un tri ou une échéance. C’est pour cela que je les traite comme des erreurs de qualité, pas comme des détails.

Erreur fréquente Ce que cela provoque Correction utile
Comparer des chaînes brutes Ordre lexicographique au lieu d’un ordre chronologique Convertir en DateTimeImmutable ou en timestamps
Utiliser === pour tester une valeur temporelle On compare l’identité de l’objet, pas son contenu Comparer les timestamps ou les dates normalisées
Oublier le fuseau horaire Décalages invisibles entre serveur, utilisateur et API Définir explicitement un fuseau, souvent UTC
Passer du texte ambigu à strtotime() Interprétation inattendue ou normalisation silencieuse Privilégier createFromFormat() pour les entrées connues
Comparer des dates complètes alors que seul le jour compte Résultats faux à cause de l’heure cachée Neutraliser l’heure avant la comparaison

Quand je relis ce type de code, je cherche toujours la même chose : quel est le contrat réel de la donnée, et est-ce que le code le respecte ? Cette discipline vaut mieux qu’un correctif tardif, parce que les dates touchent souvent la facturation, les accès, les délais ou les publications.

La règle pratique que j’applique dans un projet web

Si je devais résumer ma méthode en une règle simple, ce serait celle-ci : je normalise d’abord la donnée, puis je compare ensuite. En pratique, cela veut dire que je pars de DateTimeImmutable pour la plupart des cas, de diff() pour mesurer un écart, et de createFromFormat() dès que l’entrée doit être validée strictement.

  • Pour un tri chronologique, j’utilise les opérateurs < et > sur des objets déjà construits.
  • Pour une durée affichable, je passe par diff() et j’extrais les unités utiles.
  • Pour un formulaire français, je pars d’un format explicite comme d/m/Y H:i.
  • Pour un système distribué, je fixe le fuseau dès l’entrée, souvent en UTC côté stockage.
  • Pour du code ancien, je garde strtotime() seulement si je contrôle très bien les chaînes d’entrée.

Cette approche me paraît la plus saine en 2026 parce qu’elle réduit les ambiguïtés sans alourdir inutilement le code. Si je ne dois retenir qu’une chose, c’est qu’une comparaison de dates fiable commence toujours avant l’opérateur lui-même, au moment où l’on choisit le bon type, le bon format et le bon fuseau.

Questions fréquentes

DateTimeImmutable est préférable car il crée de nouveaux objets à chaque modification, garantissant que l'objet original reste inchangé. Cela rend le code plus prévisible et réduit les effets de bord, surtout dans les traitements en chaîne.
strtotime() est utile pour des chaînes de date simples et contrôlées, comme des formats standard. Cependant, pour des entrées utilisateur ou des formats ambigus, il est recommandé d'utiliser createFromFormat() pour une meilleure robustesse et un contrôle strict du format.
Pour comparer seulement les jours, normalisez les deux objets DateTimeImmutable à une heure commune (souvent minuit) avec setTime(0, 0, 0). Ensuite, comparez les objets ou leur représentation formatée (ex: 'Y-m-d').
Les opérateurs (<, >, <=, >=) déterminent l'ordre chronologique des dates. diff() calcule l'écart entre deux dates, retournant un objet DateInterval. Il ne sert pas à classer, mais à mesurer une durée.
Ignorer les fuseaux horaires peut entraîner des décalages inattendus (1 heure, 24 heures) lors des changements d'heure ou avec des utilisateurs dans différentes régions. Convertir les dates en UTC avant la comparaison assure une base commune et fiable.

Évaluer l'article

Moyenne: 0.0 / 5 · 0 évaluations

Tags

compare date php comparer deux dates php datetimeimmutable comparer dates php sans heure php diff dates fuseaux horaires strtotime php comparaison dates erreurs comparaison dates php
Autor Alfred Jacques
Alfred Jacques
Je m'appelle Alfred Jacques et je suis passionné par les technologies, en particulier dans les domaines du web, de l'intelligence artificielle, des réseaux et de la sécurité. Fort de plusieurs années d'expérience en tant qu'analyste de l'industrie, j'ai eu l'opportunité d'explorer en profondeur les tendances et les innovations qui façonnent notre monde numérique. Mon expertise se concentre sur l'analyse des systèmes de sécurité, l'impact de l'IA sur les entreprises et l'évolution des infrastructures web. Je m'efforce de simplifier des données complexes pour les rendre accessibles à tous, tout en garantissant une analyse objective et rigoureuse. Mon engagement envers mes lecteurs est de fournir des informations précises, à jour et fiables, afin de les aider à naviguer dans cet écosystème technologique en constante évolution.

Commentaires (0)

Ajouter un commentaire