Checking string and handling invalid date

Angelina :

When I come across invalid dates, i.e. 2018-02-31, 2018-11-31, I want my code to convert it to last day of that month.

I am not sure how to check for value within the passed string.

Here is my code so far:

/**
     * 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;
    }
Ole V.V. :

The parseUnresolved method of a DatetimeFormatter parses without trying to make sense of the parsed values. It therefore accepts an invalid date and allows you to inspect the parsed values before you try to make a LocalDate out of them.

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);
    }
}

Let’s try this version of your method out:

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

Output is:

2018-02-28
2018-02-27

So February 31 was invalid and has been adjusted into February 28, which in 2018 was the last day of that month. February 27 is valid and is returned as is.

Edit: For a related purpose one might have considered the much easier DateTimeFormatter.ISO_LOCAL_DATE.withResolverStyle(ResolverStyle.LENIENT).parse(nextFieldTypeDate, LocalDate::from). This, however, turns 2018-02-31 into 2018-03-03, which I understand is not what you want.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=91782&siteId=1