Преобразование строковой даты UTC в формат даты

Sep 25 2020

Как преобразовать строку «2020-09-02T12: 22: 53.9» в формат даты 2020-09-02T12: 22: 53.9 в java?

String dateString = "2020-09-02T12:22:53.9";
String tz = "America/Mexico_City";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-mm hh:mm:ss.S");
ZoneId zoneId = ZoneId.of(tz);
Instant instant = Instant.parse(dateString);
ZonedDateTime dateTimeInTz =ZonedDateTime.ofInstant(instant, zoneId);
System.out.println(dateTimeInTz.format(dtf));

Этот код создает java.time.format.DateTimeParseException: Text '2020-09-02T12:22:53.9' could not be parsed at index 21строку Instant instant = Instant.parse(dateString);.

Ответы

2 LiveandLetLive Sep 25 2020 at 03:11

Ваш формат неверен. Вы использовали mmвместо этого MMза месяц. Кроме того, вы пропустили литерал Tв формате. Обратите внимание, что вам нужно использовать время HHв 24-часовом формате.

Поскольку ваша строка даты и времени не содержит информации о часовом поясе, вам нужно будет проанализировать строку даты и времени, LocalDateTimeа затем использовать ее LocalDateTime#atZoneдля преобразования ZonedDateTime(если это вообще необходимо ZonedDateTime), как показано ниже:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String dateString = "2020-09-02T12:22:53.9";

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM'T'HH:mm:ss.S");

        String tz = "America/Mexico_City";
        ZoneId zoneId = ZoneId.of(tz);

        // Parse the given date-time string to LocalDateTime
        LocalDateTime ldt = LocalDateTime.parse(dateString, dtf);

        // Convert the LocalDateTime to ZonedDateTime
        ZonedDateTime dateTimeInTz = ldt.atZone(zoneId);

        // Display ZonedDateTime in its default format
        System.out.println(dateTimeInTz);

        // Display ZonedDateTime in your custom format
        System.out.println(dateTimeInTz.format(dtf));
    }
}

Вывод:

2020-02-09T12:22:53.900-06:00[America/Mexico_City]
2020-09-02T12:22:53.9

В качестве альтернативы вы можете использовать ZoneIdс DateTimeFormatterсамим собой, а затем вы можете проанализировать данную строку даты и времени непосредственно, ZonedDateTimeкак показано ниже:

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String dateString = "2020-09-02T12:22:53.9";

        String tz = "America/Mexico_City";
        ZoneId zoneId = ZoneId.of(tz);

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-dd-MM'T'HH:mm:ss.S").withZone(ZoneId.of(tz));

        // Parse the given date-time string into ZonedDateTime
        ZonedDateTime dateTimeInTz = ZonedDateTime.parse(dateString, dtf);

        // Display ZonedDateTime in its default format
        System.out.println(dateTimeInTz);

        // Display ZonedDateTime in your custom format
        System.out.println(dateTimeInTz.format(dtf));
    }
}

Вывод:

2020-02-09T12:22:53.900-06:00[America/Mexico_City]
2020-09-02T12:22:53.9
1 OleV.V. Sep 25 2020 at 07:16

Форматер не нужен

Я полагаю, что ваша строка даты находится в часовом поясе America / Mexico_City и что вы хотите выводить в том же часовом поясе, поэтому те же дата и время. Я также считаю, что внутри вашей программы вы хотите представить момент времени как файл Instant. Полный круг от строки даты до Instantи обратно может идти:

    String tz = "America/Mexico_City";
    ZoneId zoneId = ZoneId.of(tz);
    
    String dateString = "2020-09-02T12:22:53.9";
    
    Instant instant = LocalDateTime.parse(dateString).atZone(zoneId).toInstant();
    System.out.println(instant);
    
    ZonedDateTime dateTimeInTz =ZonedDateTime.ofInstant(instant, zoneId);
    System.out.println(dateTimeInTz.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

Вывод:

2020-09-02T17:22:53.900Z
2020-09-02T12:22:53.9

Ваш ввод и ваш идентичный вывод находятся в формате ISO 8601. LocalDateTimeанализирует формат ISO 8601 без часового пояса или смещения по умолчанию, то есть без явного средства форматирования. Для печати ZonedDateTimeобратной стороны в том же формате мы используем встроенный DateTimeFormatter.ISO_LOCAL_DATE_TIME. Как вы, возможно, уже поняли, отсутствие необходимости указывать нашу собственную строку шаблона формата является большим облегчением.

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

Арвинд Кумар Авинаш уже сообщил об ошибках в строке шаблона формата. Более фундаментально, вы не можете разобрать свою строку на Instant, или, точнее, для этого требуется нечто большее. Причина в том, что Java и Instantкласс не знают и не могут угадать, какой часовой пояс вы намеревались. В строке даты указаны дата и время дня без часового пояса. An Instant- это момент времени, концептуально не имеющий даты или времени суток. Ваша строка может представлять разные моменты времени в разных часовых поясах, поэтому, только указав часовой пояс, можно определить момент времени.

То , что Instantкласс может разобрать это дата и время в формате UTC обозначается через а Z. Пример такой строки в выходе из Instantвыше, 2020-09-02T17:22:53.900Z. Поскольку ваша строка не находится в формате UTC (и, следовательно, не имеет Z), это наблюдение не поможет нам в вашем случае.

Ссылка

  • Статья в Википедии: ISO 8601