Date non valide dans le safari


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

chrome, ff n'a pas de problèmes avec cela, mais safari crie "date invalide". Pourquoi ?

edit: ok, selon les commentaires ci-dessous, j'ai utilisé l'analyse de chaîne et j'ai essayé ceci:

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

edit 22 mars 2018 : On dirait que les gens débarquent encore ici - Aujourd'hui, j'utiliserais momentou j'en aurais date-fnsfini avec. Date-fns est également très indolore et léger.


Juste pour d'autres qui regardent le même problème: j'ai fini par utiliser DateJS, qui a résolu mon problème dans son ensemble .. Voir la réponse acceptée pour plus de détails.
Shrinath

2
utilisez moment.js pour analyser l'horodatage. Surtout lorsqu'il s'agit de web multiplateforme
Ming Yuen

1
C'est une vieille question. Depuis ECMAScript 2015, les chaînes de date ISO 8601 uniquement sont analysées en UTC. Cependant, il peut y avoir encore des navigateurs plus anciens qui ne l'analyseront pas du tout ou le traiteront comme local.
RobG

Réponses:


167

Le modèle yyyy-MM-ddn'est pas un format officiellement pris en charge pour le Dateconstructeur. Firefox semble le soutenir, mais ne comptez pas sur d'autres navigateurs pour faire de même.

Voici quelques chaînes prises en charge:

  • MM-jj-aaaa
  • aaaa / MM / jj
  • MM / jj / aaaa
  • MMMM jj, aaaa
  • MMM jj, aaaa

DateJS semble être une bonne bibliothèque pour analyser les formats de date non standard.

Edit : vient de vérifier la norme ECMA-262 . Citant l'article 15.9.1.15:

Format de chaîne de date et d'heure

ECMAScript définit un format d'échange de chaînes pour les dates-heures basé sur une simplification du format étendu ISO 8601. Le format est le suivant: AAAA-MM-JJTHH: mm: ss.sssZ Où les champs sont les suivants:

  • YYYY correspond aux chiffres décimaux de l'année dans le calendrier grégorien.
  • "-" (trait d'union) apparaît littéralement deux fois dans la chaîne.
  • MM est le mois de l'année du 01 (janvier) au 12 (décembre).
  • JJ est le jour du mois du 01 au 31.
  • "T" apparaît littéralement dans la chaîne, pour indiquer le début de l'élément temporel.
  • HH est le nombre d'heures complètes écoulées depuis minuit sous forme de deux chiffres décimaux.
  • ":" (deux-points) apparaît littéralement deux fois dans la chaîne.
  • mm est le nombre de minutes complètes depuis le début de l'heure sous forme de deux chiffres décimaux.
  • ss est le nombre de secondes complètes depuis le début de la minute sous forme de deux chiffres décimaux.
  • "." (point) apparaît littéralement dans la chaîne.
  • sss est le nombre de millisecondes complètes depuis le début de la seconde sous forme de trois chiffres décimaux. Les deux "." et le champ millisecondes peut être omis.
  • Z est le décalage du fuseau horaire spécifié comme "Z" (pour UTC) ou "+" ou "-" suivi d'une expression d'heure hh: mm

Ce format inclut les formulaires à date uniquement:

  • AAAA
  • AAAA-MM
  • AAAA-MM-JJ

Il comprend également des formulaires de temps uniquement avec un décalage de fuseau horaire facultatif ajouté:

  • THH: millimètre
  • THH: mm: ss
  • THH: mm: ss.sss

Sont également inclus les «dates-heures» qui peuvent être n'importe quelle combinaison des éléments ci-dessus.

Donc, il semble que AAAA-MM-JJ soit inclus dans la norme, mais pour une raison quelconque, Safari ne le prend pas en charge.

Mise à jour : après avoir consulté la documentation de datejs , en l'utilisant, votre problème devrait être résolu en utilisant un code comme celui-ci:

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");

4
Le format ISO8601 est utilisé dans la 5ème édition de la norme ECMAScript, et n'est pas encore largement pris en charge, le moyen le plus sûr d'aller à l'OMI, analyser la date manuellement :(
CMS

1
C'était mec très utile .. Merci .. :) Enfin fini par utiliser datejs pour le formatage.
Shrinath

pour ceux dans le futur, veuillez noter que si datejs est fantastique à bien des égards, il ne résout pas tous les problèmes de formatage de la date, en particulier avec safari. c'est un PITA mais il est préférable de le faire manuellement si vous avez encore des problèmes.
totalementNotLizards

@darioo J'ai donc essayé votre réponse comme suit: "var start = Date.parseExact (horodatage," AAAA-JJ-MM HH: mm: SS ");" l'horodatage est "2016-01-28 00:00:00". Cependant maintenant j'obtiens l'erreur, que "Date.parseExact n'est pas une fonction". Savez-vous ce qui se passe ici?
threxx

5
Mon problème similaire a été causé par Safari ne sachant 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 l'ai obtenu avec "aaaa-MM-jj'T'HH: mm: ss.sssXXX" qui crée ie. "2018-02-06T20: 00: 00.000 + 00: 00". Pour une raison quelconque, Safari ne peut pas lire "2018-02-06T20: 00: 00.000 + 0000", notez l'absence de deux points dans le format du fuseau horaire.
Olmstov

224

Pour moi, implémenter une nouvelle bibliothèque simplement parce que Safari ne peut pas le faire correctement, c'est trop et une regex est exagérée. Voici le oneliner :

console.log (new Date('2011-04-12'.replace(/-/g, "/")));

Si obtenir une barre oblique n'était que mon problème, alors j'aurais «accepté» votre réponse (même si c'était mon seul objectif lorsque j'ai posé cette question). Maintenant que j'ai trouvé dateJS, j'ai implémenté le format MMM DD, YYYY pour une expérience plus conviviale !!!
Shrinath le

13
Cette aide d'une ligne était parfaite pour mon besoin! Merci!
Cyril N.

4
C'était assez simple pour moi aussi. Je ne peux pas croire que Safari n'aime pas le - mais le même format avec un \\ fonctionne. Merci @Elzo et merci Shrinath d'avoir posé la question
Pete

1
Je pense que c'est la meilleure réponse que j'ai tendance à oublier / - / g au lieu de '-'
Jacek Pietal

12
applaudissements pour ne pas avoir implémenté de bibliothèque.
lharby

56

J'étais confronté à un problème similaire. Date.Parse("DATESTRING")fonctionnait sur Chrome (Version 59.0.3071.115) mais pas sur Safari (Version 10.1.1 (11603.2.5))

Safari:

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

Chrome:

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

La solution qui a fonctionné pour moi était de remplacer l'espace dans la chaîne dateString par "T". (Exemple: dateString.replace(/ /g,"T"))

Safari:

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

Chrome:

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

Notez que la réponse du navigateur Safari est inférieure de 8 heures (28800000ms) à la réponse affichée dans le navigateur Chrome car Safari a renvoyé la réponse dans la TZ locale (qui est à 8 heures derrière UTC)

Pour obtenir les deux heures dans la même TZ

Safari:

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

Chrome:

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

Ou si vous ne voulez pas que les deux dates soient les mêmes dans Safari et Chrome, vous pouvez utiliser le new Date(year, month, date, hours, minutes, seconds, milliseconds)constructeur. Analyser la date de chaîne dans un tableau de ses composants afin d'utiliser ces composants dans le constructeur. @nizantz ce serait formidable si vous pensez qu'un tel exemple pourrait être ajouté à votre réponse.
h3dkandi

Pas particulièrement utile car vous obtenez la date en UTC et non en heure locale.
Jonas Äppelgran

1
Cette dateString.replace(/ /g,"T")ligne de code magique a fonctionné pour moi. :)
Mazdak Shojaie

remplacer (/ - / g, '/')
Jack Hu

11

J'utilise le moment pour résoudre le problème. Par exemple

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

10

Pour qu'une solution fonctionne sur la plupart des navigateurs, vous devez créer votre objet date avec ce format

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

par exemple:

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

fonctionne très bien avec IE, FF, Chrome et Safari. Même les anciennes versions.

Centre de développement IE: objet de date (JavaScript)

Mozilla Dev Network: Date


6

convertir la chaîne en date à partir de (vous devez connaître le fuseau horaire du serveur)

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

où +08: 00 = timeZone du serveur


Cela ne prend pas en compte l'heure d'été. Le décalage TZ peut fluctuer et dépend de la date elle-même (et de l'heure).
costa

5

J'ai eu le même problème.Ensuite, j'ai utilisé moment.Js .Problem a disparu.

Lors de la création d'un moment à partir d'une chaîne, nous vérifions d'abord si la chaîne correspond aux formats ISO 8601 connus, puis revenons à la nouvelle Date (chaîne) si un format connu n'est pas trouvé.

Avertissement: la prise en charge par le navigateur de l'analyse des chaînes est incohérente. Comme il n'y a pas de spécification sur les formats à prendre en charge, ce qui fonctionne dans certains navigateurs ne fonctionnera pas dans d'autres navigateurs.

Pour des résultats cohérents analysant autre chose que les chaînes ISO 8601, vous devez utiliser String + Format.

par exemple

var date= moment(String);

3

Bien que vous puissiez espérer que les navigateurs prendront en charge ISO 8601 (ou des sous-ensembles de date uniquement), ce n'est pas le cas. Tous les navigateurs que je connais (au moins dans les régions américaines / anglaises que j'utilise) sont capables d'analyser l'horrible MM/DD/YYYYformat américain .

Si vous avez déjà les parties de la date, vous pouvez à la place essayer d'utiliser Date.UTC () . Si vous ne le faites pas, mais que vous devez utiliser le YYYY-MM-DDformat, je suggère d'utiliser une expression régulière pour analyser les éléments que vous connaissez, puis les transmettre Date.UTC().


Je suppose que l'analyse des chaînes est la voie à suivre :(
Shrinath

1

Utilisez le format ci-dessous, cela fonctionnerait sur tous les navigateurs

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); 

// Votre sortie ressemblerait à ceci "Wed Mar 23 2016 00:00:00 GMT + 0530 (IST)"

// Notez que ce serait dans le fuseau horaire actuel dans ce cas indiqué par IST, pour convertir en fuseau horaire UTC, vous pouvez inclure

alert(dateObj.toUTCSting);

// Votre sortie maintenant aimerait ceci "Tue, 22 Mar 2016 18:30:00 GMT"

Notez que maintenant la dateObj affiche l'heure au format GMT, notez également que la date et l'heure ont été modifiées en conséquence.

La fonction "toUTCSting" récupère l'heure correspondante au méridien de Greenwich. Il accomplit cela en établissant le décalage horaire entre votre fuseau horaire actuel et le fuseau horaire du méridien de Greenwich.

Dans le cas ci-dessus, le temps avant la conversion était de 00:00 heures et minutes le 23 mars de l'année 2016. Et après la conversion de GMT + 0530 (IST) heures en GMT (il soustrait essentiellement 5.30 heures de l'horodatage donné dans ce cas), l'heure correspond à 18h30 le 22 mars de l'année 2016 (exactement 5h30 de retard sur la première fois).

En outre, pour convertir n'importe quel objet de date en horodatage, vous pouvez utiliser

alert(dateObj.getTime());

// la sortie ressemblerait à ce "1458671400000"

Cela vous donnerait l'horodatage unique de l'heure



1

La meilleure façon de le faire est d'utiliser le format suivant:

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

Ceci est pris en charge dans tous les navigateurs et ne vous posera aucun problème. Veuillez noter que les mois sont écrits de 0 à 11.


Fonctionne bien sur Safari et Chrome, mais a toujours des problèmes sur Firefox. Safari: var date = new Date (2018,06,08,19,17) Sun Jul 08 2018 19:17:00 GMT + 0800 (+08) Chrome: var date = new Date (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

Le même problème rencontré dans Safari et il a été résolu en l'insérant dans la page Web

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

J'espère que cela fonctionnera aussi votre cas

Merci


Pourquoi pensez-vous que cela fonctionnerait? J'ai regardé le script et il ne semble pas remplacer les méthodes de l'objet Date. Je suis allé ici: polyfill.io/v3/url-builder et il semble n'y avoir rien sur l'analyse des dates.
costa

0

Comme @nizantz l'a mentionné précédemment, utiliser Date.parse () ne fonctionnait pas pour moi dans Safari. Après quelques recherches, j'ai appris que la propriété lastDateModified de l'objet File était obsolète et qu'elle n'était plus prise en charge par Safari. L'utilisation de la propriété lastModified de l'objet File a résolu mes problèmes. Bien sûr, je n'aime pas quand de mauvaises informations sont trouvées en ligne.

Merci à tous ceux qui ont contribué à cet article qui m'a aidé à suivre le chemin dont j'avais besoin pour en savoir plus sur mon problème. Sans cette information, je n'aurais probablement jamais compris mon problème racine. Peut-être que cela aidera quelqu'un d'autre dans ma situation similaire.


0

Je suis également confronté au même problème dans le navigateur Safari

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

Voici la solution:

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 

0

Ce n'est pas la meilleure solution, même si j'attrape simplement l'erreur et renvoie la date actuelle. J'ai personnellement l'impression de ne pas résoudre les problèmes de Safari, si les utilisateurs veulent utiliser un navigateur sh * t non conforme aux normes - ils doivent vivre avec des bizarreries.

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

Je suggère que votre backend envoie les dates ISO.


Sauf votre respect, lorsque vous voulez dire que les utilisateurs doivent utiliser le navigateur pour lequel vous avez écrit du code, cela semble mauvais dans un sens général. Cela dépend également de nos cas d'utilisation et de notre public cible - si un site Web est en cours de construction pour la consommation du marché de masse, nous soutiendrions également IE10, à tout le moins. Je suis sûr que quelqu'un dans MS pensait la même chose quand ils ont conçu / codé pour Internet Explorer. Nous savons tous comment on en parle maintenant.
Shrinath

-1

utilisez le format «mm / jj / aaaa». Par exemple: - nouvelle date ('02/28/2015'). Cela fonctionne bien dans tous les navigateurs.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.