Рубрики
Без рубрики

Регулярное выражение Java проверяет примеры формата даты

– Примеры регулярных выражений Java для проверки формата даты

В этой статье показано, как использовать регулярное выражение + код для проверки формата даты, поддержки одиночного и начального нулевого формата месяца и дня (1 или 01), проверки 30 или 31 дня месяца и проверки високосного года.

Ниже приведены требования к действительной дате.

  1. Формат года, 1900, 2099 регулярное выражение
  2. Формат месяца, 1, 01, 2, 02… 12 регулярное выражение
  3. Формат дня, 1, 01…31 регулярное выражение
  4. Високосный год, 29 февраля. код
  5. Обычный год, 28 дней февраля. код
  6. 31 День месяца – 1, 3, 5, 7, 8, 10, 12. код
  7. 30 Дней в месяце – 4, 6, 9, 11,. код
  8. 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 Stream validDateProvider() {
        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-регулярное выражение/дата

Рекомендации

Оригинал: “https://mkyong.com/regular-expressions/how-to-validate-date-with-regular-expression/”