How to parse datetime with optional sections?

2020-03-08 07:10发布

问题:

I've datetime that may be one of the following formats:

  • MM/dd/yy
  • M/dd/yy
  • MM/d/yy
  • M/d/yy
  • Any of the above with HH:mm
  • Any of the above with 4-digit year

The DateTimeFormatter I built is as follows:

new DateTimeFormatterBuilder()
    .appendValue(ChronoField.MONTH_OF_YEAR, 1, 2, SignStyle.NEVER)
    .appendLiteral('/')
    .appendValue(ChronoField.DAY_OF_MONTH, 1, 2, SignStyle.NEVER)
    .appendLiteral('/')
    .appendValue(ChronoField.YEAR_OF_ERA, 2, 4, SignStyle.NEVER)
    .optionalStart()
    .appendLiteral(' ')
    .appendValue(HOUR_OF_DAY, 2)
    .appendLiteral(':')
    .appendValue(MINUTE_OF_HOUR, 2)
    .toFormatter();

But it fails to format 2/9/17. Why?

回答1:

This works:

new DateTimeFormatterBuilder()
    .appendValue(ChronoField.MONTH_OF_YEAR, 1, 2, SignStyle.NEVER)
    .appendLiteral('/')
    .appendValue(ChronoField.DAY_OF_MONTH, 1, 2, SignStyle.NEVER)
    .appendLiteral('/')
    .appendValueReduced(ChronoField.YEAR, 2, 4, yearMonth.getYear())
    .appendPattern("[ HH:mm]")
    .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
    .toFormatter();

The error I posted in response to Meno Hochschild's comment is fixed by setting defaults for the optional hours and minutes.