使用DateTimeFormatter解析任意长度的日期字符串

时间:2016-11-11 16:56:18

标签: date java-8

我试图解析(几乎)任意长度的日期字符串。我使用SimpleDateFormat的方法是这样的

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

...我想做的事情"更好"使用新的Date API。我提出的是以下

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

具有以下结果

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

我在这里做错了什么,或者我将如何进一步解决这个问题?

1 个答案:

答案 0 :(得分:4)

您可以使用此修改后的格式化程序,以避免解析年度超过4位数字:

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

与月份(MM)等其他字段相比,年份字段符号y对四位数没有限制,如y字母数所示。