Проверка строки и обработка недопустимой даты

Когда я сталкиваюсь с недопустимыми датами, например 2018-02-31, 2018-11-31, я хочу, чтобы мой код преобразовал их в последний день этого месяца.

Я не уверен, как проверить значение в переданной строке.

Вот мой код:

/**
     * If date comes back as invalid, i.e. 2018-11-31
     * convert it to have last day of given month.
     *  
     * @param nextFieldTypeDate
     * @return
     */
    public static LocalDate resolveInvalidDate(String nextFieldTypeDate) {
        LocalDate convertedDate = null;
        try {
            convertedDate = LocalDate.parse(nextFieldTypeDate);
        } catch(DateTimeException dte) {
            //convertedDate = convert date to have last day of the month
            DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM");
            String yearMonthString = nextFieldTypeDate.subSequence(0, 7).toString();
            YearMonth ym = YearMonth.parse(yearMonthString, fmt);
            convertedDate = ym.atEndOfMonth();
        } catch(Exception e) {
            logger.error(e.getMessage());
            throw new ConversionException("Unable to convert nextFieldTypeDate.", e);
        }
        return convertedDate;
    }
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
0
505
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Метод parseUnresolved в DatetimeFormatter выполняет синтаксический анализ, не пытаясь понять анализируемые значения. Поэтому он принимает недопустимую дату и позволяет вам проверить проанализированные значения, прежде чем вы попытаетесь сделать из них LocalDate.

public static LocalDate resolveInvalidDate(String nextFieldTypeDate) {
    ParsePosition position = new ParsePosition(0);
    TemporalAccessor parsed = DateTimeFormatter.ISO_LOCAL_DATE
            .parseUnresolved(nextFieldTypeDate, position);
    if (position.getIndex() < nextFieldTypeDate.length()) {
        throw new IllegalArgumentException("Could not parse entire string");
    }
    YearMonth ym = YearMonth.from(parsed);
    int lastDayOfMonth = ym.lengthOfMonth();
    int parsedDayOfMOnth = parsed.get(ChronoField.DAY_OF_MONTH);
    if (parsedDayOfMOnth > lastDayOfMonth) { // invalid, must be adjusted to lasst day of month
        return ym.atEndOfMonth();
    } else {
        return ym.atDay(parsedDayOfMOnth);
    }
}

Давайте попробуем эту версию вашего метода:

    System.out.println(resolveInvalidDate("2018-02-31"));
    System.out.println(resolveInvalidDate("2018-02-27"));

Выход:

2018-02-28
2018-02-27

Таким образом, 31 февраля было недействительным и было изменено на 28 февраля, которое в 2018 году было последним днем ​​этого месяца. 27 февраля действительно и возвращается как есть.

Редактировать: Для связанных целей можно было бы рассмотреть намного более простой DateTimeFormatter.ISO_LOCAL_DATE.withResolverStyle(ResolverStyle.LENIENT).parse(nextFieldTypeDate, LocalDate::from). Это, однако, превращает 2018-02-31 в 2018-03-03, что, как я понимаю, не то, что вам нужно.

когда я прохожу 2018-14-25, он взрывается на YearMonth ym = YearMonth.from (разобранный);

Angelina 10.01.2019 14:11

Оно делает. Вы хотите, чтобы 14 было уменьшено до 12? Вы можете добавить это к своему вопросу.

Ole V.V. 10.01.2019 15:30

Нет. Я поместил его в try-catch и генерирую исключение, если указан недопустимый месяц.

Angelina 10.01.2019 15:33

Не самое чистое решение, но оно должно работать:

public static LocalDate resolveInvalidDate(String nextFieldTypeDate) {
        LocalDate convertedDate = null;
        try {
            convertedDate = LocalDate.parse(nextFieldTypeDate);
        } catch(DateTimeException dte) {
            //convertedDate = convert date to have last day of the month
            Integer[] constituents = Arrays.stream(nextFieldTypeDate.split("-"))
                                           .map(constituentString -> Integer.valueOf(constituentString))
                                           .toArray(Integer::new);
            LocalDate defaultDate = LocalDate.of(constituents[0], constituents[1], 1);
            LocalDate convertedDate = LocalDate.of(defaultDate.getYear(), defaultDate.getMonth(), defaultDate.lengthOfMonth());
        } catch(Exception e) {
            logger.error(e.getMessage());
            throw new ConversionException("Unable to convert nextFieldTypeDate.", e);
        }
        return convertedDate;
    }

Другие вопросы по теме