Safari JS не может разобрать формат даты YYYY-MM-DD?
В проекте, над которым я работаю, мне нужно проверить дату, введенную в <input type="date">
В Safari 4/5 (на Mac OSX) Javascript не выполняет синтаксический анализ дат формата YYYY-MM-DD
, возвращая NaN
вместо ожидаемой метки времени.
Я использую следующий метод для проверки поля непосредственно перед отправкой формы:
//value = '2010-06-21'
var stamp = Date.parse(value);
if (isNaN(stamp)) {
//notify user
} else {
value = new Date(stamp).format_mysql();
}
Где format_mysql()
- это прототипная функция, которая форматирует дату (правильно) в формате MySQL Date-Time (YYYY-MM-DD).
Замена -
на /
(YYYY/MM/DD) дает "правильную" временную метку.
Я должен заметить, что поле должно принимать любой формат даты, а не только YYYY-MM-DD, и что, хотя я бы хотел, я не могу использовать библиотеки типа Date.js
Как я могу это исправить или есть лучший способ проанализировать/подтвердить дату?
Ответы
Ответ 1
Поведение метода Date.parse
зависит от реализации, в ECMAScript 5 этот метод может анализировать даты в формате ISO8601, но я бы рекомендовал вы должны вручную выполнить парсинг.
Некоторое время назад я создал простую функцию, которая может обрабатывать аргумент спецификатора формата:
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');
Также вы можете обнаружить поведение ECMAScript 5 для анализа дат в формате ISO, вы можете проверить, доступен ли Date.prototype.toISOString
, например:
if (typeof Date.prototype.toISOString == "function") {
// ES5 ISO date parsing available
}
Ответ 2
Как правило, формат DD-MM-YYYY не поддерживается в сафари.
value = 2010/06/21;//должен работать.
(или)
value = new Date ('2010-06-21'.replace(/-/g, "/" ));
Ответ 3
поле должно принимать любой формат даты
Вы не имеете в виду то, что вы думаете о себе.
- Трудно надежно различать M/D/Y (US) и D/M/Y (Великобритания). D.M.Y более распространен в Великобритании, но отнюдь не универсален.
- Удачи с датами до 1600 года - григорианский (солнечный) календарь был введен в 1582 году и был только (в основном универсальным), принятым в 20 веке (Wikipedia дает 1929). 30 февраля была действительная дата Швеции.
- OS X дает вам выбор из 13 (!) календарей, хотя по умолчанию используется григорианский.
Вместо этого я рекомендую использовать виджет календаря. Я думаю, что у JQuery есть один, но ICBW.
Ответ 4
Вы можете получить однозначную дату с ввода,
но вам все равно нужно его проверить, поэтому пользователь не дает вам 31 апреля.
<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>
ярлык для document.getElementsByName
function byName (s, n) { n = n || 0; return 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();
}
вы можете задать поля, чтобы отразить текущую дату загрузки
onload= function(){
var now= new Date();
byName('inputyear').value= now.getFullYear();
byName('monthselect').selectedIndex= now.getMonth();
byName('inputdate').value= now.getDate();
}