Следует помнить, что regex был разработан для сопоставления даты (или не даты). Сказать, что дата действительна, гораздо сложнее, поскольку это потребует обработки большого количества исключений.
Начнем с сопоставления месяца (1 - 12) с необязательным ведущим 0:
1 | 0?[1-9]|1[0-2] |
Чтобы сопоставить день, также с необязательным ведущим 0:
1 | 0?[1-9]|[12][0-9]|3[01] |
И для соответствия году (предположим, что диапазон 1900 - 2999):
1 | (?:19|20)[0-9]{2} |
Разделитель может быть пробелом, тире, слешем, пустым и т.д. Не стесняйтесь добавлять все, что вы считаете нужным использовать в качестве разделителя:
1 | [-\\/ ]? |
Теперь вы конкатенируете все это и получаете:
1 2 3 | (0?[1-9]|1[0-2])[-\\/ ]?(0?[1-9]|[12][0-9]|3[01])[-/ ]?(?:19|20)[0-9]{2} // MMDDYYY (0?[1-9]|[12][0-9]|3[01])[-\\/ ]?(0?[1-9]|1[0-2])[-/ ]?(?:19|20)[0-9]{2} // DDMMYYYY (?:19|20)[0-9]{2}[-\\\/ ]?(0?[1-9]|1[0-2])[-/ ]?(0?[1-9]|[12][0-9]|3[01]) // YYYYMMDD |
Если вы хотите быть более педантичным, то можете использовать обратную ссылку, чтобы быть уверенным, что два разделителя будут одинаковыми:
1 2 3 | (0?[1-9]|1[0-2])([-\\/ ]?)(0?[1-9]|[12][0-9]|3[01])\2(?:19|20)[0-9]{2} // MMDDYYY (0?[1-9]|[12][0-9]|3[01])([-\\/ ]?)(0?[1-9]|1[0-2])\2(?:19|20)[0-9]{2} // DDMMYYYY (?:19|20)[0-9]{2}([-\\\\/ ]?)(0?[1-9]|1[0-2])\2(0?[1-9]|[12][0-9]|3[01]) // YYYYMMDD |