Как разобрать дату ISO с точностью до микросекунды в Kotlin

Я получил это от https://stackoverflow.com/a/18217193/6727914

val df1: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
val string1 = "2022-12-29T19:59:20.783357Z"
val result1: Date = df1.parse(string1)

Но это не работает:

Исключение в потоке "основной" java.text.ParseException: неразборчивая дата: «2022-12-29T19:59:20.783357Z» в java.text.DateFormat.parse (:-1)
в FileKt.main (File.kt:13) в FileKt.main (File.kt:-1)

Я не могу использовать Instant.parse(date)

Дата «2022-12-29T19:59:20.783357Z» является допустимой строкой Iso8601, где 783 — миллисекунды, а 357 — микросекунды.

Он не соответствует предоставленному вами формату; непонятно чего вы ожидаете. S для миллисекунд, их 1000 в секунду, и 783357 > 1000.

Dave Newton 29.12.2022 21:07

Вы рассматривали вариант просмотра api.flutter.dev/flutter/dart-core/DateTime/parse.html? Непонятно, почему это помечено как Java/Kotlin, если вы используете ссылки Dart :shrug:

Dave Newton 29.12.2022 21:12

@DaveNewton Заголовок вопроса заключается в том, как анализировать дату ISO в kotlin, поэтому ожидается, что дата будет проанализирована. Указанная дата является действительной датой ISO, не уверен, что непонятно

TSR 29.12.2022 21:13

Самая большая неясность заключается в том, почему микросекунды включены в вашу строку, но полностью отсутствуют в строке формата (я не знаю, обрабатывает ли SDF микросекунды, но строка формата игнорирует их, отсюда и ошибка).

Dave Newton 29.12.2022 21:15

Я не могу использовать Instant.parse(date) Почему бы и нет? SimpleDateFormat не обеспечивает точность в микросекундах.

Sotirios Delimanolis 29.12.2022 21:15

Из-за требования API 26 моему приложению 21 год. Невозможно обновить его из-за различных ограничений.

TSR 29.12.2022 21:16

Таким образом, вам либо не нужно добавлять микросекунды (вам действительно нужна микросекундная «точность»?), либо вам нужно обрабатывать это вручную.

Dave Newton 29.12.2022 21:17

@DaveNewton Мне не нужны микросекунды, но данные поступают из другого приложения, которое генерирует их с помощью встроенной функции языка, которая по умолчанию включает микросекунды, нет возможности исключить это

TSR 29.12.2022 21:19

Тогда вам нужно будет справиться с этим вручную - выдернуть что-нибудь между SSS и последним символом и нормально разобрать, при желании снова заполнив микро?

Dave Newton 29.12.2022 21:22
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
10
98
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

SimpleDateFormat не может обрабатывать доли секунды с разрешением до микросекунд, его предел - разрешение до миллисекунд. Если вы попытаетесь разобрать его как есть, вы получите неверный результат, как описано в этом ответе.

У вас есть два варианта:

  1. Обрезать долю секунды до разрешения в миллисекундах.
  2. Используйте ThreeTenABP или поддержку дешугаринга Android , как описано в этом посте . Затем вы можете использовать Instant#parse, чтобы преобразовать строку даты и времени в Instant.

Примечание. В шаблоне нужно использовать X вместо Z.

Демо:

import java.text.ParseException;
import java.text.SimpleDateFormat;

public class Main {
    public static void main(String[] args) throws ParseException {
        var df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
        var string1 = "2022-12-29T19:59:20.783357Z";
        string1 = string1.replaceAll("(\\.\\d{3})\\d+", "$1");
        var result1 = df1.parse(string1);
        System.out.println(result1);
    }
}

Вывод в моем часовом поясе, Европа/Лондон:

Thu Dec 29 19:59:20 GMT 2022

Решение с использованием API java.time

import java.time.Instant;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        var instant = Instant.parse("2022-12-29T19:59:20.783357Z");
        System.out.println(instant);

        // For any reason, if you need java.util.Date
        var date = Date.from(instant);
        System.out.println(date);
    }
}

ОНЛАЙН ДЕМО

Рекомендуемое решение java.time доступно для уровня API 21 посредством дешугаринга.

Ole V.V. 31.12.2022 09:51

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