Перевірте, чи є рядок дійсною датою в Java

1. Вступ

У цьому підручнику ми обговоримо різні способи перевірити, чи містить рядок дійсну дату в Java.

Ми обговоримо рішення до Java 8, після Java 8 та за допомогою Apache Commons Validator.

2. Огляд перевірки дати

Кожного разу, коли ми отримуємо дані в будь-якій програмі, нам потрібно перевірити їх дійсність перед подальшою обробкою.

У разі введення дати нам може знадобитися перевірити наступне:

  • Введення містить дату у допустимому форматі, наприклад, ММ / ДД / РРРР
  • Різні частини введення знаходяться в дійсному діапазоні
  • Введення визначає дійсну дату в календарі

Ми можемо використовувати регулярні вирази, щоб зробити вищезазначене. Однак регулярні вирази для обробки різних форматів введення та локалів є складними та схильними до помилок. Крім того, вони можуть погіршити продуктивність.

Ми обговоримо різні способи здійснення перевірки дат у гнучкій, надійній та ефективній формі.

Спочатку напишемо інтерфейс для перевірки дати:

public interface DateValidator { boolean isValid(String dateStr); }

У наступних розділах ми реалізуємо цей інтерфейс, використовуючи різні підходи.

3. Перевірте, використовуючи DateFormat

Java з самого початку пропонує засоби форматування та аналізу дат. Ця функціональність знаходиться в абстрактному класі DateFormat, а її реалізація - SimpleDateFormat .

Давайте реалізуємо перевірку дати за допомогою методу синтаксичного аналізу класу DateFormat :

public class DateValidatorUsingDateFormat implements DateValidator { private String dateFormat; public DateValidatorUsingDateFormat(String dateFormat) { this.dateFormat = dateFormat; } @Override public boolean isValid(String dateStr) { DateFormat sdf = new SimpleDateFormat(this.dateFormat); sdf.setLenient(false); try { sdf.parse(dateStr); } catch (ParseException e) { return false; } return true; } }

Оскільки DateFormat і пов'язані з ними класи не поточно- , ми створюємо новий екземпляр для кожного виклику методу.

Далі напишемо модульний тест для цього класу:

DateValidator validator = new DateValidatorUsingDateFormat("MM/dd/yyyy"); assertTrue(validator.isValid("02/28/2019")); assertFalse(validator.isValid("02/30/2019"));

Це було найпоширенішим рішенням до Java 8.

4. Перевірка за допомогою LocalDate

Java 8 представила вдосконалений API дати та часу. Він додав клас LocalDate , який представляє дату без часу. Цей клас є незмінним і безпечним для потоків.

LocalDate забезпечує два статичні методи синтаксичного аналізу дат. Обидва вони використовують DateTimeFormatter для фактичного розбору:

public static LocalDate parse​(CharSequence text) // parses dates using using DateTimeFormatter.ISO_LOCAL_DATE public static LocalDate parse​(CharSequence text, DateTimeFormatter formatter) // parses dates using the provided formatter

Давайте використаємо метод синтаксичного аналізу для реалізації перевірки дати:

public class DateValidatorUsingLocalDate implements DateValidator { private DateTimeFormatter dateFormatter; public DateValidatorUsingLocalDate(DateTimeFormatter dateFormatter) { this.dateFormatter = dateFormatter; } @Override public boolean isValid(String dateStr) { try { LocalDate.parse(dateStr, this.dateFormatter); } catch (DateTimeParseException e) { return false; } return true; } }

Реалізація використовує для форматування об'єкт DateTimeFormatter . Оскільки цей клас є потокобезпечним, ми використовуємо один і той же екземпляр для різних викликів методів.

Давайте також додамо модульний тест для цієї реалізації:

DateTimeFormatter dateFormatter = DateTimeFormatter.BASIC_ISO_DATE; DateValidator validator = new DateValidatorUsingLocalDate(dateFormatter); assertTrue(validator.isValid("20190228")); assertFalse(validator.isValid("20190230"));

5. Перевірка за допомогою DateTimeFormatter

У попередньому розділі ми побачили, що LocalDate використовує для аналізу об’єкт DateTimeFormatter . Ми також можемо використовувати клас DateTimeFormatter безпосередньо для форматування та синтаксичного аналізу.

DateTimeFormatter аналізує текст у два етапи. На етапі 1 він аналізує текст на різні поля дати та часу залежно від конфігурації. На фазі 2 він перетворює проаналізовані поля в об'єкт дати та / або часу.

Атрибут ResolverStyle керує фазою 2. Це перелік, що має три можливі значення:

  • ПОХІБНИЙ - поблажливо визначає дати та час
  • SMART - розумно визначає дати та час
  • STRICT - строго визначає дати та час

Тепер напишемо перевірку дати безпосередньо за допомогою DateTimeFormatter :

public class DateValidatorUsingDateTimeFormatter implements DateValidator { private DateTimeFormatter dateFormatter; public DateValidatorUsingDateTimeFormatter(DateTimeFormatter dateFormatter) { this.dateFormatter = dateFormatter; } @Override public boolean isValid(String dateStr) { try { this.dateFormatter.parse(dateStr); } catch (DateTimeParseException e) { return false; } return true; } }

Далі додамо модульний тест для цього класу:

DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd", Locale.US) .withResolverStyle(ResolverStyle.STRICT); DateValidator validator = new DateValidatorUsingDateTimeFormatter(dateFormatter); assertTrue(validator.isValid("2019-02-28")); assertFalse(validator.isValid("2019-02-30"));

У наведеному вище тесті ми створюємо DateTimeFormatter на основі шаблону та мови. Ми використовуємо сувору роздільну здатність для дат.

6. Перевірка за допомогою засобу перевірки Apache Commons

Проект Apache Commons забезпечує основу для перевірки. Це містить процедури перевірки, такі як дата, час, цифри, валюта, IP-адреса, електронна пошта та URL-адреса.

Для нашої мети в цій статті давайте розглянемо клас GenericValidator , який надає кілька методів, щоб перевірити, чи містить рядок дійсну дату:

public static boolean isDate(String value, Locale locale) public static boolean isDate(String value,String datePattern, boolean strict)

Щоб скористатися бібліотекою, додамо до нашого проекту спільність-валідатор залежності Maven:

 commons-validator commons-validator 1.6 

Далі, використовуйте клас GenericValidator для перевірки дат:

assertTrue(GenericValidator.isDate("2019-02-28", "yyyy-MM-dd", true)); assertFalse(GenericValidator.isDate("2019-02-29", "yyyy-MM-dd", true));

7. Висновок

У цій статті ми розглянули різні способи перевірити, чи містить рядок дійсну дату.

Як завжди, повний вихідний код можна знайти на GitHub.