ATTENTION À LA FUSEAU HORAIRE
L'utilisation immédiate de l'objet date pour représenter juste une date vous place dans un énorme problème de précision excessive. Vous devez gérer le temps et le fuseau horaire pour les garder à l'écart, et ils peuvent se faufiler à tout moment. La réponse acceptée à cette question tombe dans le piège.
Une date javascript n'a aucune notion de fuseau horaire . C'est un moment dans le temps (ticks depuis l'époque) avec des fonctions pratiques (statiques) pour traduire vers et depuis des chaînes, en utilisant par défaut le fuseau horaire "local" de l'appareil, ou, si spécifié, UTC ou un autre fuseau horaire. Pour représenter just-a-date ™ avec un objet date, vous voulez que vos dates représentent UTC minuit au début de la date en question. Il s'agit d'une convention courante et nécessaire qui vous permet de travailler avec des dates indépendamment de la saison ou du fuseau horaire de leur création. Vous devez donc être très vigilant pour gérer la notion de fuseau horaire, à la fois lorsque vous créez votre objet Date UTC à minuit et lorsque vous le sérialisez.
Beaucoup de gens sont confus par le comportement par défaut de la console. Si vous vaporisez une date sur la console, la sortie que vous voyez inclura votre fuseau horaire. C'est simplement parce que la console appelle toString()
votre date et toString()
vous donne une représentation locale. La date sous-jacente n'a pas de fuseau horaire ! (Tant que l'heure correspond au décalage du fuseau horaire, vous avez toujours un objet de date UTC à minuit)
Désérialisation (ou création d'objets de date UTC à minuit)
Il s'agit de l'étape d'arrondi, avec l'astuce qu'il y a deux «bonnes» réponses. La plupart du temps, vous souhaiterez que votre date reflète le fuseau horaire de l'utilisateur. Cliquez si aujourd'hui est votre anniversaire . Les utilisateurs en NZ et aux États-Unis cliquent en même temps et obtiennent des dates différentes. Dans ce cas, faites ceci ...
// create a date (utc midnight) reflecting the value of myDate and the environment's timezone offset.
new Date(Date.UTC(myDate.getFullYear(),myDate.getMonth(), myDate.getDate()));
Parfois, la comparabilité internationale l'emporte sur la précision locale. Dans ce cas, faites ceci ...
// the date in London of a moment in time. Device timezone is ignored.
new Date(Date.UTC(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate()));
Désérialiser une date
Souvent, les dates sur le fil seront au format AAAA-MM-JJ. Pour les désérialiser, faites ceci ...
var midnightUTCDate = new Date( dateString + 'T00:00:00Z');
Sérialisation
Après avoir pris soin de gérer le fuseau horaire lors de la création, vous devez maintenant vous assurer de ne pas afficher le fuseau horaire lors de la conversion en une représentation sous forme de chaîne. Vous pouvez donc utiliser en toute sécurité ...
toISOString()
getUTCxxx()
getTime() //returns a number with no time or timezone.
.toLocaleDateString("fr",{timezone:"UTC"}) // whatever locale you want, but ALWAYS UTC.
Et évitez totalement tout le reste, surtout ...
getYear()
, getMonth()
,getDate()
Alors pour répondre à votre question, 7 ans trop tard ...
<input type="date" onchange="isInPast(event)">
<script>
var isInPast = function(event){
var userEntered = new Date(event.target.valueAsNumber); // valueAsNumber has no time or timezone!
var now = new Date();
var today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() ));
if(userEntered.getTime() < today.getTime())
alert("date is past");
else if(userEntered.getTime() == today.getTime())
alert("date is today");
else
alert("date is future");
}
</script>
Voyez-le courir ...
Mise à jour 2019 ... des trucs gratuits ...
Compte tenu de la popularité de cette réponse, j'ai tout mis en code. La fonction suivante renvoie un objet date enveloppé et expose uniquement les fonctions dont l'utilisation est sûre avec just-a-date ™.
Appelez-le avec un objet Date et il se résoudra en JustADate reflétant le fuseau horaire de l'utilisateur. Appelez-le avec une chaîne: si la chaîne est un ISO 8601 avec un fuseau horaire spécifié, nous allons simplement arrondir la partie temporelle. Si le fuseau horaire n'est pas spécifié, nous le convertirons en une date reflétant le fuseau horaire local, tout comme pour les objets de date.
function JustADate(initDate){
var utcMidnightDateObj = null
// if no date supplied, use Now.
if(!initDate)
initDate = new Date();
// if initDate specifies a timezone offset, or is already UTC, just keep the date part, reflecting the date _in that timezone_
if(typeof initDate === "string" && initDate.match(/((\+|-)\d{2}:\d{2}|Z)$/gm)){
utcMidnightDateObj = new Date( initDate.substring(0,10) + 'T00:00:00Z');
} else {
// if init date is not already a date object, feed it to the date constructor.
if(!(initDate instanceof Date))
initDate = new Date(initDate);
// Vital Step! Strip time part. Create UTC midnight dateObj according to local timezone.
utcMidnightDateObj = new Date(Date.UTC(initDate.getFullYear(),initDate.getMonth(), initDate.getDate()));
}
return {
toISOString:()=>utcMidnightDateObj.toISOString(),
getUTCDate:()=>utcMidnightDateObj.getUTCDate(),
getUTCDay:()=>utcMidnightDateObj.getUTCDay(),
getUTCFullYear:()=>utcMidnightDateObj.getUTCFullYear(),
getUTCMonth:()=>utcMidnightDateObj.getUTCMonth(),
setUTCDate:(arg)=>utcMidnightDateObj.setUTCDate(arg),
setUTCFullYear:(arg)=>utcMidnightDateObj.setUTCFullYear(arg),
setUTCMonth:(arg)=>utcMidnightDateObj.setUTCMonth(arg),
addDays:(days)=>{
utcMidnightDateObj.setUTCDate(utcMidnightDateObj.getUTCDate + days)
},
toString:()=>utcMidnightDateObj.toString(),
toLocaleDateString:(locale,options)=>{
options = options || {};
options.timezone = "UTC";
locale = locale || "en-EN";
return utcMidnightDateObj.toLocaleDateString(locale,options)
}
}
}
// if initDate already has a timezone, we'll just use the date part directly
console.log(JustADate('1963-11-22T12:30:00-06:00').toLocaleDateString())
date1 === date2
ne semble pas fournir un comportement cohérent; il vaut mieux fairedate1.valueOf() === b.valueOf()
ou mêmedate1.getTime() === date2.getTime()
. Étrangeté.