Ungültiges Datum in der Safari

155
 alert(new Date('2010-11-29'));

chrome, ff hat damit keine probleme, aber safari schreit "ungültiges datum". Warum ?

edit: ok, gemäß den Kommentaren unten habe ich String-Parsing verwendet und Folgendes versucht:

alert(new Date('11-29-2010')); //doesn't work in safari
alert(new Date('29-11-2010')); //doesn't work in safari
alert(new Date('2010-29-11')); //doesn't work in safari

Bearbeiten 22. März 2018 : Scheint, als ob die Leute immer noch hier landen - heute würde ich momentoder verwenden date-fnsund damit fertig sein. Date-fns ist sehr schmerzfrei und auch leicht.

Shrinath
quelle
Nur für andere, die sich das gleiche Problem ansehen: Am Ende habe ich DateJS verwendet, wodurch mein Problem insgesamt gelöst wurde. Weitere Informationen finden Sie in der akzeptierten Antwort.
Shrinath
2
Verwenden Sie moment.js , um den Zeitstempel zu analysieren. Besonders wenn es um plattformübergreifendes Web geht
Ming Yuen
1
Dies ist eine alte Frage. Ab ECMAScript 2015 werden Nur-Datum-Zeichenfolgen nach ISO 8601 als UTC analysiert. Möglicherweise gibt es jedoch noch ältere Browser, die diese entweder gar nicht analysieren oder als lokal behandeln.
RobG

Antworten:

166

Das Muster yyyy-MM-ddist kein offiziell unterstütztes Format für DateKonstruktoren. Firefox scheint dies zu unterstützen, aber rechnen Sie nicht damit, dass andere Browser dasselbe tun.

Hier sind einige unterstützte Zeichenfolgen:

  • MM-TT-JJJJ
  • JJJJ / MM / TT
  • MM / TT / JJJJ
  • MMMM TT, JJJJ
  • MMM TT, JJJJ

DateJS scheint eine gute Bibliothek zum Parsen von nicht standardmäßigen Datumsformaten zu sein.

Bearbeiten : gerade ECMA-262 Standard überprüft . Zitat aus Abschnitt 15.9.1.15:

Datum Uhrzeit Zeichenfolgenformat

ECMAScript definiert ein Zeichenfolgenaustauschformat für Datums- und Uhrzeitangaben basierend auf einer Vereinfachung des erweiterten ISO 8601-Formats. Das Format lautet wie folgt: JJJJ-MM-TTTHH: mm: ss.sssZ Die Felder lauten wie folgt:

  • JJJJ ist die Dezimalstelle des Jahres im Gregorianischen Kalender.
  • "-" (Hyphon) erscheint buchstäblich zweimal in der Zeichenfolge.
  • MM ist der Monat des Jahres von 01 (Januar) bis 12 (Dezember).
  • DD ist der Tag des Monats von 01 bis 31.
  • "T" erscheint buchstäblich in der Zeichenfolge, um den Beginn des Zeitelements anzuzeigen.
  • HH ist die Anzahl der vollständigen Stunden, die seit Mitternacht vergangen sind, als zwei Dezimalstellen.
  • ":" (Doppelpunkt) erscheint buchstäblich zweimal in der Zeichenfolge.
  • mm ist die Anzahl der vollständigen Minuten seit Beginn der Stunde als zwei Dezimalstellen.
  • ss ist die Anzahl der vollständigen Sekunden seit Beginn der Minute als zwei Dezimalstellen.
  • "." (Punkt) erscheint buchstäblich in der Zeichenfolge.
  • sss ist die Anzahl der vollständigen Millisekunden seit dem Beginn der Sekunde als drei Dezimalstellen. Beide "." und das Millisekundenfeld kann weggelassen werden.
  • Z ist der Zeitzonenversatz, der als "Z" (für UTC) oder entweder "+" oder "-" gefolgt von einem Zeitausdruck hh: mm angegeben ist

Dieses Format enthält nur Datumsformulare:

  • JJJJ
  • JJJJ-MM
  • JJJJ-MM-TT

Es enthält auch Zeitformulare mit einem optionalen Zeitzonenversatz:

  • THH: mm
  • THH: mm: ss
  • THH: mm: ss.sss

Ebenfalls enthalten sind "Datums- und Uhrzeitangaben", die eine beliebige Kombination der oben genannten sein können.

Es scheint also, dass JJJJ-MM-TT im Standard enthalten ist, aber aus irgendeinem Grund unterstützt Safari dies nicht.

Update : Nachdem Sie sich die Dokumentation von datejs angesehen haben, sollte Ihr Problem mit folgendem Code gelöst werden:

var myDate1 = Date.parseExact("29-11-2010", "dd-MM-yyyy");
var myDate2 = Date.parseExact("11-29-2010", "MM-dd-yyyy");
var myDate3 = Date.parseExact("2010-11-29", "yyyy-MM-dd");
var myDate4 = Date.parseExact("2010-29-11", "yyyy-dd-MM");
Darioo
quelle
4
Das ISO8601-Format wird in der 5. Ausgabe des ECMAScript-Standards verwendet und wird noch nicht allgemein unterstützt. Dies ist der sicherste Weg, um IMO zu erreichen. Analysieren Sie das Datum manuell :(
CMS
1
Das war sehr hilfreich, Alter. Danke. :) Endlich habe ich datejs für die Formatierung verwendet.
Shrinath
Für diejenigen in der Zukunft beachten Sie bitte, dass datejs zwar in vielerlei Hinsicht fantastisch ist, jedoch nicht alle Probleme bei der Datumsformatierung löst, insbesondere bei Safari. Es ist eine PITA, aber es ist am besten, es manuell zu machen, wenn Sie immer noch Probleme haben.
totalNotLizards
@darioo Also habe ich Ihre Antwort wie folgt versucht: "var start = Date.parseExact (Zeitstempel," JJJJ-TT-MM HH: mm: SS ");" Der Zeitstempel lautet "2016-01-28 00:00:00". Jetzt erhalte ich jedoch die Fehlermeldung, dass "Date.parseExact keine Funktion ist". Weißt du, was hier passiert?
Threxx
5
Mein ähnliches Problem wurde dadurch verursacht, dass Safari nicht wusste, wie die Zeitzone in einem RFC 822-Zeitzonenformat gelesen werden kann. Ich konnte dies mithilfe des ISO 8601-Formats beheben. Wenn Sie die Kontrolle über das Datumsformat haben, funktioniert dies mit "yyyy-MM-dd'T'HH: mm: ss.sssXXX", das dh erstellt. "2018-02-06T20: 00: 00.000 + 00: 00". Beachten Sie aus irgendeinem Grund, dass Safari "2018-02-06T20: 00: 00.000 + 0000" nicht lesen kann. Beachten Sie das Fehlen eines Doppelpunkts im Zeitzonenformat.
Olmstov
223

Für mich ist die Implementierung einer neuen Bibliothek, nur weil Safari sie nicht richtig ausführen kann, zu viel und ein regulärer Ausdruck ist übertrieben. Hier ist der Oneliner :

console.log (new Date('2011-04-12'.replace(/-/g, "/")));
Elzo Valugi
quelle
Wenn es nur mein Problem gewesen wäre, einen Schrägstrich zu bekommen, hätte ich Ihre Antwort "akzeptiert" (obwohl dies mein einziges Ziel war, als ich diese Frage stellte). Nachdem ich dateJS gefunden hatte, implementierte ich das Format MMM TT, JJJJ für eine benutzerfreundlichere Erfahrung !!!
Shrinath
13
Diese einzeilige Hilfe war perfekt für meine Bedürfnisse! Vielen Dank!
Cyril N.
4
Das war auch für mich einfach genug. Ich kann nicht glauben, dass Safari das nicht mag - aber das gleiche Format mit einem \\ funktioniert. Danke @Elzo und danke Shrinath für das Posten der Frage
Pete
1
Ich denke, dies ist die beste Antwort, die ich eher vergesse / - / g anstelle von '-'
Jacek Pietal
12
Applaus dafür, dass keine Bibliothek implementiert wurde.
lharby
55

Ich hatte ein ähnliches Problem. Date.Parse("DATESTRING")arbeitete unter Chrome (Version 59.0.3071.115), aber nicht unter Safari (Version 10.1.1 (11603.2.5)).

Safari:

Date.parse("2017-01-22 11:57:00")
NaN

Chrom:

Date.parse("2017-01-22 11:57:00")
1485115020000

Die Lösung, die für mich funktioniert hat, war das Ersetzen des Leerzeichens im dateString durch "T". (Beispiel: dateString.replace(/ /g,"T"))

Safari:

Date.parse("2017-01-22T11:57:00")
1485086220000

Chrom:

Date.parse("2017-01-22T11:57:00")
1485115020000

Beachten Sie, dass die Antwort vom Safari-Browser 8 Stunden (28800000 ms) weniger ist als die Antwort im Chrome-Browser, da Safari die Antwort in der lokalen TZ zurückgegeben hat (8 Stunden hinter UTC).

Um beide Zeiten in derselben TZ zu bekommen

Safari:

Date.parse("2017-01-22T11:57:00Z")
1485086220000

Chrom:

Date.parse("2017-01-22T11:57:00Z")
1485086220000
nizantz
quelle
Wenn in Safari und Chrome nicht beide Daten identisch sein sollen, können Sie den new Date(year, month, date, hours, minutes, seconds, milliseconds)Konstruktor verwenden. Analysieren Sie das Zeichenfolgendatum in ein Array seiner Komponenten, um diese Komponenten im Konstruktor zu verwenden. @nizantz Es wäre großartig, wenn Sie glauben, dass ein solches Beispiel zu Ihrer Antwort hinzugefügt werden könnte.
h3dkandi
Nicht besonders nützlich, da Sie das Datum in UTC und nicht in der Ortszeit erhalten.
Jonas Äppelgran
1
Diese dateString.replace(/ /g,"T")magische Codezeile hat von mir aus funktioniert. :)
Mazdak Shojaie
ersetzen (/ - / g, '/')
Jack Hu
11

Ich nutze den Moment, um das Problem zu lösen. Beispielsweise

var startDate = moment('2015-07-06 08:00', 'YYYY-MM-DD HH:mm').toDate();
liwp_Stephen
quelle
10

Damit eine Lösung in den meisten Browsern funktioniert, sollten Sie Ihr Datumsobjekt in diesem Format erstellen

(year, month, date, hours, minutes, seconds, ms)

z.B:

dateObj = new Date(2014, 6, 25); //UTC time / Months are mapped from 0 to 11
alert(dateObj.getTime()); //gives back timestamp in ms

funktioniert gut mit IE, FF, Chrome und Safari. Auch ältere Versionen.

IE Dev Center: Datumsobjekt (JavaScript)

Mozilla Dev Network: Datum

Luxx
quelle
6

String in Date fromat konvertieren (Sie müssen die Zeitzone des Servers kennen)

new Date('2015-06-16 11:00:00'.replace(/\s+/g, 'T').concat('.000+08:00')).getTime()  

Dabei ist +08: 00 = Zeitzone vom Server

Anja Ishmukhametova
quelle
Dies berücksichtigt nicht die Sommerzeit. Der TZ-Offset kann schwanken und hängt vom Datum selbst (und der Uhrzeit) ab.
Costa
5

Ich hatte das gleiche Problem. Dann habe ich Moment verwendet. Js .Problem ist verschwunden.

Wenn Sie einen Moment aus einer Zeichenfolge erstellen, prüfen wir zunächst, ob die Zeichenfolge mit bekannten ISO 8601-Formaten übereinstimmt, und greifen dann auf das neue Datum (Zeichenfolge) zurück, wenn kein bekanntes Format gefunden wird.

Warnung: Die Browserunterstützung für das Parsen von Zeichenfolgen ist inkonsistent. Da es keine Spezifikation gibt, welche Formate unterstützt werden sollen, funktioniert das, was in einigen Browsern funktioniert, in anderen Browsern nicht.

Für konsistente Ergebnisse beim Parsen anderer Zeichenfolgen als ISO 8601-Zeichenfolgen sollten Sie Zeichenfolge + Format verwenden.

z.B

var date= moment(String);
Sampath
quelle
3

Obwohl Sie vielleicht hoffen, dass Browser ISO 8601 (oder Teilmengen davon nur mit Datum) unterstützen, ist dies nicht der Fall. Alle mir bekannten Browser (zumindest in den von mir verwendeten US / English-Gebietsschemas) können das schreckliche US- MM/DD/YYYYFormat analysieren .

Wenn Sie bereits über die Teile des Datums verfügen, können Sie stattdessen Date.UTC () verwenden . Wenn Sie dies nicht tun, aber das YYYY-MM-DDFormat verwenden müssen, empfehle ich, einen regulären Ausdruck zu verwenden, um die Ihnen bekannten Teile zu analysieren und sie dann an weiterzugeben Date.UTC().

Phrogz
quelle
Ich denke, String-Parsing ist der
richtige
1

Verwenden Sie das folgende Format, es würde auf allen Browsern funktionieren

var year = 2016;
var month = 02;           // month varies from 0-11 (Jan-Dec)
var day = 23;

month = month<10?"0"+month:month;        // to ensure YYYY-MM-DD format
day = day<10?"0"+day:day;

dateObj = new Date(year+"-"+month+"-"+day);

alert(dateObj); 

// Ihre Ausgabe würde folgendermaßen aussehen "Mi 23 Mrz 2016 00:00:00 GMT + 0530 (IST)"

// Beachten Sie, dass dies in diesem Fall in der aktuellen Zeitzone liegt, die mit IST bezeichnet ist, um in eine UTC-Zeitzone zu konvertieren, die Sie einschließen können

alert(dateObj.toUTCSting);

// Ihre Ausgabe möchte jetzt "Di, 22 Mar 2016 18:30:00 GMT"

Beachten Sie, dass jetzt das DatumObj die Uhrzeit im GMT-Format anzeigt. Beachten Sie auch, dass Datum und Uhrzeit entsprechend geändert wurden.

Die Funktion "toUTCSting" ruft die entsprechende Zeit am Greenwich-Meridian ab. Dies wird erreicht, indem der Zeitunterschied zwischen Ihrer aktuellen Zeitzone und der Greenwich-Meridian-Zeitzone ermittelt wird.

Im obigen Fall betrug die Zeit vor der Konvertierung am 23. März 2016 00:00 Stunden und Minuten. Nach der Konvertierung von GMT + 0530 (IST) Stunden in GMT (in diesem Fall werden im Wesentlichen 5,30 Stunden vom angegebenen Zeitstempel abgezogen Fall) Die Zeit entspricht 18,30 Stunden am 22. März 2016 (genau 5,30 Stunden hinter dem ersten Mal).

Außerdem können Sie jedes Datumsobjekt in einen Zeitstempel konvertieren, den Sie verwenden können

alert(dateObj.getTime());

// Ausgabe würde ungefähr so ​​aussehen wie "1458671400000"

Dies würde Ihnen den einzigartigen Zeitstempel der Zeit geben

Abhay Aradhya
quelle
1

Wie wäre es mit einer Entführung Datemit festem Datum ? Keine Abhängigkeiten, min + gzip = 280 B.

Kenberkeley
quelle
1

Der beste Weg, dies zu tun, ist das folgende Format:

new Date(year, month, day, hours, minutes, seconds, milliseconds)
var d = new Date(2018, 11, 24, 10, 33, 30, 0);

Dies wird in allen Browsern unterstützt und gibt Ihnen keine Probleme. Bitte beachten Sie, dass die Monate von 0 bis 11 geschrieben sind.

Daniël Brito
quelle
Funktioniert gut unter Safari und Chrome, hat aber immer noch Probleme mit Firefox. Safari: var date = neues Datum (2018,06,08,19,17) So Jul 08 2018 19:17:00 GMT + 0800 (+08) Chrome: var date = neues Datum (2018,06,08,19, 17) Sun Jul 08 2018 19:17:00 GMT + 0800 (Malaysia Time) Firefox: var date = new Date (2018,06,08,19,17) Date 2018-07-08T11: 17: 00.000Z
Biranchi
0

Das gleiche Problem, mit dem Safari konfrontiert war, wurde durch Einfügen in eine Webseite behoben

 <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script> 

Hoffe, es wird auch in Ihrem Fall funktionieren

Vielen Dank

Yasir Shabbir Choudhary
quelle
Warum denkst du, würde das funktionieren? Ich habe mir das Skript angesehen und es scheint die Methoden im Date-Objekt nicht zu überschreiben. Ich war hier: polyfill.io/v3/url-builder und es scheint nichts über das Parsen von Daten zu geben.
Costa
0

Wie bereits erwähnt, funktionierte die Verwendung von Date.parse () in Safari bei @nizantz nicht. Nach einigen Recherchen habe ich festgestellt, dass die lastDateModified-Eigenschaft für das File-Objekt veraltet ist und von Safari nicht mehr unterstützt wird. Die Verwendung der lastModified-Eigenschaft des File-Objekts hat meine Probleme behoben. Sicher nicht mögen, wenn schlechte Informationen online gefunden werden.

Vielen Dank an alle, die zu diesem Beitrag beigetragen haben, der mir dabei geholfen hat, den Weg zu gehen, den ich brauchte, um mehr über mein Problem zu erfahren. Wäre diese Information nicht gewesen, hätte ich wahrscheinlich nie mein Grundproblem herausgefunden. Vielleicht hilft das jemand anderem in meiner ähnlichen Situation.

S. Costello
quelle
0

Ich habe auch das gleiche Problem in Safari Browser

var date = new Date("2011-02-07");
console.log(date) // IE you get ‘NaN’ returned and in Safari you get ‘Invalid Date’

Hier die Lösung:

var d = new Date(2011, 01, 07); // yyyy, mm-1, dd  
var d = new Date(2011, 01, 07, 11, 05, 00); // yyyy, mm-1, dd, hh, mm, ss  
var d = new Date("02/07/2011"); // "mm/dd/yyyy"  
var d = new Date("02/07/2011 11:05:00"); // "mm/dd/yyyy hh:mm:ss"  
var d = new Date(1297076700000); // milliseconds  
var d = new Date("Mon Feb 07 2011 11:05:00 GMT"); // ""Day Mon dd yyyy hh:mm:ss GMT/UTC 
venkatskpi
quelle
0

Dies ist nicht die beste Lösung, obwohl ich einfach den Fehler abfange und das aktuelle Datum zurücksende. Ich persönlich habe das Gefühl, Safari-Probleme nicht zu lösen. Wenn Benutzer einen nicht standardkonformen Browser verwenden möchten, müssen sie mit Macken leben.

function safeDate(dateString = "") {
  let date = new Date();
  try {
    if (Date.parse(dateString)) {
      date = new Date(Date.parse(dateString))
    }
  } catch (error) {
    // do nothing.
  }
  return date;
}

Ich würde vorschlagen, dass Ihr Backend ISO-Daten sendet.

Andrew McLagan
quelle
Wenn Sie meinen, dass Benutzer den Browser verwenden müssen , für den Sie Code geschrieben haben, sieht das im Allgemeinen schlecht aus. Dies hängt auch von unseren Anwendungsfällen und unserer Zielgruppe ab. Wenn eine Website für den Konsum auf dem Massenmarkt erstellt wird, unterstützen wir zumindest auch IE10. Ich bin sicher, dass jemand in MS dasselbe dachte, als er für den Internet Explorer entwarf / codierte. Wir alle wissen, wie jetzt darüber gesprochen wird.
Shrinath
-1

Verwenden Sie das Format 'MM / TT / JJJJ'. Zum Beispiel: - neues Datum ('02 / 28/2015 '). Es funktioniert gut in allen Browsern.

Ravi S.
quelle