Я хотел бы сказать разницу между допустимыми и недопустимыми объектами даты в JS, но не мог понять, как:
var d = new Date("foo");
console.log(d.toString()); // shows 'Invalid Date'
console.log(typeof d); // shows 'object'
console.log(d instanceof Date); // shows 'true'
Любые идеи для написания функции isValidDate
?
Date.parse
для синтаксического анализа строк даты, что дает достоверный способ проверить правильность строки даты.Date
вообще, это было бы проще всего проверить.Date
, а затем тестирование значения времени Date
. Если дата недействительна, значение времени NaN
. Я проверил с ECMA-262, и это поведение находится в стандарте, и именно это я и ищу.Вот как бы я это сделал:
if ( Object.prototype.toString.call(d) === "[object Date]" ) {
// it is a date
if ( isNaN( d.getTime() ) ) { // d.valueOf() could also work
// date is not valid
}
else {
// date is valid
}
}
else {
// not a date
}
Вместо использования new Date()
вы должны использовать:
var timestamp = Date.parse('foo');
if (isNaN(timestamp) == false) {
var d = new Date(timestamp);
}
Date.parse()
возвращает метку времени, целое число, представляющее количество миллисекунд с 01 января /1970. Он вернет NaN
, если он не сможет разобрать предоставленную строку даты.
Date.parse
зависит от реализации и определенно не заслуживает доверия при разборе общих строк дат. Не существует единого формата, который правильно анализируется в популярных браузерах, тем более во всех используемых (хотя в конечном итоге формат ISO8601, указанный в ES5, должен быть в порядке).
Вы можете проверить достоверность объекта Date
d
через
d instanceof Date && isFinite(d)
Чтобы избежать проблем с несколькими кадрами, можно заменить проверку instanceof
на
Object.prototype.toString.call(d) === '[object Date]'
Вызов getTime()
, как в Borgar answer не нужен, поскольку isNaN()
и isFinite()
оба неявно преобразуются в число.
isFinite()
- toString.call()
является только заменой для instanceof
части проверки
Мое решение состоит в том, чтобы просто проверить, есть ли у вас действительный объект даты:
Date.prototype.isValid = function () {
// An invalid date object returns NaN for getTime() and NaN is the only
// object not strictly equal to itself.
return this.getTime() === this.getTime();
};
var d = new Date("lol");
console.log(d.isValid()); // false
d = new Date("2012/09/11");
console.log(d.isValid()); // true
isNaN
- более явный способ проверить NaN
кратчайший ответ для проверки действительной даты
if(!isNaN(date.getTime()))
date && !isNaN(date.getTime())
Хотелось бы упомянуть, что виджет jQuery UI DatePicker имеет очень полезный метод проверки валидности даты, который проверяет формат и достоверность (например, не разрешены даты 01/33/2013).
Даже если вы не хотите использовать виджет datepicker на своей странице в качестве элемента пользовательского интерфейса, вы всегда можете добавить свою библиотеку .js на свою страницу, а затем вызвать метод проверки, передав значение, которое вы хотите проверить в нем, Чтобы сделать жизнь еще проще, она берет строку как входную, а не объект JavaScript Date.
Смотрите: http://api.jqueryui.com/datepicker/
Он не указан как метод, но он существует как функция полезности. Найдите страницу для "parsedate", и вы найдете:
$datepicker.parseDate(формат, значение, настройки) - Извлечь дату из строкового значения в указанном формате.
Пример использования:
var stringval = '01/03/2012';
var testdate;
try {
testdate = $.datepicker.parseDate('mm/dd/yy', stringval);
// Notice 'yy' indicates a 4-digit year value
} catch (e)
{
alert(stringval + ' is not valid. Format must be MM/DD/YYYY ' +
'and the date value must be valid for the calendar.';
}
(Подробнее см. описание форматов даты в http://api.jqueryui.com/datepicker/#utility-parseDate)
В приведенном выше примере вы не увидите предупреждающее сообщение, так как "01/03/2012" является датой календаря в указанном формате. Однако, если вы сделали "stringval" равным "13/04/2013", например, вы получите предупреждающее сообщение, так как значение "13/04/2013" не является действительным для календаря.
Если переданное значение строки успешно проанализировано, значение 'testdate' будет объектом Javascript Date, представляющим строковое значение переданного. Если нет, это будет undefined.
Вот пример:
var m = moment('2015-11-32', 'YYYY-MM-DD');
m.isValid(); // false
Раздел проверки в документации достаточно ясен.
Кроме того, следующие флаги разбора приводят к недопустимой дате:
overflow
: переполнение поля даты, например, 13-й месяц, 32-й день месяца (или 29 февраля в непиковые годы), 367-й день года и т.д. переполнение содержит индекс недопустимой единицы для соответствия #invalidAt (см. ниже); -1 означает отсутствие переполнения.invalidMonth
: Недействительное имя месяца, например, момент ('Marbruary', 'MMMM');. Содержит недействительную строку месяца, иначе null.empty
: входная строка, которая не содержит ничего разборного, например момент ( "это вздор" ); Boolean.Источник: http://momentjs.com/docs/
moment("11/06/1986", "DD/MM/YYYY").isValid();
Мне очень понравился подход Кристофа (но не хватило репутации, чтобы его проголосовать). Для моего использования я знаю, что у меня всегда будет объект Date, поэтому я просто добавил дату с помощью метода valid().
Date.prototype.valid = function() {
return isFinite(this);
}
Теперь я могу просто написать это, и это гораздо более описательно, чем просто проверка isFinite в коде...
d = new Date(userDate);
if (d.valid()) { /* do stuff */ }
Я использую следующий код для проверки значений для года, месяца и даты.
function createDate(year, month, _date) {
var d = new Date(year, month, _date);
if (d.getFullYear() != year
|| d.getMonth() != month
|| d.getDate() != _date) {
throw "invalid date";
}
return d;
}
Подробнее см. Проверить дату в javascript
str
не используется.
// check whether date is valid
var t = new Date('2011-07-07T11:20:00.000+00:00x');
valid = !isNaN(t.valueOf());
Для проектов Angular.js вы можете использовать:
angular.isDate(myDate);
вы можете проверить действительный формат txDate.value с помощью этой обрезки. если он был в некотором формате, то Date obejct не был установлен и возвращает null в dt.
var dt = new Date(txtDate.value)
if (isNaN(dt))
И как @MiF предложил в кратчайшие сроки
if(isNaN(new Date(...)))
Хорошее решение! В моей библиотеке вспомогательных функций теперь выглядит так:
Object.isDate = function(obj) {
/// <summary>
/// Determines if the passed object is an instance of Date.
/// </summary>
/// <param name="obj">The object to test.</param>
return Object.prototype.toString.call(obj) === '[object Date]';
}
Object.isValidDate = function(obj) {
/// <summary>
/// Determines if the passed object is a Date object, containing an actual date.
/// </summary>
/// <param name="obj">The object to test.</param>
return Object.isDate(obj) && !isNaN(obj.getTime());
}
Здесь слишком много сложных ответов, но достаточно простой строки (ES5):
Date.prototype.isValid = function (d) { return !isNaN(Date.parse(d)) } ;
или даже в ES6:
Date.prototype.isValid = d => !isNaN(Date.parse(d));
Это просто сработало для меня
new Date('foo') == 'Invalid Date'; //is true
Однако это не сработало
new Date('foo') === 'Invalid Date'; //is false
IsValidDate: function(date) {
var regex = /\d{1,2}\/\d{1,2}\/\d{4}/;
if (!regex.test(date)) return false;
var day = Number(date.split("/")[1]);
date = new Date(date);
if (date && date.getDate() != day) return false;
return true;
}
Ни один из этих ответов не работал у меня (проверен в Safari 6.0) при попытке проверить дату, например, 2/31/2012, однако они отлично работают при попытке любой даты, большей 31.
Так что мне пришлось немного переборщить. Предполагая, что дата находится в формате mm/dd/yyyy
. Я использую @broox ответ:
Date.prototype.valid = function() {
return isFinite(this);
}
function validStringDate(value){
var d = new Date(value);
return d.valid() && value.split('/')[0] == (d.getMonth()+1);
}
validStringDate("2/29/2012"); // true (leap year)
validStringDate("2/29/2013"); // false
validStringDate("2/30/2012"); // false
&& value.split('/')[0] == (d.getMonth()+1);
Ни одно из вышеперечисленных решений для меня не помогло, что работала
function validDate (d) {
var date = new Date(d);
var day = ""+date.getDate();
if( day.length == 1)day = "0"+day;
var month = "" +( date.getMonth() + 1);
if( month.length == 1)month = "0"+month;
var year = "" + date.getFullYear();
return ((month + "/" + day + "/" + year) == d);
}
приведенный выше код увидит, когда JS делает 02/31/2012 в 03/02/2012, что его недействительный
Я написал эту функцию. Передайте ему строковый параметр, и он определит, является ли он действительной датой или нет на основе этого формата "dd/MM/yyyy".
вот тест
input: "hahaha", output: false.
input: "29/2/2000", output: true.
input: "29/2/2001", вывод: false.
function isValidDate(str) {
var parts = str.split('/');
if (parts.length < 3)
return false;
else {
var day = parseInt(parts[0]);
var month = parseInt(parts[1]);
var year = parseInt(parts[2]);
if (isNaN(day) || isNaN(month) || isNaN(year)) {
return false;
}
if (day < 1 || year < 1)
return false;
if(month>12||month<1)
return false;
if ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && day > 31)
return false;
if ((month == 4 || month == 6 || month == 9 || month == 11 ) && day > 30)
return false;
if (month == 2) {
if (((year % 4) == 0 && (year % 100) != 0) || ((year % 400) == 0 && (year % 100) == 0)) {
if (day > 29)
return false;
} else {
if (day > 28)
return false;
}
}
return true;
}
}
Я объединил лучшие результаты производительности, которые я нашел вокруг этой проверки, если данный объект:
В результате получается следующее:
function isValidDate(input) {
if(!(input && input.getTimezoneOffset && input.setUTCFullYear))
return false;
var time = input.getTime();
return time === time;
};
Вдохновленный подход Borgar, я убедился, что код не только проверяет дату, но фактически гарантирует, что дата является реальной датой, то есть даты, подобные 31/09/2011 и 29/02/2011, не допускаются.
function(dateStr) {
s = dateStr.split('/');
d = new Date(+s[2], s[1]-1, +s[0]);
if (Object.prototype.toString.call(d) === "[object Date]") {
if (!isNaN(d.getTime()) && d.getDate() == s[0] &&
d.getMonth() == (s[1] - 1)) {
return true;
}
}
return "Invalid date!";
}
Готовая функция, основанная на наилучшем ответе:
/**
* Check if date exists and is valid.
*
* @param {String} dateString Date in YYYY-mm-dd format.
*/
function isValidDate(dateString) {
var isValid = false;
var date;
date =
new Date(
dateString);
if (
Object.prototype.toString.call(
date) === "[object Date]") {
if (isNaN(date.getTime())) {
// Date is unreal.
} else {
// Date is real if month and day match each other in date and string (otherwise may be shifted):
isValid =
date.getUTCMonth() + 1 === dateString.split("-")[1] * 1 &&
date.getUTCDate() === dateString.split("-")[2] * 1;
}
} else {
// It not a date.
}
return isValid;
}
function isValidDate(strDate) {
var myDateStr= new Date(strDate);
if( ! isNaN ( myDateStr.getMonth() ) ) {
return true;
}
return false;
}
Назовите его так:
isValidDate(""2015/5/2""); // => true
isValidDate(""2015/5/2a""); // => false
Выбранный ответ превосходный, и я тоже его использую. Однако, если вы ищете способ подтверждения ввода даты пользователя, вы должны знать, что объект Date очень устойчив в отношении того, что может показаться недопустимыми аргументами построения в действительные. Следующий код unit test иллюстрирует точку:
QUnit.test( "valid date test", function( assert ) {
//The following are counter-examples showing how the Date object will
//wrangle several 'bad' dates into a valid date anyway
assert.equal(isValidDate(new Date(1980, 12, 15)), true);
d = new Date();
d.setFullYear(1980);
d.setMonth(1);
d.setDate(33);
assert.equal(isValidDate(d), true);
assert.equal(isValidDate(new Date(1980, 100, 150)), true);
//If you go to this exterme, then the checker will fail
assert.equal(isValidDate(new Date("This is junk")), false);
//This is a valid date string
assert.equal(isValidDate(new Date("November 17, 1989")), true);
//but is this?
assert.equal(isValidDate(new Date("November 35, 1989")), false);
//Ha! It not. So, the secret to working with this version of
//isValidDate is to pass in dates as text strings... Hooboy
//alert(d.toString());
});
вы можете конвертировать свои даты и время в миллисекунды getTime()
this getTime()
Возвращает метод Не Число NaN
, если оно недействительно
if(!isNaN(new Date("2012/25/255").getTime()))
return 'valid date time';
return 'Not a valid date time';
!isNaN(new Date("2/30/2012").getTime())
возвращает true
Объект Date для строки является более простым и надежным способом определения, являются ли оба поля действительной датой. например Если вы введете это "-------" в поле ввода даты. Некоторые из вышеперечисленных ответов не будут работать.
jQuery.validator.addMethod("greaterThan",
function(value, element, params) {
var startDate = new Date($(params).val());
var endDate = new Date(value);
if(startDate.toString() === 'Invalid Date' || endDate.toString() === 'Invalid Date') {
return false;
} else {
return endDate > startDate;
}
},'Must be greater than {0}.');
Я думаю, что некоторые из них - долгий процесс. Мы можем сократить его, как показано ниже:
function isValidDate(dateString) {
debugger;
var dateStringSplit;
var formatDate;
if (dateString.length >= 8 && dateString.length<=10) {
try {
dateStringSplit = dateString.split('/');
var date = new Date();
date.setYear(parseInt(dateStringSplit[2]), 10);
date.setMonth(parseInt(dateStringSplit[0], 10) - 1);
date.setDate(parseInt(dateStringSplit[1], 10));
if (date.getYear() == parseInt(dateStringSplit[2],10) && date.getMonth()+1 == parseInt(dateStringSplit[0],10) && date.getDate() == parseInt(dateStringSplit[1],10)) {
return true;
}
else {
return false;
}
} catch (e) {
return false;
}
}
return false;
}
Так что мне понравился @Ask Clarke ответ с небольшим улучшением, добавив try catch block для дат, которые не могут пройти через var d = new Date (d) -
function checkIfDateNotValid(d) {
try{
var d = new Date(d);
return !(d.getTime() === d.getTime()); //NAN is the only type which is not equal to itself.
}catch (e){
return true;
}
}
date.parse(valueToBeTested) > 0
- все, что нужно. Действительная дата вернет значение эпохи, а недопустимое значение вернет NaN, который завершит тест > 0
, даже не будучи числом.
Это так просто, что вспомогательная функция не сохранит код, хотя он может быть немного более читабельным. Если вы этого хотели:
String.prototype.isDate = function() {
return !Number.isNaN(Date.parse(this));
}
ИЛИ
Для использования:
"StringToTest".isDate();
function isValidDate(date) {
return !! (Object.prototype.toString.call(date) === "[object Date]" && +date);
}
Как правило, я придерживаюсь того, что Имплантация даты находится в стеке браузера. Это означает, что вы всегда будете получать "Недействительную дату" при вызове toDateString() в Chrome, Firefox и Safari с этой даты ответа.
if(!Date.prototype.isValidDate){
Date.prototype.isValidDate = function(){
return this.toDateString().toLowerCase().lastIndexOf('invalid') == -1;
};
}
Я не тестировал это в IE.
Для компонентов, основанных на int 1, даты:
var is_valid_date = function(year, month, day) {
var d = new Date(year, month - 1, day);
return d.getFullYear() === year && (d.getMonth() + 1) === month && d.getDate() === day
};
Тесты:
is_valid_date(2013, 02, 28)
&& is_valid_date(2016, 02, 29)
&& !is_valid_date(2013, 02, 29)
&& !is_valid_date(0000, 00, 00)
&& !is_valid_date(2013, 14, 01)
Date.valid = function(str){
var d = new Date(str);
return (Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()));
}
https://gist.github.com/dustinpoissant/b83750d8671f10c414b346b16e290ecf
Этот вкус isValidDate использует регулярное выражение, которое обрабатывает високосные годы:
function isValidDate(value)
{
return /((^(10|12|0?[13578])([/])(3[01]|[12][0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(11|0?[469])([/])(30|[12][0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([/])(2[0-8]|1[0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([/])(29)([/])([2468][048]00)$)|(^(0?2)([/])(29)([/])([3579][26]00)$)|(^(0?2)([/])(29)([/])([1][89][0][48])$)|(^(0?2)([/])(29)([/])([2-9][0-9][0][48])$)|(^(0?2)([/])(29)([/])([1][89][2468][048])$)|(^(0?2)([/])(29)([/])([2-9][0-9][2468][048])$)|(^(0?2)([/])(29)([/])([1][89][13579][26])$)|(^(0?2)([/])(29)([/])([2-9][0-9][13579][26])$))/.test(value)
}
Эта функция проверяет дату строки в форматах цифр, ограниченных символом, например. дд/мм/гггг, мм/дд/гггг
/*
Param :
1)the date in string data type
2)[optional - string - default is "/"] the date delimiter, most likely "/" or "-"
3)[optional - int - default is 0] the position of the day component when the date string is broken up via the String.split function (into arrays)
4)[optional - int - default is 1] the position of the month component when the date string is broken up via the String.split function (into arrays)
5)[optional - int - default is 2] the position of the year component when the date string is broken up via the String.split function (into arrays)
Return : a javascript date is returned if the params are OK else null
*/
function IsValidDate(strDate, strDelimiter, iDayPosInArray, iMonthPosInArray, iYearPosInArray) {
var strDateArr; //a string array to hold constituents day, month, and year components
var dtDate; //our internal converted date
var iDay, iMonth, iYear;
//sanity check
//no integer checks are performed on day, month, and year tokens as parsing them below will result in NaN if they're invalid
if (null == strDate || typeof strDate != "string")
return null;
//defaults
strDelimiter = strDelimiter || "/";
iDayPosInArray = undefined == iDayPosInArray ? 0 : iDayPosInArray;
iMonthPosInArray = undefined == iMonthPosInArray ? 1 : iMonthPosInArray;
iYearPosInArray = undefined == iYearPosInArray ? 2 : iYearPosInArray;
strDateArr = strDate.split(strDelimiter);
iDay = parseInt(strDateArr[iDayPosInArray],10);
iMonth = parseInt(strDateArr[iMonthPosInArray],10) - 1; // Note: months are 0-based
iYear = parseInt(strDateArr[iYearPosInArray],10);
dtDate = new Date(
iYear,
iMonth, // Note: months are 0-based
iDay);
return (!isNaN(dtDate) && dtDate.getFullYear() == iYear && dtDate.getMonth() == iMonth && dtDate.getDate() == iDay) ? dtDate : null; // Note: months are 0-based
}
Пример вызова:
var strDate = "18-01-1971";
if (null == IsValidDate (strDate)) {
alert ( "неверная дата" ); }
var isDate_ = function(input) {
var status = false;
if (!input || input.length <= 0) {
status = false;
} else {
var result = new Date(input);
if (result == 'Invalid Date') {
status = false;
} else {
status = true;
}
}
return status;
}