Все мы сталкивались с ситуациями, когда нам приходилось анализировать пользовательский ввод для проверки. Другие поля, такие как текстовые или числовые, довольно просты, но проверка даты Java немного сложна, и небольшая ошибка может оставить приложение в нестабильном состоянии.
1. Проверка даты Java с помощью SimpleDateFormat.parse()
Обычно для проверки используется метод SimpleDateFormat.parse(). Если метод parse() способен разобрать дату, то считается, что ввод действителен. Ну, может быть и неверным.
частная статическая конечная строка DATE_PATTERN = "MM/dd/yyyy";SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN);//Мягкое преобразование приводит к неожиданному результатуДата d = sdf.parse("2012/12/17");System.out.println(d);
Вывод программы:
Wed Aug 12 00:00:00 GMT+05:30 184
1.1 Что пошло не так?
Вышеуказанная проверка даты странная по двум причинам. Во-первых, она должна была пометить ошибку проверки, а во-вторых, полученный объект даты совершенно бесполезен. Так что же здесь пошло не так?
Ну, ошибка в логике разбора. Метод parse() использует позиции ключевых слов шаблона в DATE_PATTERN и использует их для разбора входной строки. По умолчанию он не является разумным, чтобы использовать правильные символы для разбора, и он использует то, что попадается ему на пути(даже слеши).
2. Правильный способ проверки даты с помощью SimpleDateFormat.setLenient()
Решение заключается в использовании метода SimpleDateFormat.setLenient() для получения недостающего интеллекта. Посмотрите на пример строгой проверки даты, приведенный ниже:
частная статическая конечная строка DATE_PATTERN = "MM/dd/yyyy";SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN);sdf.setLenient(false);//Мягкое преобразование приводит к неожиданному результатуДата d = sdf.parse("2012/12/17");System.out.println(d);
Вывод программы.
java.text.ParseException: Unparseable date: "2012/12/17"at java.text.DateFormat.parse(DateFormat.java:337)at com.howtodoinjava.dateTest.TestSetLenient.main(TestSetLenient.java:33)
Таким образом, четкая установка setLenient(false); корректирует поведение анализа SimpleDateFormat.
Мы можем проверить правильность синтаксического анализа, передав допустимую дату в требуемом шаблоне.
private static final String DATE_PATTERN = "MM/dd/yyyy";SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN);sdf.setLenient(false);//Lenient conversion result in unexpected outputDate d = sdf.parse("12/17/2012");System.out.println(d);
Вывод программы.
Mon Dec 17 00:00:00 GMT+05:30 2012
3. Поведение снисходительности по умолчанию в классе Calendar
Источник – http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html
Класс Calendar имеет два режима интерпретации полей календаря: снисходительный и не снисходительный. Когда календарь находится в снисходительном режиме, он принимает более широкий диапазон значений полей календаря, чем он производит. Когда календарь пересчитывает значения полей для возврата get(), все поля календаря нормализуются.
Например, мягкий григорианский календарь интерпретирует «МЕСЯЦ = ЯНВАРЬ и ДЕНЬ_МЕСЯЦА = 32» как 1 февраля, что неверно.
Когда Calendar находится в не-уступчивом режиме, он выдает исключение, если в его полях календаря есть какие-либо несоответствия. Например, GregorianCalendar всегда выдает значения DAY_OF_MONTH между 1 и длиной месяца. Не-уступчивый GregorianCalendar выдает исключение при вычислении значений полей времени или календаря, если было установлено какое-либо значение поля, выходящее за пределы диапазона.
По умолчанию установлен мягкий режим.
В этом примере проверки даты Java мы узнали, как преобразовать строку в определенный формат даты в Java. И не сработать для других шаблонов даты.