Перейти к основному содержимому

Проверьте, является ли строка действительной датой в Java

· 4 мин. чтения

1. Обзор

В этом руководстве мы обсудим различные способы проверки того, содержит ли строка допустимую дату в Java.

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

2. Обзор проверки даты

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

В случае ввода даты нам может потребоваться проверить следующее:

  • Входные данные содержат дату в допустимом формате, например, ММ/ДД/ГГГГ.
  • Различные части ввода находятся в допустимом диапазоне.
  • Ввод преобразуется в допустимую дату в календаре.

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

Мы обсудим различные способы гибкой, надежной и эффективной реализации проверки даты.

Во-первых, давайте напишем интерфейс для проверки даты:

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

В следующих разделах мы реализуем этот интерфейс, используя различные подходы.

3. Проверка с использованием DateFormat

Java с самого начала предоставляла средства для форматирования и анализа дат. Этот функционал находится в абстрактном классе DateFormat и его реализации — SimpleDateFormat .

Давайте реализуем проверку даты с помощью метода parse класса 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

Давайте используем метод parse для реализации проверки даты:

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. Это перечисление с тремя возможными значениями:

  • LENIENT – снисходительно разрешает дату и время
  • 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 Validator

Проект Apache Commons предоставляет платформу проверки. Он содержит процедуры проверки, такие как дата, время, числа, валюта, IP-адрес, адрес электронной почты и URL-адрес.

В этой статье давайте взглянем на класс GenericValidator , который предоставляет пару методов для проверки того, содержит ли строка допустимую дату:

public static boolean isDate(String value, Locale locale)

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

Чтобы использовать библиотеку, давайте добавим в наш проект зависимость commons-validator Maven:

<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.6</version>
</dependency>

Далее воспользуемся классом GenericValidator для проверки дат:

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

7. Заключение

В этой статье мы рассмотрели различные способы проверки того, содержит ли строка допустимую дату.

Как обычно, полный исходный код можно найти на GitHub .