wake-up-neo.net

Die Datumsanalyse in Javascript unterscheidet sich zwischen Safari und Chrome

Ich habe den folgenden Code

var c = new Date(Date.parse("2011-06-21T14:27:28.593Z"));
console.log(c);

In Chrome wird das Datum korrekt auf der Konsole ausgegeben. In Safari schlägt __.it fehl. Wer ist richtig und was ist am besten, um dies zu tun?

51
bradgonesurfing

Sie können Date.parse nicht wirklich verwenden. Ich schlage vor, Sie verwenden: new Date (year, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] )

Um den String zu teilen, können Sie es versuchen

var s = '2011-06-21T14:27:28.593Z';
var a = s.split(/[^0-9]/);
//for (i=0;i<a.length;i++) { alert(a[i]); }
var d=new Date (a[0],a[1]-1,a[2],a[3],a[4],a[5] );
alert(s+ " "+d);
90
Erik

Ich neige dazu, Date.parse zu vermeiden, wie in den anderen Antworten für diese Frage. Es scheint keine tragbare Methode zu sein, um zuverlässig mit Daten umzugehen.

Stattdessen habe ich etwas wie die Funktion unten verwendet. Dies verwendet jQuery, um das String-Array einem Zahlenarray zuzuordnen, aber das Entfernen/Ändern ist ziemlich einfach. Ich füge auch das hinzu, was ich für vernünftige Vorgaben halte, damit Sie 2007-01-09 und 2007-01-09T09:42:00 mit derselben Funktion analysieren können.

function dateFromString(str) {
  var a = $.map(str.split(/[^0-9]/), function(s) { return parseInt(s, 10) });
  return new Date(a[0], a[1]-1 || 0, a[2] || 1, a[3] || 0, a[4] || 0, a[5] || 0, a[6] || 0);
}
14
jabley

Ich habe es in mehreren Browsern geprüft und ja, Safari gibt invalid date zurück. Übrigens müssen Sie hier nicht Date.parse verwenden, nur new Date([datestring]) wird auch funktionieren. Safari erfordert offensichtlich mehr Formatierung des von Ihnen gelieferten Datenstrings. Wenn Sie '-' durch '/' ersetzen, entfernen Sie das T und alles nach dem Punkt (.593Z), damit erhalten Sie ein gültiges Datum. Dieser Code wurde getestet und funktioniert in Safari

var datestr = '2011-06-21T14:27:28.593Z'.split(/[-T.]/);
var safdat = new Date( datestr.slice(0,3).join('/')+' '+datestr[3] );

Oder mit String.replace(...):

new Date("2016-02-17T00:05:01+0000".replace(/-/g,'/').replace('T',' ').replace(/(\..*|\+.*/,""))
11
KooiInc

Mein ähnliches Problem wurde dadurch verursacht, dass Safari nicht wusste, wie er die Zeitzone in einem RFC 822-Zeitzonenformat lesen soll. Ich konnte dies mithilfe des ISO 8601-Formats beheben. Wenn Sie die Kontrolle über das Datumsformat haben, habe ich dies mit Javas SimpleDateFormat "yyyy-MM-dd'T'HH: mm: ss.sssXXX" erstellt, das für mich dh produziert. "2018-02-06T20: 00: 00.000 + 04: 00". Aus irgendeinem Grund kann Safari "2018-02-06T20: 00: 00.000 + 0400" nicht lesen. Beachten Sie das Fehlen eines Doppelpunkts im Zeitzonenformat.

// Works
var c = new Date("2018-02-06T20:00:00.000+04:00"));
console.log(c);

// Doesn't work
var c = new Date("2018-02-06T20:00:00.000+0400"));
console.log(c);
8
Olmstov

Am Ende benutzte ich eine Bibliothek, um dies auszugleichen:

http://zetafleet.com/blog/javascript-dateparse-for-iso-8601

Sobald diese Bibliothek aufgenommen wurde, erstellen Sie mit dem folgenden Code das neue Datum:

var date = new Date(Date.parse(datestring));

In unserem Projekt wurden keine Millisekunden-Spezifizierer verwendet, aber ich glaube nicht, dass dies ein Problem für Sie verursachen wird.

5
AaronSieb

Ich verwende die folgende Funktion zum Parsen von Datumsangaben mit Zeitzone. Funktioniert sowohl für Chrome als auch für Safari:

function parseDate(date) {
  const parsed = Date.parse(date);
  if (!isNaN(parsed)) {
    return parsed;
  }

  return Date.parse(date.replace(/-/g, '/').replace(/[a-z]+/gi, ' '));
}

console.log(parseDate('2017-02-09T13:22:18+0300'));  // 1486635738000 time in ms

3
Londeren

ich habe ein konvertiertes Datum ausprobiert, indem ich es gekürzt und analysiert habe. 

var dateString = "2016-01-22T08:18:10.000+0000";
 var hours = parseInt(dateString.split("+")[1].substr("0","2"));
 var mins = parseInt(dateString.split("+")[1].substr("2"));
 var date = new Date(dateString.split("+")[0]);
 date.setHours(date.getHours()-hours);
 date.setMinutes(date.getMinutes()-mins);
1
Anky

Hier ist ein robusterer ISO 8601-Parser als der, den andere gepostet haben. Das Wochenformat wird nicht behandelt, es sollte jedoch alle anderen gültigen ISO 8601-Daten in allen Browsern konsistent behandeln.

function newDate(value) {
  var field = value.match(/^([+-]?\d{4}(?!\d\d\b))(?:-?(?:(0[1-9]|1[0-2])(?:-?([12]\d|0[1-9]|3[01]))?)(?:[T\s](?:(?:([01]\d|2[0-3])(?::?([0-5]\d))?|24\:?00)([.,]\d+(?!:))?)?(?::?([0-5]\d)(?:[.,](\d+))?)?([zZ]|([+-](?:[01]\d|2[0-3])):?([0-5]\d)?)?)?)?$/) || [];
  var result = new Date(field[1], field[2] - 1 | 0, field[3] || 1, field[4] | 0, field[5] | 0, field[7] | 0, field[8] | 0)
  if (field[9]) {
    result.setUTCMinutes(result.getUTCMinutes() - result.getTimezoneOffset() - ((field[10] * 60 + +field[11]) || 0));
  }
  return result;
}

console.log(newDate('2011-06-21T14:27:28.593Z'));
console.log(newDate('1970-12-31T06:00Z'));
console.log(newDate('1970-12-31T06:00-1200'));

0
Adam Leggett

Anstatt 'Z' am Ende der Datumszeichenfolge zu verwenden, können Sie den Zeitzonenoffset des lokalen Clients hinzufügen. Wahrscheinlich möchten Sie eine Methode, um dies für Sie zu generieren:

let timezoneOffset = () => {
    let date = new Date(),
        timezoneOffset = date.getTimezoneOffset(),
        hours = ('00' + Math.floor(Math.abs(timezoneOffset/60))).slice(-2),
        minutes = ('00' + Math.abs(timezoneOffset%60)).slice(-2),
        string = (timezoneOffset >= 0 ? '-' : '+') + hours + ':' + minutes;
    return string;
}

Das Endergebnis wäre also:

var c = new Date("2011-06-21T14:27:28.593" + timezoneOffset());

0
adjwilli