Разбор DateTime с ThreetenBp вызывает исключение DateTimeParseException или неполную строку - PullRequest
0 голосов
/ 04 мая 2020

Я пытаюсь проверить, прошла ли дата более одного дня или нет.

И я получил эти ошибки, пока он анализирует строку.

java.lang.IllegalArgumentException: Pattern ends with an incomplete string literal: uuuu-MM-dd'T'HH:mm:ss'Z
org.threeten.bp.format.DateTimeParseException: Text '2020-04-04T07:05:57+00:00' could not be parsed, unparsed text found at index 19

Мой Вот пример данных:

val lastDate = "2020-04-04T07:05:57+00:00"
val serverFormat = "uuuu-MM-dd'T'HH:mm:ss'Z"
val serverFormatter =
        DateTimeFormatter
            .ofPattern(serverFormat)
val serverDateTime =
        LocalDateTime
            .parse(
                lastDate,
                serverFormatter
            )
            .atZone(ZoneId.of("GMT"))
val clientDateTime =
        serverDateTime
            .withZoneSameInstant(ZoneId.systemDefault())

val timeDiff =
        ChronoUnit.DAYS.between(
            serverDateTime,
            clientDateTime

Я пробовал с этим:

uuuu-MM-dd\'T\'HH:mm:ss\'Z
yyyy-MM-dd\'T\'HH:mm:ss\'Z
uuuu-MM-dd\'T\'HH:mm:ss
uuuu-MM-dd'T'HH:mm:ss'Z
yyyy-MM-dd'T'HH:mm:ss'Z
uuuu-MM-dd'T'hh:mm:ss'Z
yyyy-MM-dd'T'hh:mm:ss'Z
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd HH:mm:ssZ
yyyy-MM-dd'T'HH:mm:ss
yyyy-MM-dd'T'HH:mm:ssZ
yyyy-MM-dd'T'HH:mm:ss

И ни один из них не сработал ... Как правильно?

1 Ответ

1 голос
/ 05 мая 2020

Вам не нужен явный форматер. В Java (потому что это то, что я могу написать):

    String lastDate = "2020-04-04T07:05:57+00:00";
    OffsetDateTime serverDateTime = OffsetDateTime.parse(lastDate);
    ZonedDateTime clientDateTime
            = serverDateTime.atZoneSameInstant(ZoneId.systemDefault());

    System.out.println("serverDateTime: " + serverDateTime);
    System.out.println("clientDateTime: " + clientDateTime);

Вывод в моем часовом поясе:

serverDateTime: 2020-04-04T07:05:57Z
clientDateTime: 2020-04-04T09:05:57+02:00[Europe/Copenhagen]

Формат строки из вашего сервером является ISO 8601. Классы java .time анализируют наиболее распространенные варианты ISO 8601 как их значения по умолчанию, то есть без указания какого-либо форматера.

Поскольку строка на вашем сервере имеет UT C смещение, +00: 00 и отсутствие часового пояса, как в Азии / Сеуле, OffsetDateTime - лучшее и наиболее правильное время для него. С другой стороны, время клиента имеет часовой пояс, поэтому ZonedDateTime здесь хорошо.

Поскольку время сервера и клиента обозначают одно и то же время, разница всегда будет равна нулю:

    Duration difference = Duration.between(serverDateTime, clientDateTime);
    System.out.println(difference);
PT0S

Читается как период времени 0 секунд (это тоже формат ISO 8601).

Если вы хотите узнать разницу между текущим временем и сервером время, используйте now():

    Duration difference = Duration.between(serverDateTime, OffsetDateTime.now());
    System.out.println(difference);

Что пошло не так в вашем коде?

Во-первых, смещение UT C в вашей строке равно +00:00. Ни одна буква шаблона формата Z, ни литерал Z не будут соответствовать этому. Так что не пытайся. Во-вторых, никогда дает Z как литерал, заключенный в одинарные кавычки в строке шаблона формата. Когда Z отображается как смещение, что является обычным явлением, вам необходимо проанализировать его как смещение, а не как литерал. В-третьих, буквенный текст в строке шаблона формата должен иметь одинарную кавычку до и одну кавычку после него. Вы делаете это правильно для T в середине. Если вы не хотели Z быть буквальным, не ставьте перед ним ни одной кавычки. Если вы действительно подразумеваете, что это буквально - как я уже сказал, просто не надо.

Ссылки

...