Length of arbitrary parsing length String with DateTimeFormatter

I am trying to parse a date string of (almost) arbitrary length. The approach I had with SimpleDateFormat was something like this

private Date parseWithSimpleDateFormat(String dateString) throws ParseException {
    String pattern = "yyyyMMddHHmmss".substring(0, dateString.length());
    SimpleDateFormat format = new SimpleDateFormat(pattern);
    return format.parse(dateString);
}

... which I want to do "better" with the new Date API. I came up with the following:

private static final DateTimeFormatter FLEXIBLE_FORMATTER = new DateTimeFormatterBuilder()
    .appendPattern("yyyy[MM[dd[HH[mm[ss]]]]]")
    .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
    .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
    .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
    .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
    .toFormatter();

private Date parseWithDateTimeFormatter(String dateString) {
    LocalDateTime localDateTime = LocalDateTime.parse(dateString, FLEXIBLE_FORMATTER);
    ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
    Instant instant = zonedDateTime.toInstant();
    return Date.from(instant);
}

with the following result

parseWithDateTimeFormatter("2016"); // works as intended
parseWithDateTimeFormatter("201605"); // Text '201605' could not be parsed at index 0
parseWithDateTimeFormatter("20160504"); // Text '20160504' could not be parsed at index 0
parseWithDateTimeFormatter("2016050416"); // Text '2016050416' could not be parsed at index 0
parseWithDateTimeFormatter("201605041636"); // Text '201605041636' could not be parsed at index 0

What am I doing wrong here, or how will I further eliminate this?

+4
source share
1 answer

You can use this modified formatter to avoid parsing more than 4 digits per year:

private static final DateTimeFormatter FLEXIBLE_FORMATTER =
    new DateTimeFormatterBuilder()
    .appendValue(ChronoField.YEAR, 4)
    .appendPattern("[MM[dd[HH[mm[ss]]]]]")
    .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
    .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
    .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
    .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
    .toFormatter();

Unlike other fields, such as month (MM), etc., the symbol for the year y field has no four-digit limit, as indicated by the number of y-letters.

+4
source

Source: https://habr.com/ru/post/1660527/


All Articles