В этой статье показано, как использовать регулярное выражение + код для проверки формата даты, поддержки одиночного и начального нулевого формата месяца и дня (1 или 01), проверки 30 или 31 дня месяца и проверки високосного года.
Ниже приведены требования к действительной дате.
- Формат года, 1900, 2099
регулярное выражение
- Формат месяца, 1, 01, 2, 02… 12
регулярное выражение
- Формат дня, 1, 01…31
регулярное выражение
- Високосный год, 29 февраля.
код
- Обычный год, 28 дней февраля.
код
- 31 День месяца – 1, 3, 5, 7, 8, 10, 12.
код
- 30 Дней в месяце – 4, 6, 9, 11,.
код
- ISO 8601 ,
гггг-ММ-дд
илиуууу-М-д
, например, 2020-11-03.регулярное выражение
((?:19|20)[0-9][0-9])-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])
Приведенное выше регулярное выражение может выполнять требования 1, 2, 3 и 8. Для требований 4, 5, 6, 7 нам нужна ручная проверка кода. Допустимый диапазон дат от 1900-01-01
или 1900-1-1
чтобы 2099-12-31
.
1. Регулярное выражение для формата даты, Года, месяца и Дня.
1.1 Регулярное выражение для подтверждения года, принимает 1900-2099
.
(19|20)[0-9][0-9] # explanation 19[0-9][0-9] # 1900-1999 | # ..or 20[0-9][0-9] # 2000-2099
В будущем, если мы хотим поддерживать год, начинающийся с 21xx
, обновите регулярное выражение, как показано ниже:
(19|20|21)[0-9][0-9]
1.2 Регулярное выражение для подтверждения месяца, принимает 01-09
(ведущий ноль), 1-9
(однозначная цифра) и 10,11,12
.
0?[1-9]|1[012] # explanation 0?[1-9] # 01-09 or 1-9 | # ..or 1[012] # 10,11,12
1.3 Регулярное выражение для подтверждения дня, принимает 01-09
(ведущий ноль), 1-9
(одна цифра), 10-19
, 20-29
и 30-31
.
0?[1-9]|[12][0-9]|3[01] # explanation 0?[1-9] # 01-09 or 1-9 | # ..or [12][0-9] # 10-19 or 20-29 | # ..or 3[01] # 30, 31
1.4 У нас есть регулярное выражение для года, месяца и дня, попробуйте объединить его с разными разделителями, чтобы сформировать другой формат даты.
Регулярное выражение для проверки формата даты дд/мм/гггг (общее)
или d/M/uuuu (форматер даты Java)
# (dd)/(mm)/(yyyy) (0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/((?:19|20)[0-9][0-9])
Регулярное выражение для проверки формата даты гггг-мм-дд (общий)
или uuuu-Md (форматирование даты Java)
# (yyyy)-(mm)-(dd) ((?:19|20)[0-9][0-9])-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])
Регулярное выражение для проверки формата даты гггг.мм.дд (общий)
или уууу. M.d (форматер даты Java)
# (yyyy).(mm).(dd) ((?:19|20)[0-9][0-9])\\.(0?[1-9]|1[012])\\.(0?[1-9]|[12][0-9]|3[01])$
P.S ?: означает совпадение, но не захватывает его. Смотрите ниже #3 Java DateValidator.
2. 30 или 31 день и високосный год.
Теперь мы можем использовать приведенное выше регулярное выражение для записи года, месяца и дня. Позже мы проверим 30 или 31 день месяца и високосный год .
2.1 В течение 30 или 31 дня месяца.
- В течение месяца 1,3,5,7,8,10,12 имеет 31 день.
- На месяц 4,6,9,11 приходится 30 дней.
if ((month.equals("4") || month.equals("6") || month.equals("9") || month.equals("04") || month.equals("06") || month.equals("09") || month.equals("11")) && day.equals("31")) { isValid = false; }
2.2 Для високосного года 366 дней в году, а в феврале 29 дней; Для обычного года 365 дней в году, а в феврале 28 дней.
if (month.equals("2") || month.equals("02")) { if (day.equals("30") || day.equals("31")) { isValid = false; } else if (day.equals("29")) { // feb 29 days? leap year checking if (!isLeapYear(year)) { isValid = false; } } } private static boolean isLeapYear(int year) { return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); }
“Каждый год, который в точности делится на четыре, является високосным годом, за исключением лет, которые в точности делятся на 100, но эти столетние годы являются високосными, если они в точности делятся на 400. Например, 1700, 1800 и 1900 годы не являются високосными, но 1600 и 2000 годы являются високосными”.
Источник: Википедия Високосный год .
3. Средство проверки даты Регулярных Выражений Java
Вот окончательная версия.
package com.mkyong.regex.date; import java.util.regex.Matcher; import java.util.regex.Pattern; public class DateValidatorRegex { // ?: match but don't capture it // uuuu-M-d private static final String DATE_PATTERN = "^((?:19|20)[0-9][0-9])-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$"; private static final Pattern pattern = Pattern.compile(DATE_PATTERN); public static boolean isValid(final String date) { boolean result = false; Matcher matcher = pattern.matcher(date); if (matcher.matches()) { // it is a valid date format yyyy-mm-dd // assign true first, later we will check the leap year and odd or even months result = true; // (?:19|20), match but don't capture it, otherwise it will messy the group order // for example, 2020-2-30, it will create 4 groups. // group(1) = 2020, group(2) matches (19|20) = 20, group(3) = 2, group(4) = 30 // So, we put (?:19|20), don't capture this group. int year = Integer.parseInt(matcher.group(1)); // why string? month matches 02 or 2 String month = matcher.group(2); String day = matcher.group(3); // 30 or 31 days checking // only 1,3,5,7,8,10,12 has 31 days if ((month.equals("4") || month.equals("6") || month.equals("9") || month.equals("04") || month.equals("06") || month.equals("09") || month.equals("11")) && day.equals("31")) { result = false; } else if (month.equals("2") || month.equals("02")) { if (day.equals("30") || day.equals("31")) { result = false; } else if (day.equals("29")) { // leap year? feb 29 days. if (!isLeapYear(year)) { result = false; } } } } return result; } private static boolean isLeapYear(int year) { return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); } }
4. Модульные тесты
Ниже приведены параметризованные тесты JUnit 5 для вышеуказанных средств проверки данных Java.
package com.mkyong.regex.date; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; public class DateValidatorTest { @ParameterizedTest(name = "#{index} - Run test with date = {0}") @MethodSource("validDateProvider") void test_date_regex_valid(String date) { assertTrue(DateValidatorRegex.isValid(date)); } @ParameterizedTest(name = "#{index} - Run test with date = {0}") @MethodSource("invalidDateProvider") void test_date_regex_invalid(String date) { assertFalse(DateValidatorRegex.isValid(date)); } static StreamvalidDateProvider() { return Stream.of( "1998-09-30", "1998-9-30", "2020-09-1", "2020-09-01", "2020-9-1", "2020-9-01", "2020-2-29", // leap year "2020-2-28", // leap year "2019-2-28", // common year "2000-02-29", // 2000 is a leap year, % 400 == 0 "1900-02-28", // 1900 is a common year "2020-07-31", "2020-08-31", "2020-06-30", "1900-01-01", "2099-12-31"); } static Stream invalidDateProvider() { return Stream.of( "1998-09-31", // invalid day, sep max 30 "1998-11-31", // invalid day, nov max 30 "2008-02-2x", // invalid day 2x "2008-0x-28", // invalid month 0x "20xx-02-28", // invalid year 20xx "20-11-02", // invalid year 20, must be yyyy "2020/11/02", // invalid date format, yyyy-mm-dd "2020-11-32", // invalid day, 32 "2020-13-30", // invalid month 13 "2020-A-20", // invalid month A "2020-2-30", // leap year, feb max 29 "2019-2-29", // common year, feb max 28 "1900-02-29", // 1900 is a common year, feb max 28 "12012-04-05", // support only 4 digits years " ", // empty ""); // empty } }
Все тесты пройдены.
5. Java 8 форматирование даты и времени + стиль преобразования. строгий
Для разработчика с защитой от регулярных выражений рассмотрим Java 8 Форматировщик даты и времени
+ Решающий стиль. СТРОГОЕ
решение для проверки формата даты. Для получения полного примера и модульных тестов, пожалуйста, обратитесь к этой статье – Проверьте, действительна ли дата в Java
public static boolean isValid(final String date) { boolean valid = false; try { // ResolverStyle.STRICT for 30, 31 days checking, and also leap year. LocalDate.parse(date, DateTimeFormatter.ofPattern("uuuu-M-d") .withResolverStyle(ResolverStyle.STRICT) ); valid = true; } catch (DateTimeParseException e) { e.printStackTrace(); valid = false; } return valid; }
Скачать Исходный Код
$клон git $клон git
$cd java-регулярное выражение/дата
Рекомендации
- Википедия – Високосный год
- Википедия ISO 8601
- Форматирование даты и времени javadoc
- Проверьте, действительна ли дата в Java
Оригинал: “https://mkyong.com/regular-expressions/how-to-validate-date-with-regular-expression/”