Я изменил регулярное выражение, которое я получил здесь . Мне нужно было изменить его, потому что мне нужно было соответствовать следующим дополнительным критериям:
- Даты только с месяцем и годом
- полные даты в виде мм дд, гггг
- Даты только с годом
- Ввод с посторонней информацией (например, том 51, № 1, март 2008 г.)
Это то, что у меня есть до сих пор. Я сделал это с RegexBuddy, чтобы помочь мне разобрать логику, но это настолько сложно, что я не уверен, что у меня есть самое эффективное решение.
\b(?:((Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sept|Nov|Dec)(ember)?)|((((Jan(uary)?|Ma(r(ch)?|y)|Jul(y)?|Aug(ust)?|Oct(ober)?|Dec(ember)?) 31)|((Jan(uary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sept|Nov|Dec)(ember)?) (0?[1-9]|([12]\d)|30))|(Feb(ruary)? (0?[1-9]|1\d|2[0-8]|(29(?=, ((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))))),)) ((1[6-9]|[2-9]\d)\d{2}))|((1[6-9]|[2-9]\d)\d{2})
Можно ли что-нибудь сделать, чтобы сохранить функциональность как исходного регулярного выражения, так и моих дополнительных критериев?
Вот код, в котором я это реализую, если он поможет вам увидеть, что я пытаюсь сделать. Предполагается, что выходные данные функции parseDate представляют собой строковую дату в форме «гггг мм дд» (т. Е. В примере 4 должно быть выведено «2008 мар»):
//generalized RegEx function
function returnRegExMatch(ex,haystack) {
var needle = ex.exec(haystack);
if (needle) { return needle[0]; }
}
// date extraction (uses returnRegExMatch)
function parseDate(date) {
//strip anything other than a valid date
var dateRe = /\b(?:((Jan(uary)?|Feb(ruary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sept|Nov|Dec)(ember)?)|((((Jan(uary)?|Ma(r(ch)?|y)|Jul(y)?|Aug(ust)?|Oct(ober)?|Dec(ember)?) 31)|((Jan(uary)?|Ma(r(ch)?|y)|Apr(il)?|Ju((ly?)|(ne?))|Aug(ust)?|Oct(ober)?|(Sept|Nov|Dec)(ember)?) (0?[1-9]|([12]\d)|30))|(Feb(ruary)? (0?[1-9]|1\d|2[0-8]|(29(?=, ((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))))),)) ((1[6-9]|[2-9]\d)\d{2}))|((1[6-9]|[2-9]\d)\d{2})/;
date = returnRegExMatch(dateRe,date);
var yearRe = /[0-9][0-9][0-9][0-9]/;
var monthRe = /Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/;
var dayRe = /[0-9]?[0-9],/;
var year = returnRegExMatch(yearRe,date);
var month = returnRegExMatch(monthRe,date);
var day = parseInt(returnRegExMatch(dayRe,date),10);
var dateReturned = "";
if (year) { dateReturned = year; }
if (month) { dateReturned = dateReturned + " " + month; }
if (month && day) { dateReturned = dateReturned + " " + day; }
return dateReturned;
}
Спасибо!
EDIT
Спасибо всем, кто нашел время, чтобы ответить. Вы, ребята, сделали то, на что я надеялся, указав на самые нелепые вещи в моей реализации. Я решил немного упростить основное регулярное выражение. Вот результат:
\b(?:(?:Jan(?:uary)?|Feb(?:ruary)?|Ma(?:r(?:ch)?|y)|Apr(?:il)?|Ju(?:(?:ly?)|(?:ne?))|Aug(?:ust)?|Oct(?:ober)?|(?:Sept|Nov|Dec)(?:ember)?) (?:\d{1,2}, )?)?\d{4}
Это не беспокоит обнаружение недействительных дат, основанных на високосных годах или чем-то еще. @ Барт убедил меня, что это лучше всего сделать с нативным JS, чем с регулярным выражением. Спасибо @Tim также за указание на необходимость не захватывать скобки.
Если у кого-то есть дополнительные предложения о том, как мне улучшить это регулярное выражение, пожалуйста, откажитесь.