Преобразование строки с датой и временем в нативный объект Date

Разбор строки с датой и временем в JavaScript — задача нетривиальная. Поведение браузера при разных форматах записи не определено. Некоторые браузеры пытаются угадать формат, в то время как другие возвращают значение NaN. Конечно, есть специализированные библиотеки наподобие Day.js или Moment.js, но они нацелены на решение более широкого круга задач, тогда как иногда, условно говоря, достаточно одной функции из большой библиотеки.

В одном из проектов мне понадобилось добавить к полю ввода даты возможность инкрементировать месяцы. Чтобы сделать это корректно, нужно для начала разобрать входную строку с датой. При этом не забыть, что с интерфейсом пользователи могут взаимодейстовать в системах с различными настройками локали.

Форматы ввода для разбора

Дата

2008-05-07  2008/05/07  2008.05.07  07-05-2008
07/05/2008  07.05.2008  07-15-2008  07/15/2008
07.15.2008  17-05-2008  17/05/2008  17.05.2008
7-5-2008    7/5/2008    7.5.2008

Дата и время

2008-05-07 09:15    2008/05/07 9:15 07.05.2008 09a15
07-05-2008 9a15 2008/05/07 21:15    2008.05.07 21:15
07-05-2008 09p15    07/05/2008 9p15 2008.05.07 12:15
2008-05-07 00:15    07/05/2008 12a15    07.05.2008 12p15

JavaScript-код парсера строки с датой и временем

function parseDate(dateString) {
    "use strict";
    if (!dateString) {
        return new Date();
    }

    dateString = dateString.match(/(?:(\d{4})([\-\/.])([0-3]?\d)\2([0-3]?\d)|([0-3]?\d)([\-\/.])([0-3]?\d)\6(\d{4}))(?:\s+([012]?\d)([:hap])([0-5]\d))?/i) || [dateString];
    dateString.forEach((v, i, a) => {
        a[i] = v && v.match(/^\d+$/) ? parseInt(v, 10) : (v || 0);
    });

    if (dateString.length > 1) {
        if (!dateString[1]) {
            dateString[1] = dateString[8];
            dateString[2] = dateString[6];
            dateString[3] = dateString[7];
            dateString[4] = dateString[5];
        }

        if (dateString[3] > 12 && dateString[4] < 13) {
            dateString[0] = dateString[3];
            dateString[3] = dateString[4];
            dateString[4] = dateString[0];
        }

        if (dateString[10] === 'P' || dateString[10] === 'p' && dateString[9] < 13) {
            dateString[9] = (dateString[9] + 12) % 24;
        }

        if (dateString[3] > 12 || dateString[4] > ([0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][dateString[3]])) {
            return dateString[0];
        }

        return new Date(dateString[1], dateString[3] - 1, dateString[4], dateString[9], dateString[11], 0, 0);
    }
    return dateString[0];
}

Это адаптированный вариант функции-парсера от Hans PUFAL, код в оригинале: http://jsfiddle.net/jstoolsmith/Db3JM/. Возможно, пригодится и вам.