Converter string UTC no formato de data

Sep 25 2020

Como converter a string "2020-09-02T12: 22: 53.9" para o formato de data 2020-09-02T12: 22: 53.9 em 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));

Este código lança um java.time.format.DateTimeParseException: Text '2020-09-02T12:22:53.9' could not be parsed at index 21formulário na linha Instant instant = Instant.parse(dateString);.

Respostas

2 LiveandLetLive Sep 25 2020 at 03:11

Seu formato não está correto. Você usou mm, em vez de MM, durante o mês. Além disso, você perdeu o literal Tno formato. Observe que você precisa usar o HHformato de hora de 24 horas.

Uma vez que sua string de data e hora não tem informações de fuso horário, você terá que analisar a string de data e hora para LocalDateTimee, em seguida, LocalDateTime#atZoneconvertê-la para ZonedDateTime(se necessário ZonedDateTime) conforme mostrado abaixo:

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));
    }
}

Resultado:

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

Como alternativa, você pode usar o ZoneIdcom DateTimeFormatterele mesmo e, em seguida, pode analisar a string de data e hora fornecida diretamente em, ZonedDateTimeconforme mostrado abaixo:

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));
    }
}

Resultado:

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

Nenhum formatador necessário

Presumo que sua string de data esteja no fuso horário America / Mexico_City e que você deseja a saída no mesmo fuso horário, portanto, a mesma data e hora. Além disso, considero que, internamente em seu programa, você deseja representar o momento como um Instant. O círculo completo de sua string de data Instante volta pode ir:

    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));

Resultado:

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

Sua entrada e saída idêntica estão no formato ISO 8601. LocalDateTimeanalisa o formato ISO 8601 sem fuso horário ou deslocamento como padrão, ou seja, sem qualquer formatador explícito. Para imprimir o ZonedDateTimeverso no mesmo formato, estamos usando o embutido DateTimeFormatter.ISO_LOCAL_DATE_TIME. Como você já deve ter percebido, ficar livre de especificar nossa própria string de padrão de formato é um grande alívio.

O que deu errado em seu código?

Arvind Kumar Avinash já relatou os erros em sua string de padrão de formato. Mais fundamentalmente, você não pode analisar sua string em um Instant, ou mais precisamente, é necessário algo mais para fazer isso. O motivo é que Java e a Instantclasse não sabem e não podem adivinhar qual fuso horário você pretendia. Sua string de data tem data e hora do dia sem nenhum fuso horário. Um Instanté um ponto no tempo, conceitualmente sem qualquer data ou hora do dia. Sua string pode representar diferentes pontos no tempo em diferentes fusos horários, portanto, somente especificando o fuso horário é possível determinar o ponto no tempo.

O que a Instantclasse pode analisar é uma data e hora em UTC denotadas por a Z. Um exemplo de tal string está na saída Instantacima 2020-09-02T17:22:53.900Z,. Como sua string não está em UTC (e, portanto, não tem o Z), essa observação não nos ajuda no seu caso.

Ligação

  • Artigo da Wikipedia: ISO 8601