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

Как преобразовать строку "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 ответа

Ваш формат неправильный. Вы использовали 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

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

Я полагаю, что ваша строка даты находится в часовом поясе 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), это наблюдение не поможет нам в вашем случае.

Ссылка

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