Comparer deux dates en JavaScript paraît simple jusqu’au moment où l’heure, le fuseau horaire ou un format de chaîne un peu trop libre viennent fausser le résultat. Derrière compare date js, il y a presque toujours la même vraie question : veut-on comparer un instant précis, un jour civil ou un intervalle de temps ? Je vais aller droit au but avec les méthodes fiables, les pièges que je vois le plus souvent et les bons choix selon le contexte.
L’essentiel à retenir pour comparer des dates sans mauvaise surprise
- Pour comparer deux instants précis, comparez leurs timestamps avec
getTime()ou une coercition numérique. -
===ne dit pas si deux dates représentent le même moment, il teste surtout l’identité de l’objet. - Si vous ne voulez comparer que le jour, ignorez l’heure et comparez année, mois et jour.
- Les dates ISO au format
YYYY-MM-DDsont pratiques, mais seulement si vous maîtrisez strictement leur sens. - Le fuseau horaire peut changer le résultat visible, surtout autour de minuit et des changements d’heure.
- En 2026,
Temporalest prometteur, mais sa disponibilité navigateur reste limitée selon les environnements.
Comparer deux objets Date sans se tromper
En JavaScript, un objet Date représente un instant mesuré en millisecondes depuis l’époque Unix. C’est pour cela que la comparaison chronologique fonctionne bien avec les opérateurs relationnels <, >, <= et >= : le moteur convertit les deux dates en valeur numérique avant de comparer. Pour une égalité stricte entre deux instants, je préfère toutefois comparer les timestamps avec getTime(), parce que c’est plus lisible dans une équipe.
| Méthode | Ce que cela compare | Usage utile | Limite principale |
|---|---|---|---|
date1 < date2 |
L’ordre de deux instants | Trier, filtrer, vérifier une échéance | Ne dit rien sur le même jour civil |
date1.getTime() === date2.getTime() |
Le même instant exact | Vérifier une égalité réelle | Retourne NaN pour une date invalide |
Number(date1) === Number(date2) |
Le même timestamp | Alternative concise à getTime()
|
Moins explicite à la lecture |
date1 === date2 |
La même instance d’objet | Cas très rare | Ne compare pas la valeur de la date |
const date1 = new Date('2026-06-17T08:00:00+02:00');
const date2 = new Date('2026-06-17T06:00:00Z');
console.log(date1 > date2); // false
console.log(date1.getTime() === date2.getTime()); // true
console.log(Number(date1) === Number(date2)); // true
Le point que je vérifie toujours en premier, c’est la validité de la donnée. Une date invalide ne se comporte pas comme une date normale, et la comparaison peut devenir trompeuse si vous ne testez pas le résultat avant. Le réflexe simple est donc Number.isNaN(date.getTime()). Une fois ce socle posé, la vraie question devient différente : compare-t-on un moment ou un jour ?
Comparer seulement le jour, le mois et l’année
Dans beaucoup d’applications web, on ne veut pas comparer deux instants précis mais deux dates civiles. C’est typiquement le cas d’un calendrier, d’une réservation, d’une échéance ou d’un formulaire qui stocke une journée sans heure. Dans ce cas, ajouter artificiellement une heure à la valeur finit souvent par créer des bugs inutiles ; je préfère comparer directement les composantes de date.
function sameLocalDay(a, b) {
return a.getFullYear() === b.getFullYear()
&& a.getMonth() === b.getMonth()
&& a.getDate() === b.getDate();
}
function sameUtcDay(a, b) {
return a.getUTCFullYear() === b.getUTCFullYear()
&& a.getUTCMonth() === b.getUTCMonth()
&& a.getUTCDate() === b.getUTCDate();
}
Le choix entre local et UTC dépend du besoin métier. Si l’utilisateur pense en heure locale, par exemple pour un agenda en France, comparez en local. Si votre backend normalise tout en UTC et que la logique attend un référentiel unique, comparez en UTC. Cette distinction paraît mineure, mais elle change le résultat dès qu’on approche de minuit.
- Comparer en local convient aux interfaces centrées sur l’utilisateur.
- Comparer en UTC convient aux logs, aux API et aux événements horodatés.
-
Comparer une chaîne ISO peut suffire si vous manipulez uniquement du
YYYY-MM-DDstrict.
Je vois souvent une erreur récurrente : transformer une date sans heure en Date complet puis la comparer comme si elle représentait toujours la même journée partout. En réalité, une date civile n’est pas un instant. Dès qu’on mélange les deux notions, la suite du raisonnement devient fragile, ce qui nous amène directement au sujet des fuseaux horaires.
Gérer les fuseaux horaires et les chaînes de dates
Le vrai piège, ce n’est pas la comparaison elle-même, c’est la manière dont la donnée entre dans le système. Une chaîne ISO complète comme 2026-06-17T09:30:00+02:00 représente un instant clair, alors qu’une chaîne de type 2026-06-17 représente surtout une journée. Les deux ne racontent pas la même chose, même si elles se ressemblent visuellement.
| Format | Sens réel | Lecture la plus sûre | Risque |
|---|---|---|---|
2026-06-17 |
Date civile sans heure | Comparer comme une journée | Affichage décalé selon le fuseau |
2026-06-17T07:30:00Z |
Instant UTC précis | Comparer via timestamp | Peut sembler “changer de jour” en local |
2026-06-17T09:30:00+02:00 |
Instant avec offset explicite | Normaliser avant comparaison | Conversion locale parfois mal interprétée |
Je déconseille les formats ambigus comme 17/06/2026 ou 06/17/2026 quand ils passent par Date.parse() ou new Date(string). Le comportement dépend trop du contexte et du moteur, ce qui n’est pas acceptable dans une base de code sérieuse. Si l’objectif est de comparer une date sans heure, le mieux est souvent de conserver cette valeur comme date civile pure, ou de la normaliser dès l’entrée avec une règle unique.
Autre détail qui compte : le changement d’heure. Un même fuseau ne garde pas toujours le même décalage par rapport à l’UTC, donc une comparaison à cheval sur un passage été/hiver peut produire des surprises si l’on reconstruit mal les objets. C’est précisément pour ce genre de cas que je regarde aussi les alternatives plus récentes du langage.
Quand Temporal ou date-fns devient plus pertinent
En 2026, Temporal est une option sérieuse pour tout ce qui concerne les dates sans ambiguïté, mais sa disponibilité navigateur reste limitée. Je le trouve particulièrement propre pour les dates civiles, parce qu’il sépare mieux les concepts : un jour, une heure, un fuseau, une durée. Pour comparer deux jours purs, Temporal.PlainDate.compare() est beaucoup plus explicite que de bricoler un Date avec minuit artificiel.
const a = Temporal.PlainDate.from('2026-06-17');
const b = Temporal.PlainDate.from('2026-06-18');
console.log(Temporal.PlainDate.compare(a, b)); // -1
Si votre environnement ne permet pas encore d’utiliser Temporal directement, une librairie comme date-fns peut rendre le code plus lisible. Sa fonction compareAsc renvoie -1, 0 ou 1, ce qui est très pratique pour trier ou décider d’un ordre chronologique. Je l’utilise volontiers quand le projet l’emploie déjà, mais je n’ajoute pas une dépendance entière juste pour une simple comparaison.
| Solution | Meilleur cas d’usage | Atout principal | Limite |
|---|---|---|---|
Date + getTime()
|
Comparer des instants précis | Native, rapide, universelle | Facile à mal employer pour une date civile |
Temporal.PlainDate |
Comparer des jours sans heure | Modèle plus juste | Support navigateur encore hétérogène |
date-fns |
Projet déjà outillé avec une librairie date | API claire et pratique | Ajout de dépendance |
Mon avis est simple : si vous comparez des instants, restez sur le natif ; si vous comparez des jours métiers, choisissez un modèle qui représente vraiment un jour et pas un pseudo-jour fabriqué au hasard. Une bonne API de date ne corrige pas un mauvais modèle de données, elle le révèle.
Le réflexe que j’applique avant de mettre la comparaison en production
Avant de livrer une comparaison de dates, je me pose toujours la même question : qu’est-ce qu’on compare exactement ? Si la réponse est “un moment”, je pars sur les timestamps. Si la réponse est “un jour”, je compare des dates civiles. Et si la source de données mélange déjà plusieurs formats, je normalise avant d’écrire la moindre condition.
- Comparer un instant précis avec
getTime()ou une valeur numérique. - Comparer un jour civil avec année, mois et jour, jamais avec l’heure par défaut.
- Conserver une date sans heure comme une date sans heure, pas comme un faux timestamp.
- Éviter les formats de chaîne ambigus dès l’entrée du système.
- Tester au moins un cas de minuit et un cas de changement d’heure.
Si je devais résumer la pratique en une phrase, je dirais ceci : la bonne comparaison ne dépend pas d’un opérateur magique, mais d’un modèle clair. Quand vous séparez proprement l’instant, la date civile et le fuseau horaire, la logique devient plus simple, les bugs diminuent, et votre code reste lisible même des mois plus tard.