Java 8 необязательная часть времени не работает

Я пытаюсь создать формат даты для дополнительной части времени, в настоящее время я реализовал это

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.text.ParseException;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        System.out.println(Ideone.getDate("2017-07-01T00:00:00.0Z"));
        System.out.println(Ideone.getDate("2017-07-01T00:00:00.00Z"));
        System.out.println(Ideone.getDate("2017-07-01T00:00:00.000Z"));
    }

    public static LocalDateTime getDate(String date) {
        try {

            DateTimeFormatter formatter2 =
                DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS]'Z'");
            LocalDateTime ldt = LocalDateTime.parse(date, formatter2);


            return ldt;

        } catch (DateTimeParseException ex) {
            return null;
        }
    }
}

И имея вывод

null

2017-07-01T00: 00

2017-07-01T00: 00

Теперь мой вопрос: почему дата с 1 временной долей не работает и работает с 2 и 3 фракциями? должен ли он принимать 1,2 и 3 фракции? или только 3 фракции?

Заранее спасибо

Ответ 1

Это похоже на ошибку. Миллисекундная часть синтаксиса datetime, по-видимому, вообще не работает в Java 8, см. эту проблему и ее дубликаты.

Соответствующая цитата:

Хуже всего то, что шаблон SSS, таким образом, строгий режим, когда режим смягчения был бы уместным. В настоящее время стенды, DateTimeFormatter.ofPattern( "hhmmss.SSS" ) требует трех цифр за миллисекунды, когда изначально предполагалось, что требуется 0 до 9 (мягкое поведение).

Учитывая, что текущая реализация требует трех цифр для SSS, поэтому очень удивительно, что смешение парциального значения не применяется.

Но вы, кажется, нашли случай, когда указанное выше требование не применяется. Кроме того, хотя проблема выше в состоянии "исправлена", ваш пример, похоже, имеет проблемы как в java 8, так и в java 9: ​​

>java -version
java version "9"
Java(TM) SE Runtime Environment (build 9+181)
Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)

>javac Ideone.java

>java Ideone
null
2017-07-01T00:00
2017-07-01T00:00

>"c:\Program Files\Java\jdk1.8.0\bin"\javac Ideone.java

>"c:\Program Files\Java\jdk1.8.0\bin"\java Ideone
null
2017-07-01T00:00
2017-07-01T00:00

если он содержит 1,2 и 3 фракции? или только 3 фракции?

Основываясь на цитате, она должна быть только 3, хотя первоначально она должна была быть 0-9.

Ответ 2

Причина, по которой вы получаете null, когда вы передаете это,

"2017-07-01T00: 00: 00.0Z"

вы сказали парсеру ожидать 3 char формата (см. ниже .SSS)

DateTimeFormatter.ofPattern( "YYYY-MM-dd'T'HH: мм: сс [.SSS] 'Z'" );

Если вы измените его на .SS, он должен работать, однако ваш последний вход, т.е. 2017-07-01T00: 00: 00.000Z, сломается. Вы можете включить некоторую логику для обработки различных форматов.

Ответ 3

Я думаю, что вы хотите DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS][.S]'Z'")

В основном это говорит, чтобы сначала проверить длинную форму 2 + цифр в секунду, иначе, если это необязательное поле отсутствует, проверьте для необязательного поля одну дробную цифру, указанную [.S]