Problema de formato de data com DateTimeFormatter [duplicado]

Oct 05 2020

Tenho uma data no seguinte formato: 1/1/2020 3:4:7 AMEstou tentando formatar usando DateTimeFormatter.

Eu tenho o seguinte código com um formatador para analisá-lo, mas não funciona.

LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));

Eu recebo a seguinte exceção:

java.time.format.DateTimeParseException: Text '1/1/2020 3:4:7 AM' could not be parsed at index 0

Alguém pode me ajudar?

Respostas

7 rzwitserloot Oct 05 2020 at 21:07

Dois problemas separados:

Contagens erradas

Você está usando, por exemplo, MMque é um explícito: Sempre a quantidade total de dígitos, preenchido com zeros. Sua string não é assim, é apenas o número. Então, faça isso M/d/uuuu h:m:s a.

EDIT: Alterado yyyypara uuuu, obrigado, @deHaar. Raciocínio: yyyy ou uuuu raramente importa, mas observe que isso significa que são necessários 4 dígitos . A diferença entra em ação anos antes de 0: uuuufica negativo, yyyynão faz e espera que você use, por exemplo, GGpara obter em 44 BCvez de -44. Dessa forma, uuuué apenas mais correto, embora normalmente a diferença não vá aparecer.

Localidade ausente

O segundo problema é que você quase nunca deve usar essa versão do ofPattern- ela tem um bug, que você não consegue detectar com testes de unidade, o que o torna um bug que é milhares de vezes "pesado" e, portanto, um problema real .

Você precisa especificar o local. Sem ele, 'AM' não analisará, a menos que o local padrão da plataforma seja o inglês.

Juntar as peças

LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM",
  DateTimeFormatter.ofPattern("M/d/uuuu h:m:s a", Locale.ENGLISH));

funciona bem.

3 GiorgiTsiklauri Oct 05 2020 at 21:09

Em seu snippet:

LocalDateTime
    .parse("1/1/2020 3:4:7 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));
  • 1 - não corresponde MM
  • 1 - não corresponde dd
  • 3 - não corresponde hh
  • 4 - não corresponde mm
  • 7 - não corresponde ss

ou seja, os comprimentos das partes do padrão do formatador (por exemplo MM) e suas respectivas partes do texto da string (por exemplo 1) não correspondem.

Você pode combiná-los de algumas maneiras, por exemplo, você pode alterar o texto da string para corresponder ao padrão do formatador ou de outra forma.

Você pode tentar isso:

LocalDateTime
    .parse("01/01/2020 03:04:07 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));

Além disso, dê uma olhada nas letras e símbolos de padrão .

3 LiveandLetLive Oct 05 2020 at 21:05
  1. Use letras únicas para componentes de data e hora (mês, dia, ano, hora, minuto e segundo).

  2. Você também pode fazer o formatador lidar com o padrão sem diferenciar maiúsculas de minúsculas (por exemplo, am, AM, Am), conforme mostrado abaixo:

    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.time.format.DateTimeFormatterBuilder;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
             // Formatter to handle the pattern in case insensitive way (e.g. am, AM, Am)
            DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                                                .parseCaseInsensitive()
                                                .appendPattern("M/d/u h:m:s a")
                                                .toFormatter(Locale.ENGLISH);
            LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM", formatter);
            System.out.println(date);
        }
    }
    

Resultado:

2020-01-01T03:04:07
2 0009laH Oct 05 2020 at 21:08

De acordo com a documentação do DateTimeFormatter :

Número: se a contagem de letras for um , o valor será emitido usando o número mínimo de dígitos e sem preenchimento. Caso contrário, a contagem de dígitos é usada como a largura do campo de saída, com o valor preenchido com zeros conforme necessário.

Ao inverter o raciocínio, você pode tentar usar este formatador:

DateTimeFormatter.ofPattern("M/d/yyyy h:m:s a")