Changer le format de date dans une chaîne en Java

Convertir une date stockée dans une chaîne vers un autre format (20/04/20262026-04-20, ou Apr 20, 202620 avril 2026) est l'un des besoins les plus fréquents en Java. La méthode moderne tient en deux étapes : parser puis reformater.

Principe général

  1. Déclarer un DateTimeFormatter pour le format d'entrée.
  2. parse() la chaîne en LocalDate (ou LocalDateTime).
  3. Déclarer un autre DateTimeFormatter pour le format de sortie.
  4. format() la date obtenue.

Exemple de base

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

String entree = "20/04/2026";

DateTimeFormatter formatEntree = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date = LocalDate.parse(entree, formatEntree);

DateTimeFormatter formatSortie = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String sortie = date.format(formatSortie);

System.out.println(sortie); // 2026-04-20

Formats courants

FormatExemple
dd/MM/yyyy20/04/2026
yyyy-MM-dd2026-04-20 (ISO)
MM-dd-yyyy04-20-2026 (US)
d MMMM yyyy20 avril 2026
EEEE, d MMMM yyyylundi, 20 avril 2026
dd/MM/yyyy HH:mm20/04/2026 14:35

Gérer la locale

Pour afficher les noms de mois ou de jour dans une langue précise, précisez la locale :

import java.util.Locale;

DateTimeFormatter fr = DateTimeFormatter.ofPattern("EEEE d MMMM yyyy", Locale.FRANCE);
DateTimeFormatter en = DateTimeFormatter.ofPattern("EEEE, MMMM d, yyyy", Locale.US);

System.out.println(LocalDate.now().format(fr));  // lundi 20 avril 2026
System.out.println(LocalDate.now().format(en));  // Monday, April 20, 2026

Sans locale, le formatteur utilise celle de la JVM, qui varie entre machines — cause fréquente de bugs en production.

Formats ISO prédéfinis

Pas besoin de réinventer les patterns ISO :

DateTimeFormatter.ISO_LOCAL_DATE           // 2026-04-20
DateTimeFormatter.ISO_LOCAL_DATE_TIME      // 2026-04-20T14:35:12
DateTimeFormatter.ISO_OFFSET_DATE_TIME     // 2026-04-20T14:35:12+02:00
DateTimeFormatter.ISO_INSTANT              // 2026-04-20T12:35:12Z

Inclure l'heure

Pour une date-heure complète, utilisez LocalDateTime au lieu de LocalDate :

import java.time.LocalDateTime;

String entree = "2026-04-20 14:35:12";
DateTimeFormatter formatEntree = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime date = LocalDateTime.parse(entree, formatEntree);

DateTimeFormatter formatSortie = DateTimeFormatter.ofPattern("EEEE d MMMM yyyy 'à' HH'h'mm", Locale.FRANCE);
System.out.println(date.format(formatSortie));
// lundi 20 avril 2026 à 14h35

Gérer les fuseaux horaires

Si votre chaîne inclut un fuseau, utilisez ZonedDateTime ou OffsetDateTime :

import java.time.*;

String entree = "2026-04-20T14:35:12+02:00";
OffsetDateTime odt = OffsetDateTime.parse(entree); // ISO automatique

ZonedDateTime zdt = odt.atZoneSameInstant(ZoneId.of("America/New_York"));
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm zzz", Locale.US);
System.out.println(zdt.format(f));
// 2026-04-20 08:35 EDT

Parser des formats multiples

Quand les données d'entrée peuvent arriver dans plusieurs formats, essayez-les en chaîne :

public static LocalDate parseTolerant(String entree) {
    DateTimeFormatter[] formats = {
        DateTimeFormatter.ofPattern("yyyy-MM-dd"),
        DateTimeFormatter.ofPattern("dd/MM/yyyy"),
        DateTimeFormatter.ofPattern("MM-dd-yyyy"),
        DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.FRANCE)
    };
    for (DateTimeFormatter f : formats) {
        try { return LocalDate.parse(entree, f); }
        catch (java.time.format.DateTimeParseException ignored) { }
    }
    throw new IllegalArgumentException("Format de date inconnu : " + entree);
}

Gérer les erreurs de parsing

try {
    LocalDate date = LocalDate.parse("20-04-2026", formatEntree);
} catch (java.time.format.DateTimeParseException e) {
    System.err.println("Format invalide : " + e.getMessage());
    System.err.println("Position : " + e.getErrorIndex());
}

L'ancienne API (à éviter)

Pour du code legacy qui utilise SimpleDateFormat :

import java.text.SimpleDateFormat;
import java.util.Date;

SimpleDateFormat entree = new SimpleDateFormat("dd/MM/yyyy");
Date date = entree.parse("20/04/2026");

SimpleDateFormat sortie = new SimpleDateFormat("yyyy-MM-dd");
String resultat = sortie.format(date);

SimpleDateFormat n'est pas thread-safe. Créez une nouvelle instance à chaque appel, ou utilisez un ThreadLocal. Pour tout code moderne, DateTimeFormatter est la voie à suivre : immuable, thread-safe et plus expressive.

Pièges fréquents

  • Confondre yyyy et YYYY : YYYY est l'année ISO-semaine, pas l'année calendaire. Utilisez toujours yyyy.
  • Confondre MM (mois) et mm (minutes).
  • Oublier la locale pour les formats avec noms de mois/jour.
  • Utiliser LocalDateTime quand la chaîne contient un fuseau — perte d'information.

Avec DateTimeFormatter, la conversion d'une chaîne datée d'un format à un autre se fait en deux lignes, claires et sûres.