CUIDADO CON LA TIMEZONE
Usar el objeto de fecha para representar solo una fecha de inmediato lo lleva a un gran problema de exceso de precisión. Debe administrar el tiempo y la zona horaria para mantenerlos alejados, y pueden colarse en cualquier momento. La respuesta aceptada a esta pregunta cae en la trampa.
Una fecha de JavaScript no tiene noción de zona horaria . Es un momento en el tiempo (marca desde la época) con prácticas funciones (estáticas) para traducir hacia y desde cadenas, utilizando de forma predeterminada la zona horaria "local" del dispositivo o, si se especifica, UTC u otra zona horaria. Para representar just-a-date ™ con un objeto de fecha, desea que sus fechas representen la medianoche UTC al comienzo de la fecha en cuestión. Esta es una convención común y necesaria que le permite trabajar con fechas independientemente de la temporada o zona horaria de su creación. Por lo tanto, debe estar muy atento para administrar la noción de zona horaria, tanto cuando crea su objeto UTC Date de medianoche como cuando lo serializa.
Mucha gente está confundida por el comportamiento predeterminado de la consola. Si aplica una fecha a la consola, la salida que verá incluirá su zona horaria. Esto es solo porque la consola llama toString()
a tu cita y toString()
te da una representación local. ¡La fecha subyacente no tiene zona horaria ! (Mientras la hora coincida con el desplazamiento de la zona horaria, todavía tiene un objeto de fecha UTC de medianoche)
Deserialización (o creación de objetos UTC Date a medianoche)
Este es el paso de redondeo, con el truco de que hay dos respuestas "correctas". La mayoría de las veces, querrá que su fecha refleje la zona horaria del usuario. Haz clic si hoy es tu cumpleaños . Los usuarios de NZ y EE. UU. Hacen clic al mismo tiempo y obtienen fechas diferentes. En ese caso, haz esto ...
// 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 veces, la comparabilidad internacional supera la precisión local. En ese caso, haz esto ...
// the date in London of a moment in time. Device timezone is ignored.
new Date(Date.UTC(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate()));
Deserializar una fecha
A menudo, las fechas en el cable tendrán el formato AAAA-MM-DD. Para deserializarlos, haz esto ...
var midnightUTCDate = new Date( dateString + 'T00:00:00Z');
Serializando
Habiendo tenido cuidado de administrar la zona horaria cuando crea, ahora debe asegurarse de mantener la zona horaria fuera cuando convierta nuevamente a una representación de cadena. Para que pueda usar con seguridad ...
toISOString()
getUTCxxx()
getTime() //returns a number with no time or timezone.
.toLocaleDateString("fr",{timezone:"UTC"}) // whatever locale you want, but ALWAYS UTC.
Y evita totalmente todo lo demás, especialmente ...
getYear()
` getMonth()
`getDate()
Entonces, para responder a su pregunta, 7 años demasiado tarde ...
<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>
Véalo correr ...
Actualización 2019 ... cosas gratis ...
Dada la popularidad de esta respuesta, lo puse todo en código. La siguiente función devuelve un objeto de fecha envuelta y solo expone aquellas funciones que son seguras de usar con just-a-date ™.
Llámalo con un objeto Date y se resolverá en JustADate reflejando la zona horaria del usuario. Llámalo con una cadena: si la cadena es un ISO 8601 con la zona horaria especificada, simplemente redondearemos la parte del tiempo. Si no se especifica la zona horaria, la convertiremos a una fecha que refleje la zona horaria local, al igual que para los objetos de fecha.
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
no parecen proporcionar un comportamiento coherente; Es mejor hacerlodate1.valueOf() === b.valueOf()
o inclusodate1.getTime() === date2.getTime()
. Extrañeza.