анализ DateTime с помощью ThreetenBp вызывает исключение DateTimeParseException или ошибку неполной строки

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

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

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 ответ

Решение

Вам не нужен явный форматировщик. На 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 по умолчанию, то есть без указания какого-либо средства форматирования.

Поскольку строка с вашего сервера имеет смещение по всемирному координированному времени, +00:00 и не имеет часового пояса, например Asia/Seoul, 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);

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

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

Ссылки

Другие вопросы по тегам