web-dev-qa-db-fra.com

La date Javascript n'est pas valide sur iOS

Je travaille sur une application iOS basée sur Phonegap, ce qui est déjà fait pour Android. Les lignes suivantes fonctionnent correctement pour Android mais pas pour iOS. Pourquoi?

var d = new Date("2015-12-31 00:00:00");
console.log(d.getDate() + '. ' + d.getMonth() + ' ' + d.getFullYear();

Résultat pour Android:

31.11 2015

Résultat sur iOS:

NaN. NaN NaN

D'où vient la différence?

39
Philipp Siegfried

Votre chaîne de date n'est pas dans un format spécifié pour fonctionner avec new Date. Le seul format de la spécification est ne version simplifiée de l'ISO-8601 , mais qui n'a été ajouté que dans ES5 et le support peut donc être tactile. Votre chaîne n'est pas dans ce format, mais elle est vraiment proche.

Si vous changez l'espace en T, vous serez en spécification:

var dateString = "2015-12-31 00:00:00";
var d = new Date(dateString.replace(' ', 'T'));

(Je suppose que vous n'utilisez pas réellement un littéral de chaîne, d'où l'appel replace.)

Notez qu'il y avait une erreur dans la spécification ES5 qui a été corrigée dans ES2015 (ES6): que se passe-t-il lorsqu'il n'y a pas d'indicateur de fuseau horaire sur la chaîne. Dans l'ISO-8601, aucun indicateur ne signifie "heure locale", mais la spécification ES5 indique qu'elle est par défaut Z (UTC - vaguement, GMT). Ils l'ont corrigé dans la spécification ES2015, mais malheureusement, certains moteurs JavaScript ont suivi la spécification ES5 et d'autres ont suivi ISO-8601 (et maintenant ES2015). Mais attendez, cela empire: l'utilisation de l'heure locale pour des chaînes qui ne contiennent que des dates s'est avérée problématique pour le code existant (et TC39 vraiment, vraiment essaie de ne pas casser le code existant), donc dans ES2016, ils ont dû changez-le à nouveau pour dire: s'il s'agit d'une chaîne de date uniquement, interprétez-la comme UTC, mais s'il s'agit d'une chaîne de date/heure, interprétez-la comme heure locale.

Donc, avec tous ces divertissements et jeux, pour une prise en charge multi-navigateur solide, vous devez inclure un indicateur de fuseau horaire, car sinon vous ne savez pas s'il sera interprété comme UTC ou heure locale. Vous êtes autorisé à utiliser Z pour GMT ou +/- suivi par HH:MM pour donner un décalage. (Les abréviations comme CST ne sont pas autorisées, car il n'y a pas de norme pour elles.)

S'ils ne le prennent pas encore en charge, il existe un support quasi universel pour YYYY/MM/DD HH:MM:SS (interprété comme heure locale), même si il n'est pas spécifié . Donc:

var dateString = "2015-12-31 00:00:00";
var d = new Date(dateString.replace(/-/g, '/'));
96
T.J. Crowder

Je ne peux pas te dire pourquoi. Peut-être parce qu'iOS ne prend pas en charge la fonction Javascript Date ainsi que Android, ou prend en charge un format différent?

Mais je peux vous donner une solution:

var s = "2015-12-31 00:00:00".split(" ")[0].split("-"),
    d = new Date( s[0], s[1], s[2], 0, 0, 0 );

console.log(d);

var s = "2015-12-31 00:00:00".replace(/[ :]/g, "-").split("-"),
    d = new Date( s[0], s[1], s[2], s[3], s[4], s[5] );

console.log(d);
6
andlrc

Une solution qui fonctionne pour les deux IOS et Android, et éviter la manipulation de chaînes lorsqu'elle n'est pas requise est

let fullDate = "1991-03-29 00:00:00";
let date = new Date(fullDate);

// In case its IOS, parse the fulldate parts and re-create the date object.
if(Number.isNaN(date.getMonth())) {
  let arr = fullDate.split(/[- :]/);
  date = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]);
}
2
Eyal c