BEACHTEN SIE DIE ZEITZONE
Wenn man das Datumsobjekt verwendet, um ein einfaches Datum darzustellen, hat man sofort ein großes Problem mit der übermäßigen Genauigkeit. Sie müssen die Zeit und die Zeitzone verwalten, um sie herauszuhalten, und sie können sich jederzeit wieder einschleichen. Die gängige Antwort auf diese Frage führt in die Falle.
Ein Javascript-Datum hat keine Kenntnis der Zeitzone . Es handelt sich um einen Moment in der Zeit (Ticks seit der Epoche) mit praktischen (statischen) Funktionen für die Übersetzung in und aus Zeichenketten, wobei standardmäßig die "lokale" Zeitzone des Geräts oder, falls angegeben, UTC oder eine andere Zeitzone verwendet wird. Um just-a-date™ mit einem Datumsobjekt darzustellen, Sie möchten, dass Ihre Daten UTC-Mitternacht zu Beginn des betreffenden Datums entsprechen. Dies ist eine gängige und notwendige Konvention, die es Ihnen ermöglicht, mit Daten unabhängig von der Jahreszeit oder Zeitzone ihrer Erstellung zu arbeiten. Sie müssen also sehr wachsam sein, um den Begriff der Zeitzone zu verwalten, sowohl bei der Erstellung Ihres Mitternachts-UTC-Datumsobjekts als auch bei dessen Serialisierung.
Viele Leute sind durch das Standardverhalten der Konsole verwirrt. Wenn Sie ein Datum in die Konsole sprühen, enthält die Ausgabe, die Sie sehen, Ihre Zeitzone. Das liegt einfach daran, dass die Konsole die Funktion toString()
bei Ihrem Date, und toString()
gibt Ihnen eine lokale Repräsentanz. Das zugrunde liegende Datum hat keine Zeitzone ! (Solange die Zeit mit dem Zeitzonen-Offset übereinstimmt, haben Sie immer noch ein Mitternachts-UTC-Datumsobjekt)
Deserialisierung (oder Erstellung von Mitternachts-UTC-Datumsobjekten)
Dies ist der Rundungsschritt mit dem Trick, dass es zwei "richtige" Antworten gibt. In den meisten Fällen möchten Sie, dass Ihr Datum die lokale Zeitzone des Benutzers widerspiegelt. Was ist das Datum hier, wo ich bin. . Nutzer in Neuseeland und den USA können gleichzeitig klicken und erhalten in der Regel unterschiedliche Daten. In diesem Fall, tun Sie dies...
// 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()));
Manchmal übertrifft die internationale Vergleichbarkeit die lokale Genauigkeit. In diesem Fall sollten Sie dies tun...
// the date in London of a moment in time. Device timezone is ignored.
new Date(Date.UTC(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate()));
Deserialisieren eines Datums
Häufig werden die Daten auf der Leitung im Format JJJJ-MM-TT angegeben. Um sie zu deserialisieren, tun Sie Folgendes...
var midnightUTCDate = new Date( dateString + 'T00:00:00Z');
Serialisierung
Nachdem Sie bei der Erstellung darauf geachtet haben, die Zeitzone zu verwalten, müssen Sie nun sicherstellen, dass die Zeitzone bei der Rückkonvertierung in eine String-Darstellung nicht berücksichtigt wird. So können Sie sicher verwenden...
toISOString()
getUTCxxx()
getTime() //returns a number with no time or timezone.
.toLocaleDateString("fr",{timeZone:"UTC"}) // whatever locale you want, but ALWAYS UTC.
Und vermeiden Sie alles andere, vor allem...
getYear()
, getMonth()
, getDate()
Um also Ihre Frage zu beantworten: 7 Jahre zu spät...
<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>
Sehen Sie es laufen...
Update 2019... kostenlose Sachen...
In Anbetracht der Beliebtheit dieser Antwort habe ich alles in Code geschrieben. Die folgende Funktion gibt ein umhülltes Datumsobjekt zurück und stellt nur die Funktionen zur Verfügung, die sicher mit just-a-date™ verwendet werden können.
Rufen Sie es mit einem Date-Objekt auf, und es wird in JustADate aufgelöst, das die Zeitzone des Benutzers widerspiegelt. Aufruf mit einer Zeichenkette: Wenn die Zeichenkette eine ISO 8601-Zeichenkette mit angegebener Zeitzone ist, wird nur der Zeitteil abgerundet. Wenn die Zeitzone nicht angegeben ist, wird sie in ein Datum konvertiert, das die lokale Zeitzone widerspiegelt, genau wie bei Datumsobjekten.
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())
8 Stimmen
date1.toDateString() === date2.toDateString()
0 Stimmen
Von den Toten auferstanden: Ich erhalte fehlerhafte Ergebnisse von
date.setFullYear(yyyy,mm,dd)
Wenn ich toSting auf das Datum anwende, wird der Monat um 1 erhöht. Getestet auf dieser Seite Link sowohl in FireFox als auch in Edge.