Skip to content
Advertisement

Create a DateTimeFormater with an Optional Section at Beginning

I have timecodes with this structure hh:mm:ss.SSS for which i have a own Class, implementing the Temporal Interface. It has the custom Field TimecodeHour Field allowing values greater than 23 for hour. I want to parse with DateTimeFormatter. The hour value is optional (can be omitted, and hours can be greater than 24); as RegEx (d*dd:)?dd:dd.ddd

For the purpose of this Question my custom Field can be replaced with the normal HOUR_OF_DAY Field.

My current Formatter

DateTimeFormatter UNLIMITED_HOURS = new DateTimeFormatterBuilder()
    .appendValue(ChronoField.HOUR_OF_DAY, 2, 2,SignStyle.NEVER)
    .appendLiteral(':')
    .parseDefaulting(TimecodeHour.HOUR, 0)
    .toFormatter(Locale.ENGLISH);
DateTimeFormatter TIMECODE = new DateTimeFormatterBuilder()
    .appendOptional(UNLIMITED_HOURS)
    .appendValue(MINUTE_OF_HOUR, 2)
    .appendLiteral(':')
    .appendValue(SECOND_OF_MINUTE, 2)
    .appendFraction(MILLI_OF_SECOND, 3, 3, true)
    .toFormatter(Locale.ENGLISH);

Timecodes with a hour value parse as expected, but values with hours omittet throw an Exception

java.time.format.DateTimeParseException: Text '20:33.123' could not be parsed at index 5

I assume, as hour and minute have the same pattern, the parser starts at front and captures the minute value for the optional section. Is this right, and how can solve this?

Advertisement

Answer

Try with two optional parts (one with hours, other without) like in:

var formatter = new DateTimeFormatterBuilder()
    .optionalStart()
      .appendValue(HOUR_OF_DAY, 2, 4, SignStyle.NEVER).appendLiteral(":")
      .appendValue(MINUTE_OF_HOUR, 2).appendLiteral(":")
      .appendValue(SECOND_OF_MINUTE, 2)
    .optionalEnd()
    .optionalStart()
      .parseDefaulting(HOUR_OF_DAY, 0)
      .appendValue(MINUTE_OF_HOUR, 2).appendLiteral(":")
      .appendValue(SECOND_OF_MINUTE, 2)
    .optionalEnd()
    .toFormatter(Locale.ENGLISH);

I do not know about TimecodeHour, so I used HOUR_OF_DAY to test
(also too lazy to include fractions)

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement