2 votes

Dans mon programme, je reçois occasionnellement une ParseException lors de l'utilisation de SimpleDateFormat.parse

Dans mon programme, je reçois de manière aléatoire une ParseException lors de l'exécution de SimpleDateFormat.parse.

J'ai écrit un bolt Apache Storm, dans lequel je parse la date d'entrée "2018-02-26 18:13:32 UTC".

Cette exception n'est pas levée pour chaque date d'entrée. De plus, j'ai imprimé la date d'entrée dans le journal d'erreurs. Visuellement, il n'y a aucun problème avec le format de la date d'entrée.

Mais j'ai reçu la ParseException pour des entrées intermittentes.

Je soupçonne que cela puisse être dû à l'environnement concurrent.

Voici un extrait de code :

utcDateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss 'UTC'");

4voto

zuts Points 47

Je doute que ce soit parce que c'est un environnement concurrent.

En fait, c'est la cause la plus probable, car SimpleDateFormat n'est pas thread safe. Consultez ici une analyse du problème et comment le résoudre : https://www.javaspecialists.eu/archive/Issue172.html

En dehors de cela, "UTC" est une information importante (cela indique que, eh bien, la date est en UTC), donc vous ne pouvez pas la traiter comme une chaîne littérale (entre guillemets). Le formateur que vous avez créé ignore que la date est en UTC (parce qu'entre guillemets, elle est traitée comme "quelque texte", pas comme "elle est en UTC"), donc elle utilise en fait le fuseau horaire par défaut de la JVM (qui n'est pas nécessairement UTC).

Pour analyser correctement UTC, vous devez utiliser le motif z:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
Date date = sdf.parse("2018-02-26 18:13:32 UTC");

Mais si vous utilisez Java 8 ou une version supérieure, utilisez simplement la nouvelle API de date :

DateTimeFormatter fmt = new DateTimeFormatterBuilder()
    // analyse de la date et de l'heure
    .appendPattern("yyyy-MM-dd HH:mm:ss ")
    // analyse de l'UTC
    .appendOffset("+HH:MM", "UTC")
    // créer le formateur
    .toFormatter();
OffsetDateTime odt = OffsetDateTime.parse("2018-02-26 18:13:32 UTC", fmt);

Cela semble plus compliqué au début, mais cette nouvelle API offre de nombreux types de date-heure différents et bien plus d'options pour les analyser et les formater.

Et plus important : elle est thread safe.

MISE À JOUR :

Comme suggéré dans les commentaires, vous pouvez également faire :

DateTimeFormatter fmt  = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss zzz");
ZonedDateTime zdt = ZonedDateTime.parse("2018-02-26 18:13:32 UTC", fmt);

Si vous devez toujours travailler avec java.util.Date, il est facile de convertir :

Date javaUtilDate = Date.from(zdt.toInstant());

La classe OffsetDateTime possède également une méthode toInstant(), donc les deux peuvent être convertis en Date.

1voto

Mike Adamenko Points 2185

SimpleDateFormat n'est pas threadsafe et vous pouvez vraiment obtenir une ParseException dans un environnement concurrent.

Voir ici pour plus de détails.

Pour Java 8, vous pouvez utiliser DateTimeFormatter qui est threadsafe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X