Fall eins:
new Date(Date.parse("Jul 8, 2005"));
Sortie :
Fri Jul 08 2005 00:00:00 GMT-0700 (PST)
Fall 2:
new Date(Date.parse("2005-07-08"));
Sortie :
Thu Jul 07 2005 17:00:00 GMT-0700 (PST)
Warum ist das zweite Parsing falsch?
new Date(Date.parse("Jul 8, 2005"));
Fri Jul 08 2005 00:00:00 GMT-0700 (PST)
new Date(Date.parse("2005-07-08"));
Thu Jul 07 2005 17:00:00 GMT-0700 (PST)
Warum ist das zweite Parsing falsch?
Bis zum Erscheinen der 5. Auflage der Spezifikation war die Date.parse
Methode war vollständig Implementierungsabhängig ( new Date(string)
ist gleichbedeutend mit Date.parse(string)
mit der Ausnahme, dass letztere eine Zahl anstelle einer Date
). In der Spezifikation der 5. Auflage wurde die Anforderung hinzugefügt, eine vereinfacht (und leicht falsch) ISO-8601 (siehe auch Was sind gültige Date Time Strings in JavaScript? ). Aber abgesehen davon gab es no Anforderung für was Date.parse
/ new Date(string)
akzeptieren sollten, als dass sie das akzeptieren mussten, was Date#toString
Output (ohne zu sagen, was das war).
Ab ECMAScript 2017 (Edition 8) müssen Implementierungen ihre Ausgabe für Date#toString
et Date#toUTCString
aber das Format dieser Zeichenketten wurde nicht angegeben.
Ab ECMAScript 2019 (Edition 9) wird das Format für Date#toString
et Date#toUTCString
wurden als (jeweils) angegeben:
mit 2 weiteren Formaten, die Date.parse
sollte in neuen Implementierungen zuverlässig geparst werden (wobei zu beachten ist, dass die Unterstützung nicht allgegenwärtig ist und nicht konforme Implementierungen noch einige Zeit in Gebrauch sein werden).
Ich würde empfehlen, dass Datumsstrings manuell geparst werden und die Datum-Konstruktor mit den Argumenten Jahr, Monat und Tag verwendet, um Mehrdeutigkeiten zu vermeiden:
// parse a date in yyyy-mm-dd format
function parseDate(input) {
let parts = input.split('-');
// new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
return new Date(parts[0], parts[1]-1, parts[2]); // Note: months are 0-based
}
Während meiner jüngsten Erfahrungen beim Schreiben eines JS-Interpreters habe ich viel mit dem Innenleben der ECMA/JS-Daten gerungen. Also, ich denke, ich werde in meine 2 Cent hier werfen. Ich hoffe, dass die Weitergabe dieser Informationen anderen helfen wird, die Fragen zu den Unterschieden zwischen den Browsern bei der Handhabung von Datumsangaben haben.
Alle Implementierungen speichern ihre Datumswerte intern als 64-Bit-Zahlen, die die Anzahl der Millisekunden (ms) seit dem 01.01.1970 UTC darstellen (GMT ist das Gleiche wie UTC). Dieses Datum ist die ECMAScript-Epoche, die auch von anderen Sprachen wie Java und POSIX-Systemen wie UNIX verwendet wird. Daten, die nach der Epoche liegen, sind positive Zahlen, Daten davor sind negativ.
Der folgende Code wird in allen aktuellen Browsern als dasselbe Datum interpretiert, allerdings mit dem Offset der lokalen Zeitzone:
Date.parse('1/1/1970'); // 1 January, 1970
In meiner Zeitzone (EST, also -05:00) ist das Ergebnis 18000000, denn so viele ms sind in 5 Stunden (in den Sommermonaten sind es nur 4 Stunden). Der Wert wird in verschiedenen Zeitzonen unterschiedlich sein. Dieses Verhalten ist in der ECMA-262 festgelegt, so dass alle Browser dies auf die gleiche Weise tun.
Es gibt zwar einige Unterschiede bei den Formaten der Eingabezeichenfolgen, die von den wichtigsten Browsern als Datumsangaben interpretiert werden, aber im Wesentlichen interpretieren sie sie in Bezug auf Zeitzonen und Sommerzeit gleich, auch wenn das Parsing weitgehend von der Implementierung abhängt.
Das Format ISO 8601 ist jedoch anders. Es ist eines von nur zwei Formaten in ECMAScript 2015 (Ausgabe 6), die von allen Implementierungen auf die gleiche Weise geparst werden müssen (das andere ist das Format, das für Date.prototype.toString ).
Aber selbst bei Zeichenketten im ISO 8601-Format gibt es Implementierungen, die es falsch machen. Hier ist eine Vergleichsausgabe von Chrome und Firefox, als diese Antwort ursprünglich für den 1.1.1970 (die Epoche) auf meinem Rechner unter Verwendung von Zeichenketten im ISO 8601-Format geschrieben wurde, die debe in allen Implementierungen auf genau den gleichen Wert geparst werden:
Date.parse('1970-01-01T00:00:00Z'); // Chrome: 0 FF: 0
Date.parse('1970-01-01T00:00:00-0500'); // Chrome: 18000000 FF: 18000000
Date.parse('1970-01-01T00:00:00'); // Chrome: 0 FF: 18000000
Dieser Unterschied wurde ab 2020 behoben, aber es gibt noch andere Macken zwischen den Browsern beim Parsen von Zeichenketten im ISO 8601-Format.
Aber es kommt noch schlimmer. Eine Besonderheit der ECMA-262 besteht darin, dass das reine ISO 8601-Datumsformat (JJJJ-MM-TT) als UTC geparst werden muss, während es nach ISO 8601 als Lokalformat geparst werden muss. Hier ist die Ausgabe von FF mit den langen und kurzen ISO-Datumsformaten ohne Zeitzonenangabe.
Date.parse('1970-01-01T00:00:00'); // 18000000
Date.parse('1970-01-01'); // 0
Die erste wird also als Ortszeit geparst, weil es sich um ISO 8601 Datum und Uhrzeit ohne Zeitzone handelt, und die zweite wird als UTC geparst, weil es sich nur um ein ISO 8601 Datum handelt.
Um also die ursprüngliche Frage direkt zu beantworten, "YYYY-MM-DD"
muss gemäß ECMA-262 als UTC interpretiert werden, während der andere als lokal interpretiert wird. Das ist der Grund:
console.log(new Date(Date.parse("Jul 8, 2005")).toString()); // Local
console.log(new Date(Date.parse("2005-07-08")).toString()); // UTC
console.log(new Date(Date.parse("Jul 8, 2005")).toString());
console.log(new Date(Date.parse("2005-07-08T00:00:00")).toString());
Die Quintessenz für das Parsen von Datumszeichenfolgen ist die folgende. Die EINZIGE ISO 8601-Zeichenkette, die Sie sicher in allen Browsern analysieren können, ist die lange Form mit einem Versatz (entweder ±HH:mm oder "Z"). Auf diese Weise können Sie sicher zwischen Ortszeit und UTC-Zeit hin- und herwechseln.
console.log(new Date(Date.parse("2005-07-08T00:00:00Z")).toString());
Die meisten aktuellen Browser behandeln die anderen Eingabeformate gleich, einschließlich der häufig verwendeten Formate "1/1/1970" (M/D/YYYY) und "1/1/1970 00:00:00 AM" (M/D/YYYY hh:mm:ss ap). Alle folgenden Formate (außer dem letzten) werden in allen Browsern als Eingabe der Ortszeit behandelt. Die Ausgabe dieses Codes ist in allen Browsern in meiner Zeitzone gleich. Das letzte Format wird unabhängig von der Zeitzone des Hosts als -05:00 behandelt, da der Offset im Zeitstempel festgelegt ist:
console.log(Date.parse("1/1/1970"));
console.log(Date.parse("1/1/1970 12:00:00 AM"));
console.log(Date.parse("Thu Jan 01 1970"));
console.log(Date.parse("Thu Jan 01 1970 00:00:00"));
console.log(Date.parse("Thu Jan 01 1970 00:00:00 GMT-0500"));
Da jedoch selbst die in ECMA-262 spezifizierten Formate nicht einheitlich geparst werden, wird empfohlen, sich nie auf den eingebauten Parser zu verlassen und Zeichenketten immer manuell zu parsen, z. B. mithilfe einer Bibliothek, und dem Parser das Format zu übergeben.
In moment.js könnten Sie z.B. schreiben:
let m = moment('1/1/1970', 'M/D/YYYY');
Auf der Ausgabeseite übersetzen alle Browser die Zeitzonen auf die gleiche Weise, aber sie behandeln die String-Formate unterschiedlich. Hier sind die toString
Funktionen und was sie ausgeben. Beachten Sie die toUTCString
et toISOString
Funktionen geben auf meinem Rechner 5:00 Uhr morgens aus. Außerdem kann der Name der Zeitzone eine Abkürzung sein und in verschiedenen Implementierungen anders lauten.
Konvertiert vor dem Drucken von UTC in die lokale Zeit
- toString
- toDateString
- toTimeString
- toLocaleString
- toLocaleDateString
- toLocaleTimeString
Druckt die gespeicherte UTC-Zeit direkt aus
- toUTCString
- toISOString
In Chrome
toString Thu Jan 01 1970 00:00:00 GMT-05:00 (Eastern Standard Time)
toDateString Thu Jan 01 1970
toTimeString 00:00:00 GMT-05:00 (Eastern Standard Time)
toLocaleString 1/1/1970 12:00:00 AM
toLocaleDateString 1/1/1970
toLocaleTimeString 00:00:00 AM
toUTCString Thu, 01 Jan 1970 05:00:00 GMT
toISOString 1970-01-01T05:00:00.000Z
In Firefox
toString Thu Jan 01 1970 00:00:00 GMT-05:00 (Eastern Standard Time)
toDateString Thu Jan 01 1970
toTimeString 00:00:00 GMT-0500 (Eastern Standard Time)
toLocaleString Thursday, January 01, 1970 12:00:00 AM
toLocaleDateString Thursday, January 01, 1970
toLocaleTimeString 12:00:00 AM
toUTCString Thu, 01 Jan 1970 05:00:00 GMT
toISOString 1970-01-01T05:00:00.000Z
Ich verwende normalerweise nicht das ISO-Format für die Eingabe von Zeichenketten. Das einzige Mal, dass dieses Format für mich von Vorteil ist, ist, wenn Daten als Zeichenketten sortiert werden müssen. Das ISO-Format ist ohne weiteres sortierbar, die anderen Formate nicht. Wenn Sie eine browserübergreifende Kompatibilität benötigen, geben Sie entweder die Zeitzone an oder verwenden Sie ein kompatibles String-Format.
Der Code new Date('12/4/2013').toString()
durchläuft die folgende interne Pseudo-Transformation:
"12/4/2013" -> toUCT -> [storage] -> toLocal -> print "12/4/2013"
Ich hoffe, diese Antwort war hilfreich.
Der Wahnsinn hat Methode. Generell gilt: Wenn ein Browser ein Datum als ISO-8601 interpretieren kann, tut er das auch. "2005-07-08" fällt in dieses Lager und wird daher als UTC geparst. "8. Juli 2005" kann das nicht und wird daher in der lokalen Zeit geparst.
Voir JavaScript und Daten, was für ein Chaos! für mehr.
Eine andere Lösung besteht darin, ein assoziatives Array mit Datumsformat zu erstellen und die Daten dann neu zu formatieren.
Diese Methode ist nützlich für ungewöhnlich formatierte Daten.
Ein Beispiel:
mydate='01.02.12 10:20:43':
myformat='dd/mm/yy HH:MM:ss';
dtsplit=mydate.split(/[\/ .:]/);
dfsplit=myformat.split(/[\/ .:]/);
// creates assoc array for date
df = new Array();
for(dc=0;dc<6;dc++) {
df[dfsplit[dc]]=dtsplit[dc];
}
// uses assc array for standard mysql format
dstring[r] = '20'+df['yy']+'-'+df['mm']+'-'+df['dd'];
dstring[r] += ' '+df['HH']+':'+df['MM']+':'+df['ss'];
Utilisez moment.js zum Parsen von Daten:
var caseOne = moment("Jul 8, 2005", "MMM D, YYYY", true).toDate();
var caseTwo = moment("2005-07-08", "YYYY-MM-DD", true).toDate();
Das 3. Argument bestimmt strict parsing (verfügbar ab 2.3.0). Ohne dieses Argument kann moment.js auch falsche Ergebnisse liefern.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.