Problème de format de date avec DateTimeFormatter [duplicate]

Oct 05 2020

J'ai une date au format suivant: 1/1/2020 3:4:7 AMj'essaye de la formater en utilisant DateTimeFormatter.

J'ai le code suivant avec un formateur pour l'analyser, mais cela ne fonctionne pas.

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

J'obtiens l'exception suivante:

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

Quelqu'un peut-il m'aider?

Réponses

7 rzwitserloot Oct 05 2020 at 21:07

Deux problèmes distincts:

Mauvais comptes

Vous utilisez par exemple MMce qui est explicite: toujours le nombre total de chiffres, complété par des zéros. Votre chaîne n'est pas comme ça, c'est juste le nombre. Alors, faites ça M/d/uuuu h:m:s a.

EDIT: Changé yyyyen uuuu, merci, @deHaar. Raisonnement: yyyy ou uuuu compte rarement, mais notez que cela signifie que 4 chiffres sont requis . La différence entre en jeu pendant des années avant 0: uuuudevient négatif, yyyyne le fait pas et s'attend à GGce que vous l'utilisiez, par exemple, pour obtenir la 44 BCplace de -44. De cette façon, uuuuc'est juste plus correct, même si généralement la différence ne se fera pas.

Paramètres régionaux manquants

Le deuxième problème est que vous ne devriez pratiquement jamais utiliser cette version de ofPattern- il y a un bogue, que vous ne pouvez pas attraper avec les tests unitaires, ce qui en fait un bogue des milliers de fois `` plus lourd '', et donc, un vrai problème .

Vous devez spécifier les paramètres régionaux. Sans cela, «AM» ne sera pas analysé à moins que la langue par défaut de votre plate-forme soit l'anglais.

Mettre ensemble

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

fonctionne très bien.

3 GiorgiTsiklauri Oct 05 2020 at 21:09

Dans votre extrait:

LocalDateTime
    .parse("1/1/2020 3:4:7 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));
  • 1 - ne correspond pas MM
  • 1 - ne correspond pas dd
  • 3 - ne correspond pas hh
  • 4 - ne correspond pas mm
  • 7 - ne correspond pas ss

c'est-à-dire que les longueurs des parties de motif du formateur (par exemple MM) et leurs parties respectives du texte de chaîne (par exemple 1) ne correspondent pas.

Vous pouvez les faire correspondre de plusieurs façons, par exemple, vous pouvez soit changer le texte de la chaîne pour qu'il corresponde au modèle du formateur, soit autrement.

Vous pouvez essayer ceci à la place:

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

De plus, jetez un œil aux lettres et symboles du modèle .

3 LiveandLetLive Oct 05 2020 at 21:05
  1. Utilisez des lettres uniques pour les composants de date et d'heure (mois, jour, année, heure, minute et seconde).

  2. Vous pouvez également faire en sorte que le formateur gère le motif d'une manière insensible à la casse (par exemple, am, AM, Am) comme indiqué ci-dessous:

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

Production:

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

Selon la documentation de DateTimeFormatter :

Nombre: si le nombre de lettres est égal à un , la valeur est sortie en utilisant le nombre minimum de chiffres et sans remplissage. Sinon, le nombre de chiffres est utilisé comme largeur du champ de sortie, avec la valeur complétée par zéro si nécessaire.

En inversant le raisonnement, vous pouvez essayer d'utiliser ce formateur à la place:

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