web-dev-qa-db-fra.com

Convertir SimpleDateFormat en DateTimeFormatter

Ainsi, lorsque j'ai essayé de remplacer du code hérité à l'aide de SimpleDateFormat et Date, pour utiliser Java.time.DateTimeFormatter et LocalDate, j'ai rencontré un problème. Les deux formats de date ne sont pas équivalents. À ce stade, je dois dire que je sais que les deux types de dates ne sont pas identiques, mais le scénario dans lequel je me trouve signifie que je ne me soucie jamais de l'aspect temporel, je peux donc l'ignorer.

public Date getDate(String value) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
    try {
        return dateFormat.parse(value);
    } catch (ParseException e) {
        return null;
    }
}

public LocalDate getLocalDate(String value) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
    try {
        return LocalDate.parse(value, formatter);
    } catch (DateTimeParseException e) {
        return null;
    }
}

public void testDates() {
    getDate("03/07/2016");               // Sun Jul 03 00:00:00 BST 2016
    getDate("3/7/2016");                 // Sun Jul 03 00:00:00 BST 2016
    getDate("3/7/2016 00:00:00");        // Sun Jul 03 00:00:00 BST 2016
    getDate("3/7/2016 00:00:00.0+0100"); // Sun Jul 03 00:00:00 BST 2016
    getDate("3/7/2016T00:00:00.0+0100"); // Sun Jul 03 00:00:00 BST 2016

    getLocalDate("03/07/2016");               // 2016-07-03
    getLocalDate("3/7/2016");                 // null
    getLocalDate("3/7/2016 00:00:00");        // null
    getLocalDate("3/7/2016 00:00:00.0+0100"); // null
    getLocalDate("3/7/2016T00:00:00.0+0100"); // null
}

Comme vous pouvez le voir lorsque le même modèle est utilisé dans les deux formateurs, DateTimeFormatter finit par produire des valeurs nulles où vous vous attendez à voir des dates équivalentes à celles de SDF. Dans ce scénario, je m'attendrais à ce que les données non requises soient supprimées, mais ce n'est pas le cas.

Alors, comment créer un analyseur date/heure robuste?!

13
Remlap21

Il peut donc y avoir d'autres réponses à cette question, mais ce que j'ai trouvé répond au cas le plus extrême que j'ai. J'ai d'abord réduit dd/MM à d/M. Cela dénote le nombre minimum de caractères attendus et analysera donc parfaitement les doubles chiffres. Notez que vous pouvez également utiliser le nouveau DateTimeFormatterBuilder (). ParseLenient () mais cela semble inutile.

Deuxièmement, j'ai décidé d'utiliser la clause facultative dans le modèle de format lui-même. Cela vous permet de spécifier quelles pièces peuvent ne pas être fournies, ce qui est exactement le cas que j'essayais de résoudre.

Nous laissant avec:

DateTimeFormatter.ofPattern("d/M/yyyy[' ']['T'][H:mm[:ss[.S]]][X]");

Cela permet désormais de fournir une date avec ou sans heure, y compris un séparateur en T, des secondes, des millis et un décalage de zone.

Avec un peu de chance, cela aide quelqu'un d'autre!

private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/yyyy[' ']['T'][H:mm[:ss[.S]]][X]");

public LocalDate getRobustLocalDate(String value) {
    try {
        return LocalDate.parse(value, formatter);
    } catch (DateTimeParseException e) {
        return null;
    }
}

@Test
public void testDates() {
    getRobustLocalDate("03/07/2016");               // 2016-07-03
    getRobustLocalDate("3/7/2016");                 // 2016-07-03
    getRobustLocalDate("3/7/2016 00:00:00");        // 2016-07-03
    getRobustLocalDate("3/7/2016 00:00:00.0+0100"); // 2016-07-03
    getRobustLocalDate("3/7/2016T00:00:00.0+0100"); // 2016-07-03
}
12
Remlap21