SimpleDateFormat.parse(MM/гггг)

Я пытаюсь реализовать метод, который анализирует String в Date, и я хотел бы использовать SimpleDateFormat, потому что это работает:

java.util.Date parseMonth(String str) throws ParseException {
    SimpleDateFormat format=new SimpleDateFormat("MM/yyyy");
    return format.parse(str);
}

Но по некоторым причинам я не получаю ParseException на входах, где я ожидаю их получить.

  • "00/2000" -> 1999-12-01, без исключений
  • "13/2000" -> 01.01.2001, без исключений

Каков предпочтительный способ проверить, является ли String правильной датой (в отношении некоторого формата, зависящего от реализации)?


person Frank Endriss    schedule 13.03.2018    source источник
comment
На этот вопрос уже был дан ответ здесь: stackoverflow.com/questions/20231539/   -  person Alexander Aurand    schedule 13.03.2018
comment
У каждого свой путь, я предпочитаю валидатор регулярных выражений.   -  person Roman C    schedule 13.03.2018
comment
Я рекомендую вам избегать SimpleDateFormat. Он не только давно устарел, но и заведомо хлопотный. Вместо этого используйте java.time, современный API даты и времени Java. С ним намного приятнее работать. Посмотрите на его классы YearMonth и DateTimeFormatter.   -  person Ole V.V.    schedule 14.03.2018
comment
Дубликат: Как анализировать дату только с месяцем и годом. См. правильный ответ Андреаса с использованием YearMonth.   -  person Basil Bourque    schedule 14.05.2019


Ответы (1)


SimpleDateFormat по умолчанию снисходителен, поэтому он пытается быть умным (обычно терпит неудачу) и делает такие вещи, как "нулевой месяц становится декабрем предыдущего года".

Чтобы недопустимые входные данные вызывали исключение, просто отключите снисходительное поведение:

SimpleDateFormat format = new SimpleDateFormat("MM/yyyy");
format.setLenient(false); // not lenient

Это вызовет ParseException для недопустимых входных данных, таких как 00/2000 и 13/2000.


Но теперь у нас есть лучшие API для этого. Начиная с Java 8 появился новый API даты/времени, а для версий ‹= 7 есть хороший бэкпорт. В этом API форматтеры по умолчанию не снисходительны:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MM/yyyy");
YearMonth.parse("00/2000", fmt); // exception
person diston    schedule 13.03.2018
comment
Почему минус? Разве setLenient не решает проблему? - person diston; 13.03.2018
comment
Я не знаю, так ли это здесь. но некоторые пользователи любят отрицать ответы на вопросы, получившие отрицательные отзывы, и/или дублировать вопросы, чтобы избежать слишком большого количества таких вопросов. Это хороший ответ. Кто-то все еще может возразить, что лучше оставить ответы там, где находится первоначальный вопрос. - person Ole V.V.; 14.03.2018