Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Валидация даты/время без библиотеки Date.js (https://javascript.ru/forum/misc/64110-validaciya-daty-vremya-bez-biblioteki-date-js.html)

Master_Sergius 20.07.2016 12:13

Валидация даты/время без библиотеки Date.js
 
Здравствуйте! Вот, что умеет библиотека Date.js http://www.datejs.com/:

> Date.parseExact('01-01-2001', "MM-dd-yyyy")
Mon Jan 01 2001 00:00:00 GMT+0200 (EET)
> Date.parseExact('01-01-2001', "MM-dd-yyyy HH:mm:ss")
null
> Date.parseExact('01-01-2001 12:12:12', "MM-dd-yyyy HH:mm:ss")
Mon Jan 01 2001 12:12:12 GMT+0200 (EET)


То есть, Я могу провести валидацию даты и времени согласно нужному мне формату. Как добиться такого же результата без использования сторонних библиотек? Ну и конечно же не подходит вариант - скопировать код этой библиотеки себе в скрипт :)

рони 20.07.2016 12:44

Цитата:

Сообщение от Rise
почему во втором случае null

а что должно быть если данные не соотвествуют формату

рони 20.07.2016 12:47

Цитата:

Сообщение от Master_Sergius
. Как добиться такого же результата без использования сторонних библиотек?

парсить строку и проверять

Master_Sergius 20.07.2016 12:56

Цитата:

Сообщение от Rise (Сообщение 422714)
рони, а визуально не видно что не соответствуют формату зачем для этого библиотеку писать?

Ага, зачем же тогда вообще понапридумывали кучу алгоритмов, если всё видно визуально?

Цитата:

Сообщение от рони
парсить строку и проверять

Да, похоже как-то придётся парсить, но как? Разбить на числа и пробовать создать новый объект Date?

рони 20.07.2016 12:59

Цитата:

Сообщение от Rise
визуально не видно

:blink: не осилил ... это типа а нафига валидация в js?

рони 20.07.2016 13:01

Цитата:

Сообщение от Master_Sergius
Разбить на числа и пробовать создать новый объект Date?

из новой даты вытащить числа, сформировать строку и сравнить с прежней строкой ... как-то так

Master_Sergius 20.07.2016 13:05

Цитата:

Сообщение от Rise (Сообщение 422718)
Master_Sergius, ну и для чего это надо приведи пример?

Обычно, максимум валидации пытаются сделать на стороне клиента, чтобы не грузить сервер и сеть. Представьте, что запросы/ответы могут быть реально очень тяжеловесные.

Master_Sergius 20.07.2016 16:06

Вот, решил таким образом:

function validate_date(date_str, date_format){
    /* Validate date or datetime due to specified format
     *
     * Example: date_str "01/01/2016" valid with format "M/d/y",
     *          but invalid with format "M/d/y h:m:s"
     */
    date_str = date_str.trim();
    var letter = "", re = "";
    // replace letters in format with regex digit "\d", thus 'd' must be first
    replace_patterns = ['d', 'M', 'm', 'Y', 'y', 'H', 'h', 'm', 's']
    for (i=0; i < replace_patterns.length; i++) {
        pattern = replace_patterns[i];
        re = new RegExp(pattern, 'g');
        date_format = date_format.replace(re, '\\d');
    }
    var date_format_regex = new RegExp('^' + date_format + '$');
    return (date_format_regex.test(date_str) && !isNaN(Date.parse(date_str)));
};


Единственная беда в том, что Date.parse() пропускает чуть ли не любое число для месяца и дня, к примеру:

>Date.parse('40/40/2015')
1525899600000


Ещё бы эту проблему решить как-то.

рони 20.07.2016 16:44

Цитата:

Сообщение от Master_Sergius
Ещё бы эту проблему решить как-то.

Цитата:

Сообщение от рони
из новой даты вытащить числа, сформировать строку и сравнить с прежней строкой ... как-то так

:-?

рони 20.07.2016 16:47

Master_Sergius,
вам какой формат нужен?

рони 20.07.2016 17:22

валидация даты
 
Master_Sergius,
function validate_date(date) {
    var str = date.trim().split("/");
    if (str.length == 3) {
        str = new Date(str[2], str[0] - 1, str[1], 0, 0, 0);
        if (!str) return false;
        str = [("0" + (str.getMonth() + 1)).substr(-2), ("0" + str.getDate()).substr(-2), str.getFullYear()].join("/");
        return str === date.trim()
    }
    return false
};
alert(validate_date('01/21/2015')); //true  mm/dd/yyyy
alert(validate_date('40/40/2015')); // false

Master_Sergius 20.07.2016 17:37

Цитата:

Сообщение от рони (Сообщение 422760)
Master_Sergius,
function validate_date(date) {
    var str = date.trim().split("/");
    if (str.length == 3) {
        str = new Date(str[2], str[0] - 1, str[1], 0, 0, 0);
        if (!str) return false;
        str = [("0" + (str.getMonth() + 1)).substr(-2), ("0" + str.getDate()).substr(-2), str.getFullYear()].join("/");
        return str === date.trim()
    }
    return false
};
alert(validate_date('01/21/2015')); //true  mm/dd/yyyy
alert(validate_date('40/40/2015')); // false

Неплохой вариант! Я ещё такую штуку рассматриваю:
^(([0]?[1-9]|1[0-2])/([0-2]?[0-9]|3[0-1])/[1-2]\d{3}) (20|21|22|23|[0-1]?\d{1}):([0-5]?\d{1})$


В общем, суть понял. Спасибо.

Master_Sergius 20.07.2016 18:30

Цитата:

Сообщение от рони (Сообщение 422760)
Master_Sergius,
function validate_date(date) {
    var str = date.trim().split("/");
    if (str.length == 3) {
        str = new Date(str[2], str[0] - 1, str[1], 0, 0, 0);
        if (!str) return false;
        str = [("0" + (str.getMonth() + 1)).substr(-2), ("0" + str.getDate()).substr(-2), str.getFullYear()].join("/");
        return str === date.trim()
    }
    return false
};
alert(validate_date('01/21/2015')); //true  mm/dd/yyyy
alert(validate_date('40/40/2015')); // false

Вот это меня натолкнуло на такую мысль и теперь вроде всё работает (до идеала ещё далеко, но всё же):

function validate_date(date_str, date_format){
    /* Validate date or datetime due to specified format
     *
     * Example: date_str "01/01/2016" valid with format "MM/dd/YYYY",
     *          but invalid with format "MM/dd/YYYY hh:mm:ss"
     *
     * NOTE: MM/dd/YYYY and M/d/Y are equivalent, hh:mm:ss equals to h:m:s
     */
    date_str = date_str.trim();
    var date_parsed = Date.parse(date_str);
    if (!isNaN(date_parsed)) {
        date_parsed = new Date(date_parsed);
    } else {
        return false;
    }
    // build date from components according to format
    date_format = date_format.replace(/M+/g, ("0" + (date_parsed.getMonth() + 1)).substr(-2));
    date_format = date_format.replace(/d+/g, ("0" + date_parsed.getDate()).substr(-2));
    date_format = date_format.replace(/Y+/g, date_parsed.getFullYear());
    date_format = date_format.replace(/h+/g, ("0" + date_parsed.getHours()).substr(-2));
    date_format = date_format.replace(/m+/g, ("0" + date_parsed.getMinutes()).substr(-2));
    date_format = date_format.replace(/s+/g, ("0" + date_parsed.getSeconds()).substr(-2));
    console.log(date_parsed);
    console.log(date_format);
    return date_str == date_format
};

alert(validate_date('02/30/2016', 'MM/dd/YYYY'));
alert(validate_date('02/28/2016', 'MM/dd/YYYY'));

рони 20.07.2016 19:35

Цитата:

Сообщение от Rise
а то получится 30 февраля валидной датой...

не получится, можешь проверить

рони 20.07.2016 19:42

Rise,
function validate_date(date) {
    var str = date.trim().split("/");
    if (str.length == 3) {
        str = new Date(str[2], str[0] - 1, str[1], 0, 0, 0);
        if (!str) return false;
        str = [("0" + (str.getMonth() + 1)).substr(-2), ("0" + str.getDate()).substr(-2), str.getFullYear()].join("/");
        return str === date.trim()
    }
    return false
};
alert(validate_date('02/30/2015')); //false  mm/dd/yyyy
alert(validate_date('02/28/2015')); //true  mm/dd/yyyy

рони 20.07.2016 20:10

Цитата:

Сообщение от Rise
рони, наверное строка 5 бесполезна?

не вижу вариантов, если str не дата вернуть false , что не так?

рони 20.07.2016 20:17

Валидация даты
 
Rise,
function validate_date(date) {
    var str = date.trim().split("/");
    if (str.length == 3) {
        str = new Date(str[2], str[0] - 1, str[1], 0, 0, 0); alert(str)
        if (!str) return false;
        str = [("0" + (str.getMonth() + 1)).substr(-2), ("0" + str.getDate()).substr(-2), str.getFullYear()].join("/");
        return str === date.trim()
    }
    return false
};
alert(validate_date('02/дд/2015')); //  mm/dd/yyyy

рони 20.07.2016 20:40

Валидация даты
 
Rise,
уговорил :)
дополненный вариант
function validate_date(date) {
    var str = date.trim().split("/");
    if (str.length == 3) {
        str = new Date(str[2], str[0] - 1, str[1], 0, 0, 0);
        if (str == 'Invalid Date') return false;
        str = [("0" + (str.getMonth() + 1)).substr(-2), ("0" + str.getDate()).substr(-2), str.getFullYear()].join("/");
        return str === date.trim()
    }
    return false
};
alert(validate_date('02/дд/2015')); //false  mm/dd/yyyy
alert(validate_date('02/30/2015')); //false  mm/dd/yyyy
alert(validate_date('02/29/2016')); //true  mm/dd/yyyy

рони 20.07.2016 20:40

Rise,
спасибо за науку!!! плюсануть не могу

Master_Sergius 21.07.2016 11:15

Я добавил алерты и кнопочку запустить, прошу проверить.


Часовой пояс GMT +3, время: 17:33.