web-dev-qa-db-fra.com

Safari JS ne peut pas analyser le format de date AAAA-MM-JJ?

Dans un projet sur lequel je travaille, je dois valider une date entrée dans un <input type="date">

Avec Safari 4/5 (sur Mac OSX), Javascript ne parvient pas à analyser les dates du format YYYY-MM-DD, Renvoyant NaN au lieu de l'horodatage Epoch attendu.

J'utilise la technique suivante pour valider le champ juste avant l'envoi du formulaire:

//value = '2010-06-21'
var stamp = Date.parse(value);
if (isNaN(stamp)) {
    //notify user
} else {
    value = new Date(stamp).format_mysql();
}

format_mysql() est une fonction prototype qui formate la date (correctement) au format date-heure MySQL (AAAA-MM-JJ).

Le remplacement des - Par des / (AAAA/MM/JJ) produit un horodatage "correct".

Je dois noter que le champ doit accepter n'importe quel format de date, pas seulement AAAA-MM-JJ, et que même si je le souhaite, je ne peux pas utiliser de bibliothèques comme Date.js

Comment puis-je résoudre ce problème, ou existe-t-il une meilleure façon d'analyser/valider une date?

37
Austin Hyde

Le comportement de Date.parse dépend de l'implémentation, sur ECMAScript 5, cette méthode peut analyser les dates formatées ISO8601, mais je vous recommande de faire l'analyse manuelle.

Il y a quelque temps, j'ai créé une fonction simple, qui peut gérer un argument spécificateur de format:

function parseDate(input, format) {
  format = format || 'yyyy-mm-dd'; // default format
  var parts = input.match(/(\d+)/g), 
      i = 0, fmt = {};
  // extract date-part indexes from the format
  format.replace(/(yyyy|dd|mm)/g, function(part) { fmt[part] = i++; });

  return new Date(parts[fmt['yyyy']], parts[fmt['mm']]-1, parts[fmt['dd']]);
}

parseDate('06.21.2010', 'mm.dd.yyyy');
parseDate('21.06.2010', 'dd.mm.yyyy');
parseDate('2010/06/21', 'yyyy/mm/dd');
parseDate('2010-06-21');

Vous pouvez également détecter le comportement ECMAScript 5 pour analyser les dates au format ISO, vous pouvez vérifier si le Date.prototype.toISOString est disponible, par exemple:

if (typeof Date.prototype.toISOString == "function") {
  // ES5 ISO date parsing available
}
57
CMS

Généralement, le format DD-MM-YYYY n'est pas pris en charge dans Safari.

valeur = 2010/06/21; //devrait marcher.

(ou)

value = new Date ('2010-06-21'.replace (/ -/g, "/"));

12
Vishnu Vardhana

le champ doit accepter n'importe quel format de date

Vous ne voulez pas dire ce que vous pensez vouloir dire.

  • Il est difficile de faire une distinction fiable entre M/D/Y (États-Unis) et D/M/Y (Royaume-Uni). D.M.Y est plus courant au Royaume-Uni, mais en aucun cas universel.
  • Bonne chance avec des dates antérieures à 1600 environ - le calendrier grégorien (solaire) a été introduit en 1582 et n'a été adopté (pour la plupart universellement) qu'au XXe siècle (Wikipedia donne 1929). Le 30 février était une date valable pour la Suède.
  • OS X vous offre un choix de 13 (!) Calendriers, bien que la valeur par défaut soit grégorienne.

Au lieu de cela, je recommande d'utiliser un widget de calendrier. Je pense que JQuery en a un, mais ICBW.

3
tc.

Vous pouvez obtenir une date non ambiguë en entrée, mais vous devez toujours la vérifier, de sorte qu'un utilisateur ne vous donne pas le 31 avril.

<fieldset id= "localdate"> 
<select id= "monthselect" size= "1"> 
<option selected= "selected"> January</option> 
<option> February</option> 
<option> March</option> 
<option> April</option> 
<option> May</option> 
<option> June</option> 
<option> July</option> 
<option> August</option> 
<option> September</option> 
<option> October</option> 
<option> November</option> 
<option> December</option> 
</select> 
<label> Date: <input name= "inputdate" size= "2" value= "1"> </label> 
<label> Year: <input name= "inputyear" size= "4" value= "2010"> </label> 
</fieldset> 

raccourci pour document.getElementsByName

fonction byName (s, n) {n = n || 0; renvoyer document.getElementsByName (s) [n]; }

function getDateInput(){
    var day, y= parseInt(byName('inputyear').value),
    m= byName('monthselect').selectedIndex,
    d= parseInt(byName('inputdate').value);

    if(!y || y<1000 || y> 3000) throw 'Bad Year '+y;
    if((!d || d<1 || d> 32) throw 'Bad Date '+d;
    day= new Date(y,m,d);
    if(day.getDate()!= d) throw 'Bad Date '+d;
    value= day.format_mysql();
}

vous pouvez prédéfinir les champs pour refléter la date de chargement actuelle

onload= function(){
    var now= new Date();
    byName('inputyear').value= now.getFullYear();
    byName('monthselect').selectedIndex= now.getMonth();
    byName('inputdate').value= now.getDate();
}
1
kennebec