Java 8 LocalDateTime обрабатывает недопустимую дату

Я хотел проверить дату на стороне клиента, поэтому я написал следующий код. Но вместо получения исключения я получаю правильный объект даты для строки даты 31-го февраля, что явно недействительная дата.

public class Test { public static void main(String[] args) { String dateFormat = "HH:mm:ss MM/dd/yyyy"; String dateString = "11:30:59 02/31/2015"; DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US); try { LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter); System.out.println(date); } catch (Exception e) { // Throw invalid date message } } } 

Результат : 2015-02-28T11: 30: 59

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

Вам просто нужен строгий ResolverStyle .

Разбор текстовой строки происходит в два этапа. Фаза 1 представляет собой основной синтаксический анализ текста в соответствии с полями, добавленными к строителю. Фаза 2 разрешает проанализированные пары значений поля в дату и / или временные объекты. Этот стиль используется для контроля того, как происходит этап 2, разрешая его.

Пример кода – где с withResolverStyle(ResolverStyle.STRICT) – важное изменение, наряду с использованием uuuu а не yyyy (где uuuu – «год», а «yyyy» – «год эры» и, следовательно, неоднозначный):

 import java.time.*; import java.time.format.*; import java.util.*; public class Test { public static void main(String[] args) { String dateFormat = "HH:mm:ss MM/dd/uuuu"; String dateString = "11:30:59 02/31/2015"; DateTimeFormatter dateTimeFormatter = DateTimeFormatter .ofPattern(dateFormat, Locale.US) .withResolverStyle(ResolverStyle.STRICT); try { LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter); System.out.println(date); } catch (DateTimeParseException e) { // Throw invalid date message System.out.println("Exception was thrown"); } } } 

Java 8 DateTimeFormatter использует yyyy для обозначения YEAR_OF_ERA, а uuuu означает YEAR. Вам необходимо изменить строку шаблона следующим образом:

 String dateFormat = "HH:mm:ss MM/dd/uuuu"; 

DateTimeFormatter по умолчанию использует стиль распознавателя SMART, но вы хотите, чтобы он использовал стиль распознавателя STRICT. Измените код инициализации dateTimeFormatter следующим образом:

 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US) .withResolverStyle(ResolverStyle.STRICT); 

Это не округление. В феврале никогда не было 31 дня, и невозможно использовать проверяющий объект даты / времени для представления дня, который не существует.

В результате он принимает неверный ввод и дает наилучшее приближение к правильной дате (последняя дата февраля того же года).

SimpleDateFormat наследует от DateFormat который имеет setLenient(boolean value) . Я ожидал бы, что, если вы вызвали setLenient(true) перед синтаксическим parsingом, он, вероятно, будет жаловаться больше, как описано в javadocs .

 try { SimpleDateFormat df = new java.text.SimpleDateFormat("HH:mm:ss MM/dd/yyyy"); df.setLenient(false); System.out.println(df.parse("11:30:59 02/29/2015")); } catch (java.text.ParseException e) { System.out.println(e); } 

Я нашел одно решение распознать дату как действительную дату с DateFormat.setLenient (boolean) . Если вы попытаетесь разобрать любую недействительную дату, она выдает исключение синтаксического анализа.

Редактировать:

Java 8 , но это вызовет исключение, если месяц не находится между 1 и 12 , если день больше 32 . Точно не работает. Но за месяц его работала.

 try { TemporalAccessor ta = DateTimeFormatter.ofPattern("HH:mm:ss MM/dd/yyyy").parse("11:30:59 02/32/2015"); } catch (Exception e) { System.out.println(e); } 

Вывод:

 java.time.format.DateTimeParseException: Text '11:30:59 02/32/2015' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32 

LocalDateTime.parse будет выдавать ошибку только в том случае, если строка, содержащаяся в ней, содержит недопустимые символы, количество дней, превышающее 31 или месяц, превышающее 12.

Например, если вы изменили код как таковой:

 String dateString = "11:30:59 0zz2/31/2015"; 

исключение будет вызвано недействительными символами «zz» в течение указанной даты. Что касается того, почему это «округление» даты так сказать, что я не знаю.

Источник: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#parse-java.lang.CharSequence-

  • Сеанс даты и времени для языка Java
  • Преобразование относительного пути в абсолютный URL с помощью PHP
  • Эффективность анализа (если, TryParse, Try-Catch)
  • Проблема parsingа текста валюты на десятичный тип
  • Ошибка анализатора Antlr 4.5 во время выполнения
  • Как анализировать даты в нескольких форматах с помощью SimpleDateFormat
  • Использование ANTLR 3.3?
  • Как преобразовать строку C ++ в int?
  • Более безопасная, но простая в использовании и гибкая альтернатива C ++ для s ++ ()
  • Получить и проанализировать CSV-файл в android
  • Parse цитирует строки с boost :: spirit
  • Давайте будем гением компьютера.