Exception если в List есть противоречивая дата. Java
У меня есть List<Date>, с датами в формате d/MMMM/yyyy, их нужно обработать, и если есть противоречивая дата(дней больше чем должно быть в месяце), то должно выбрасываться исключение.
То есть, если есть:
31/February/2021
То должно выбрасываться исключение. Аргументы метода - строки с годом, днем и месяцев из определенной даты. Вот мой код.
public static boolean checkIfIncorrect(String year, String day, String month) throws ParseException {
int year2 = Integer.parseInt(year);
int day2 = Integer.parseInt(day);
Date date = new SimpleDateFormat("MMMM", Locale.ENGLISH).parse(month);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int month2 = cal.get(Calendar.MONTH);
Calendar calendar = new GregorianCalendar(year2, month2, day2);
int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
if (day2 > daysInMonth) {
//Тут должно быть выбрасывание ошибки
System.out.println("Столько дней в дате: " + day2);
System.out.println("А столько должно быть в дате: " + daysInMonth);
} else {
System.out.println("Все хорошо, кол-во дней в дате не превышает возможное");
}
return true;
}
```
Ответы (2 шт):
А в чём вопрос? в месте где у вас написано "//Тут должно быть выбрасывание ошибки" бросайте исключение:
throw new ParseException();
точнее после вывода сообщений в консоль.
Поскольку в прошлом вопросе использовалось Stream API, а значит, как минимум Java 8, то и для работы с датами следует применять Java Date/Time API (вводная статья на Medium).
Касаемо формулировки задачи:
У меня есть
List<Date>, с датами в форматеd/MMMM/yyyy, их нужно обработать, и если есть противоречивая дата(дней больше чем должно быть в месяце), то должно выбрасываться исключение. То есть, если есть:31/February/2021То должно выбрасываться исключение.
На самом деле, на входе задан список строк List<String> в определённом формате, которые нужно распарсить и превратить в список дат.
Для парсинга даты в заданном формате существует класс DateTimeFormatter, для которого понадобится установить строгий режим определения даты из строки ResolverStyle.STRICT, тогда в случае некорректной даты будет выбрасываться требуемое исключение DateTimeParseException. Нужно отметить, что это исключение не является checked, и может поэтому использоваться в Stream API.
Также результат можно отсортировать по порядку месяцев, как в прошлом вопросе.
Следует отметить, что yyyy в Java 8 означает год с учётом эры, а простой год обозначается в формате как uuuu.
Поэтому можно либо создать простой форматтер, использующий год uuuu
private static final DateTimeFormatter dMMMMuuuu = DateTimeFormatter
.ofPattern("d/MMMM/uuuu", Locale.US)
.withResolverStyle(ResolverStyle.STRICT);
либо (если очень нужен формат yyyy), использовать DateTimeFormatterBuilder, в котором установить "нашу эру" по умолчанию:
private static final DateTimeFormatter dMMMMyyyy = new DateTimeFormatterBuilder()
.appendPattern("d/MMMM/yyyy")
.parseDefaulting(ChronoField.ERA, 1) // н.э. / AD
.toFormatter(Locale.US)
.withResolverStyle(ResolverStyle.STRICT);
public static List<LocalDate> getLocalDateList(List<String> formattedDates) {
return formattedDates.stream()
.map(fd -> LocalDate.parse(fd, dMMMMyyyy))
.sorted(Comparator.comparingInt(LocalDate::getMonthValue)
.thenComparingInt(LocalDate::getYear))
.collect(Collectors.toList());
}
Тесты:
System.out.println(getLocalDateList(Arrays.asList("30/April/1990", "29/February/2020", "31/February/2000")));
Exception in thread "main" java.time.format.DateTimeParseException: Text '31/February/2000' could not be parsed: Invalid date 'FEBRUARY 31'
at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:2023)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1958)
at java.base/java.time.LocalDate.parse(LocalDate.java:430)
at MyClass.lambda$getLocalDateList$0(MyClass.java:14)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at MyClass.getLocalDateList(MyClass.java:17)
at MyClass.main(MyClass.java:30)
Caused by: java.time.DateTimeException: Invalid date 'FEBRUARY 31'
at java.base/java.time.LocalDate.create(LocalDate.java:461)
at java.base/java.time.LocalDate.of(LocalDate.java:273)
...
Для корректных данных (которые снова форматируются для вывода в исходном формате):
getLocalDateList(Arrays.asList(
"4/February/2020", "25/May/2021", "8/September/2009",
"6/February/1990", "11/April/2012", "30/August/2011"
)).stream().map(dMMMMyyyy::format).forEach(System.out::println);
результат будет таким
6/February/1990
4/February/2020
11/April/2012
25/May/2021
30/August/2011
8/September/2009
Следует заметить, что в строгом режиме названия месяцев должны быть написаны с большой буквы (остальные буквы -- строчные).