Existe-t-il un moyen agréable et facile de convertir une date Java Date au format de chaîne de date XML et vice versa?
À votre santé,
Andez
Je suppose ici que par "format de date XML", vous voulez dire quelque chose comme "2010-11-04T19: 14Z". Il s'agit en fait du format ISO 8601 .
Vous pouvez le convertir en utilisant SimpleDateFormat, comme d'autres l'ont suggéré, FastDateFormat ou en utilisant Joda Time qui a été, je crois, spécialement créé pour cet objectif .
Comme Earnshae a déclaré dans un commentaire, cette réponse pourrait être améliorée avec des exemples.
Tout d'abord, nous devons préciser que la réponse originale est assez dépassée. C'est parce que Java 8 a introduit les classes pour manipuler la date et l'heure - le package _Java.time
_ devrait être intéressant. Si vous avez la chance d'utiliser Java 8, vous devez en utiliser un. Cependant, ces choses sont étonnamment difficiles à obtenir correctement.
Considérez cet exemple:
_LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T18:21");
System.out.println(dateTime); // 2016-03-23T18:21
_
Au début, il peut sembler que ce que nous utilisons ici est un local (à la date et à l'heure de l'utilisateur). Cependant, si vous osez demander, vous obtiendrez un résultat différent:
_System.out.println(dateTime.getChronology()); // ISO
_
En fait, le temps ISO. Je crois qu'il devrait lire "UTC" mais néanmoins cela n'a aucune notion de fuseau horaire local. Nous devons donc le considérer comme universel.
Veuillez noter qu'il n'y a pas de "Z" à la fin de la chaîne que nous analysons. Si vous ajoutez autre chose que la date et l'heure, vous serez accueilli avec _Java.time.format.DateTimeParseException
_. Il semble donc que cette classe ne soit d'aucune utilité si nous voulons analyser la chaîne ISO8601.
Heureusement, il existe une classe qui permet d'analyser les chaînes ISO8601 - c'est un Java.time.ZonedDateTime .
_ZonedDateTime zonedDateTime = ZonedDateTime.parse("2016-03-23T18:21+01:00");
System.out.println(zonedDateTime); // 2016-03-23T18:21+01:00
ZonedDateTime zonedDateTimeZulu = ZonedDateTime.parse("2016-03-23T18:21Z");
System.out.println(zonedDateTimeZulu); // 2016-03-23T18:21Z
_
Le seul problème ici est que vous devez réellement utiliser la désignation de fuseau horaire. Essayer d'analyser l'heure de la date brute (c'est-à-dire "2016-03-23T18: 21") entraînera déjà RuntimeException
déjà mentionné. Selon la situation, vous devrez choisir entre LocalDateTime
et ZonedDateTime
.
Bien sûr, vous pouvez facilement convertir entre ces deux, donc cela ne devrait pas être un problème:
_System.out.println(zonedDateTimeZulu.toLocalDateTime()); // 2016-03-23T18:21
// Zone conversion
ZonedDateTime cetDateTime = zonedDateTimeZulu.toLocalDateTime()
.atZone(ZoneId.of("CET"));
System.out.println(cetDateTime); // 2016-03-23T18:21+01:00[CET]
_
Je recommande d'utiliser ces cours de nos jours. Cependant, si votre description de poste inclut l'archéologie (ce qui signifie que vous n'avez pas la chance de travailler avec des Java 8 ans de plus de 2 ans), vous devrez peut-être utiliser autre chose.
Je ne suis pas un très grand fan de https://docs.Oracle.com/javase/8/docs/api/Java/text/SimpleDateFormat.html, mais parfois vous n'avez tout simplement pas d'autre choix. Le problème est qu'il n'est pas sûr pour les threads et il vous enverra un Exception
vérifié (à savoir ParseException
) en face s'il n'aime pas quelque chose. Par conséquent, l'extrait de code est plutôt moche:
_private Object lock = new Object();
// ...
try {
synchronized (lock) {
// Either "2016-03-23T18:21+01:00" or "2016-03-23T18:21Z"
// will be correctly parsed (mind the different meaning though)
Date date = dateFormat.parse("2016-03-23T18:21Z");
System.out.println(date); // Wed Mar 23 19:21:00 CET 2016
}
} catch (ParseException e) {
LOG.error("Date time parsing exception", e);
}
_
FastDateFormat
est synchronisé, vous pouvez donc au moins vous débarrasser du bloc synchronisé. Il s'agit cependant d'une dépendance externe. Mais puisque c'est le Apache Commons Lang et qu'il est bien utilisé, je suppose que c'est acceptable. Son utilisation est en fait très similaire à SimpleDateFormat
:
_FastDateFormat fastDateFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mmX");
try {
Date fastDate = fastDateFormat.parse("2016-03-23T18:21+01:00");
System.out.println(fastDate);
} catch (ParseException e) {
LOG.error("Date time parsing exception", e);
}
_
Avec Joda-Time, vous pouvez penser que les travaux suivants fonctionnent:
_DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser();
LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T20:48+01:00", parser);
System.out.println(dateTime); // 2016-03-23T20:48:00.000
_
Malheureusement, peu importe ce que vous mettez à la dernière position (Z, +03: 00, ...) le résultat sera le même. De toute évidence, cela ne fonctionne pas.
Eh bien, vous devriez vraiment l'analyser directement:
_DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser();
DateTime dateTime = parser.parseDateTime("2016-03-23T21:12:23+04:00");
System.out.println(dateTime); // 2016-03-23T18:12:23.000+01:00
_
Maintenant ça va aller. Veuillez noter que contrairement à l'une des autres réponses, j'ai utilisé dateTimeParser()
et pasdateTime()
. J'ai remarqué une différence de comportement subtile mais importante entre eux (Joda-Time 2.9.2). Mais, je laisse au lecteur le soin de le tester et de le confirmer.
Comme déjà suggéré, utilisez SimpleDateFormat.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
String date = sdf.format(new Date());
System.out.println(date);
Date d = sdf.parse(date);
Je suppose que le format/modèle que vous recherchez est yyyy-MM-dd'T'HH:mm:ss
Jetez également un œil à http://www.w3schools.com/schema/schema_dtypes_date.asp
En utilisant Joda Time vous feriez ce qui suit:
DateTimeFormatter fmt = ISODateTimeFormat.dateTime(); // ISO8601 (XML) Date/time
DateTime dt = fmt.parseDateTime("2000-01-01T12:00:00+100"); // +1hr time zone
System.out.println(fmt.print(dt)); // Prints in ISO8601 format
Fil sûr, immuable et simple.
La méthode parfaite, utilisez XMLGregorianCalendar:
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(v);
DatatypeFactory df = DatatypeFactory.newInstance();
XMLGregorianCalendar dateTime = df.newXMLGregorianCalendar(calendar);
return dateTime.toString();
En utilisant simplement SimpleDateFormat dans Java nous pouvons le faire ...
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date date = sdf.parse("2011-12-31T15:05:50+1000");
Je recommanderais d'utiliser le Java construit dans la classe javax.xml.bind.DatatypeConverter . Il peut gérer la conversion vers et à partir de la plupart des types simples xml. Il est un peu lourd pour les dates que vous devez passer par un objet Calendar
mais d'un autre côté, il gère toutes les variantes des informations de zone qui peuvent se produire dans un champ xml datetime
.
De xml:
Calendar c = DatatypeConverter.parseDateTime("2015-10-21T13:25");
Date d = c.getTime();
Vers xml:
Date yourDate = new Date()
Calendar c = Calendar.getInstance();
c.setTime(yourDate);
String xmlDateTime = DatatypeConverter.printDateTime(c);
[~ # ~] modifier [~ # ~]
La classe DatatypeConverter n'est plus visible publiquement dans Java 9 et plus car elle appartient au package javax.xml.bind. Voir cette question pour plus d'informations) informations et solutions possibles. La solution proposée par loic vaugeois pour utiliser XmlGregorianCalendar est bien meilleure dans ce cas.
Vous pouvez analyser et formater des dates vers et depuis n'importe quel format en utilisant SimpleDateFormat
Pour se conformer à ISO8601, le fuseau horaire doit être au format + HH: MM ou - HH: MM
Avec Simpledateformat, vous devez utiliser XXX au lieu de Z (voir la réponse de NovelGuy)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
Sans savoir exactement de quel format vous avez besoin, la réponse générique est: vous allez vouloir DateFormat ou SimpleDateFormat. Il y a un joli tutoriel sur les deux ici .