web-dev-qa-db-fra.com

L'analyse de la date en javascript est différente entre safari et chrome

J'ai le code suivant

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

Sur Chrome, il affiche correctement la date sur la console. Dans Safariit échoue. Qui est correct et, plus important encore, quel est le meilleur moyen.

51
bradgonesurfing

Vous ne pouvez pas vraiment utiliser Date.parse. Je vous suggère d'utiliser: new Date (year, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] )

Pour séparer la chaîne, vous pouvez essayer

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

J'ai tendance à éviter Date.parse, comme indiqué dans les autres réponses à cette question. Cela ne semble pas être un moyen portable de traiter de manière fiable les dates.

Au lieu de cela, j'ai utilisé quelque chose comme la fonction ci-dessous. Cela utilise jQuery pour mapper le tableau de chaînes en un tableau de nombres, mais c'est une dépendance assez facile à supprimer/modifier. J'inclus également ce que je considère comme des valeurs par défaut raisonnables, pour vous permettre d'analyser 2007-01-09 et 2007-01-09T09:42:00 en utilisant la même fonction.

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

Je l'ai vérifié dans plusieurs navigateurs, et oui, safari renvoie invalid date. En passant, vous n'avez pas à utiliser Date.parse ici, seul new Date([datestring]) fonctionnera aussi. Safari nécessite évidemment plus de formatage de la chaîne de données fournie. Si vous remplacez '-' par '/', supprimez le T et tout ce qui suit le point (.593Z), cela vous donnera une date valide. Ce code est testé et fonctionne dans Safari

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

Ou en utilisant String.replace(...):

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

Mon problème similaire était dû au fait que Safari ne savait pas comment lire le fuseau horaire dans un format de fuseau horaire RFC 822. J'ai pu résoudre ce problème en utilisant le format ISO 8601. Si vous avez le contrôle du format de date, je travaille avec le SimpleDateFormat de Java "aaaa-MM-jj'T'HH: mm: ss.sssXXX" qui produit pour moi, par exemple. "2018-02-06T20: 00: 00.000 + 04: 00". Pour une raison quelconque, Safari ne peut pas lire "2018-02-06T20: 00: 00.000 + 0400", remarquez l'absence de deux points dans le format du fuseau horaire.

// 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

J'ai fini par utiliser une bibliothèque pour compenser ceci:

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

Une fois cette bibliothèque incluse, vous utilisez ce code pour créer la nouvelle date:

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

Notre projet n'utilisait pas de spécificateurs millisecondes, mais je ne crois pas que cela vous posera problème.

5
AaronSieb

J'utilise la fonction suivante pour analyser les dates avec le fuseau horaire. Fonctionne très bien à la fois Chrome et 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

j'ai essayé de convertir la date en le tronquant et en l'analysant comme ça, il fonctionne parfaitement avec Safari et iOS 

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

Voici un analyseur ISO 8601 plus robuste que ce que d’autres ont publié. Il ne gère pas le format hebdomadaire, mais il doit gérer toutes les autres dates ISO 8601 valides de manière cohérente sur tous les navigateurs.

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