ATTENZIONE AL FUSO ORARIO
L'utilizzo dell'oggetto date per rappresentare subito una data ti mette in un enorme problema di precisione in eccesso. È necessario gestire il tempo e il fuso orario per tenerli fuori e possono rientrare di soppiatto in qualsiasi momento. La risposta accettata a questa domanda cade nella trappola.
Una data javascript non ha nozione di fuso orario . È un momento nel tempo (segni di spunta dall'epoca) con pratiche funzioni (statiche) per la traduzione da e verso le stringhe, utilizzando di default il fuso orario "locale" del dispositivo o, se specificato, UTC o un altro fuso orario. Per rappresentare just-a-date ™ con un oggetto data, si desidera che le date rappresentino la mezzanotte UTC all'inizio della data in questione. Questa è una convenzione comune e necessaria che ti consente di lavorare con le date indipendentemente dalla stagione o dal fuso orario della loro creazione. Quindi è necessario essere molto vigili per gestire la nozione di fuso orario, sia quando si crea l'oggetto Data UTC di mezzanotte, sia quando lo si serializza.
Molte persone sono confuse dal comportamento predefinito della console. Se si spruzza una data sulla console, l'output visualizzato includerà il fuso orario. Questo perché la console chiama toString()
il tuo appuntamento e toString()
ti dà una rappresentazione locale. La data sottostante non ha fuso orario ! (Fintanto che l'ora corrisponde all'offset del fuso orario, hai ancora un oggetto data UTC di mezzanotte)
Deserializzazione (o creazione di oggetti Data UTC di mezzanotte)
Questa è la fase di arrotondamento, con il trucco che ci sono due risposte "giuste". Il più delle volte, vorrai che la tua data rifletta il fuso orario dell'utente. Fai clic su se oggi è il tuo compleanno . Gli utenti in Nuova Zelanda e Stati Uniti fanno clic contemporaneamente e ottengono date diverse. In tal caso, fai questo ...
// 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()));
A volte, la comparabilità internazionale supera l'accuratezza locale. In tal caso, fai questo ...
// the date in London of a moment in time. Device timezone is ignored.
new Date(Date.UTC(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate()));
Deserializzare una data
Spesso le date sul filo saranno nel formato AAAA-MM-GG. Per deserializzarli, fai questo ...
var midnightUTCDate = new Date( dateString + 'T00:00:00Z');
serializzazione
Avendo cura di gestire il fuso orario durante la creazione, ora è necessario essere sicuri di mantenere il fuso orario fuori quando si converte nuovamente in una rappresentazione di stringa. Quindi puoi usare tranquillamente ...
toISOString()
getUTCxxx()
getTime() //returns a number with no time or timezone.
.toLocaleDateString("fr",{timezone:"UTC"}) // whatever locale you want, but ALWAYS UTC.
Ed evita totalmente tutto il resto, specialmente ...
getYear()
, getMonth()
,getDate()
Quindi, per rispondere alla tua domanda, 7 anni in ritardo ...
<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>
Guardalo in esecuzione ...
Aggiornamento 2019 ... roba gratis ...
Data la popolarità di questa risposta, ho inserito tutto nel codice. La seguente funzione restituisce un oggetto data spostato ed espone solo quelle funzioni che sono sicure da usare con just-a-date ™.
Chiamalo con un oggetto Date e si risolverà in JustADate in base al fuso orario dell'utente. Chiamalo con una stringa: se la stringa è ISO 8601 con il fuso orario specificato, completeremo semplicemente la parte temporale. Se il fuso orario non è specificato, lo convertiremo in una data che riflette il fuso orario locale, proprio come per gli oggetti data.
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
non sembra fornire un comportamento coerente; è meglio faredate1.valueOf() === b.valueOf()
o anchedate1.getTime() === date2.getTime()
. Stranezza.