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();
}
Où 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?
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
}
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, "/"));
le champ doit accepter n'importe quel format de date
Vous ne voulez pas dire ce que vous pensez vouloir dire.
Au lieu de cela, je recommande d'utiliser un widget de calendrier. Je pense que JQuery en a un, mais ICBW.
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();
}