JSR-310 - парная секундная секция с переменной длиной

Есть ли способ создания форматирования JSR-310, который способен анализировать обе следующие даты/времени с переменной длиной в секцию секунд?

2015-05-07 13:20:22.276052

или

2015-05-07 13:20:22.276

Пример кода:

DateTimeFormatter formatter
= new java.time.format.DateTimeFormatterBuilder()
        .append( java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") )
        .appendOptional( java.time.format.DateTimeFormatter.ofPattern(".SSSSSS") )
        .toFormatter();
formatter.parse("2015-05-07 13:20:22.276052", LocalDateTime::from);

Ответы

Ответ 1

Это решает проблему:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .appendPattern("yyyy-MM-dd HH:mm:ss")
    .appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
    .toFormatter();

System.out.println(LocalDateTime.parse("2015-05-07 13:20:22.276052", formatter));
System.out.println(LocalDateTime.parse("2015-05-07 13:20:22.276", formatter));
System.out.println(LocalDateTime.parse("2015-05-07 13:20:22", formatter));

// output
2015-05-07T13:20:22.276052
2015-05-07T13:20:22.276
2015-05-07T13:20:22

Ответ JiriS неверен, поскольку он использует appendValue, тогда как правильный способ - использовать DateTimeFormatterBuilder.appendFraction (который также обрабатывает десятичную точку). Разницу можно увидеть во второй системе, где appendValue неправильно анализирует "2015-05-07T13: 20: 22.000276".

При синтаксическом анализе LocalDateTime.parse(str, formatter) используется более аккуратный подход, чем использование форматера непосредственно в большинстве случаев.

При использовании builder воспользуйтесь appendPattern() и optionalStart(), чтобы все было в порядке.

Ответ 2

И этот работает

DateTimeFormatter formatter
= new java.time.format.DateTimeFormatterBuilder()
        .append( java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") )
        .appendOptional(
                new java.time.format.DateTimeFormatterBuilder()
                    .appendLiteral('.')
                    .appendValue( ChronoField.MICRO_OF_SECOND, 1, 6, SignStyle.NOT_NEGATIVE).toFormatter())
        .toFormatter();