Разобрать строку до даты определенного формата

У меня есть строка следующего формата String stringDate = "2019-04-25T07:03:17.428Z"; и мне нужно преобразовать его в объект LocalDateTime формата 2019-04-2507:03:17

Я пробовал с LocalDateTime.parse(stringDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) но я получаю это исключение синтаксического анализа:

      Exception in thread "main" java.time.format.DateTimeParseException: Text '2019-04-25T07:03:17.428Z' could not be parsed at index 10
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
    at com.company.Main.main(Main.java:12)

Каким будет способ конвертировать в конкретный формат?

3 ответа

Решение

Что вы просили (но не хотите)

          String stringDate = "2019-04-25T07:03:17.428Z";
    LocalDateTime ldt = LocalDateTime.parse(stringDate, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
            .truncatedTo(ChronoUnit.SECONDS);
    System.out.println(ldt);

Выход

2019-04-25T07:03:17

Он дает вам то, что вы сказали, что хотели, но, как указывает rzwitserloot в другом ответе , это не имеет смысла. Он игнорирует смещение Zэто было в твоей строке. Смещение имеет решающее значение для интерпретации даты и времени как момента времени. Если бы строка была 2019-04-25T07:03:17.428+13:00 вместо этого вы все равно получите тот же результат, даже если строка обозначает момент времени на 13 часов раньше.

Призыв к truncatedTo()избавляется от доли секунды. Если вы можете жить с этой долей секунды, опустите этот призыв.

Что вы можете захотеть вместо этого

Для более разумного преобразования:

          ZoneId zone = ZoneId.of("Europe/Zagreb");
    
    Instant pointInTime = Instant.parse(stringDate);
    LocalDateTime ldt = pointInTime.atZone(zone)
            .toLocalDateTime()
            .truncatedTo(ChronoUnit.SECONDS);

    System.out.format("Date and time in %s: %s%n", zone, ldt);

Дата и время в Европе / Загребе: 2019-04-25T09:03:17

Теперь время 07:03 UTC было преобразовано в 09:03 Центральноевропейского летнего времени.

Изменить: если вам действительно нужен LocalDateTime в UTC, например, для столбца базы данных, требующего этого, вы можете сделать этот факт явным в своем коде следующим образом:

          LocalDateTime ldt = pointInTime.atOffset(ZoneOffset.UTC)
            .toLocalDateTime()
            .truncatedTo(ChronoUnit.SECONDS);

    System.out.format("Date and time in UTC: %s%n", ldt);

Дата и время в UTC: 2019-04-25T07: 03: 17

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

Чтобы понять, что для вас не удалось, давайте посмотрим на полученное вами сообщение об исключении:

Текст '2019-04-25T07: 03: 17.428Z' не удалось проанализировать в индексе 10

Индекс 10 - это то место, где находится начало временной части. Давайте сравним с вашей строкой шаблона формата: yyyy-MM-dd HH:mm:ss. Перед временной частью стоит пробел. Это было причиной исключения. Если вам нужно было указать в шаблоне, что T должен быть там, нам нужно будет заключить его в одинарные кавычки, например yyyy-MM-dd'T'HH:mm:ss.

Ваш вклад, по сути, не является LDT. Это ZDT - Z - это зона (ZonedDateTime). Таким образом, невозможно преобразовать эту строку напрямую в LDT, и это хорошо, потому что это не имеет смысла.

Преобразуйте его в ZDT. Затем преобразуйте это в LDT. Это вызов одного метода.

Вы можете сначала проанализировать его с помощью java.time.Instant, а затем использовать метод ofInstant из примера java.time.LocalDateTime :

      String stringDate = "2019-04-25T07:03:17.428Z";
var instant = Instant.parse(stringDate);
var localDateTime = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
Другие вопросы по тегам