FYI: Ces deux classes terribles ont été remplacées il y a des années par les classes java.time définies dans JSR 310. Voir la ZonedDateTimeclasse et de nouvelles méthodes de conversion ajoutées aux classes héritées. Détails dans cette réponse par Ole VV
Basil Bourque
Réponses:
36
Je voudrais prendre du recul et un regard moderne sur cette question vieille de 10 ans. Les classes mentionnées Dateet XMLGregorianCalendarsont désormais anciennes. Je conteste leur utilisation et propose des alternatives.
Datea toujours été mal conçu et a plus de 20 ans. C'est simple: ne l'utilisez pas.
XMLGregorianCalendarest vieux aussi et a un design à l'ancienne. Si je comprends bien, il a été utilisé pour produire des dates et des heures au format XML pour les documents XML. Comme 2009-05-07T19:05:45.678+02:00ou 2009-05-07T17:05:45.678Z. Ces formats concordent assez bien avec ISO 8601 pour que les classes de java.time, l'API moderne de date et d'heure Java, puissent les produire, ce que nous préférons.
Aucune conversion nécessaire
À de nombreuses fins (la plupart?), Le remplacement moderne d'un Datesera un Instant. An Instantest un point dans le temps (tout comme un Dateest).
C'est le même que le dernier de mes exemples de XMLGregorianCalendarchaînes ci-dessus. Comme la plupart d'entre vous le savent, cela vient du Instant.toStringfait d' être implicitement appelé par System.out.println. Avec java.time, dans de nombreux cas , nous ne devons pas les conversions dans les vieux jours que nous avons fait entre Date, Calendar, XMLGregorianCalendaret d' autres classes (dans certains cas , nous faisons des conversions de besoin, cependant, je vous montre un couple dans la section suivante) .
Contrôle du décalage
Ni a Dateni in Instantn'ont de fuseau horaire ni de décalage UTC. La réponse précédemment acceptée et toujours la plus votée par Ben Noland utilise le fuseau horaire par défaut actuel des JVM pour sélectionner le décalage du XMLGregorianCalendar. Pour inclure un décalage dans un objet moderne, nous utilisons un OffsetDateTime. Par exemple:
ZoneId zone =ZoneId.of("America/Asuncion");OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();System.out.println(dateTime);
2009-05-07T13: 05: 45.678-04: 00
Encore une fois, cela est conforme au format XML. Si vous souhaitez réutiliser le paramètre de fuseau horaire JVM actuel, définissez zonesur ZoneId.systemDefault().
Et si j'ai absolument besoin d'un XMLGregorianCalendar?
Il existe plusieurs façons de convertir Instanten XMLGregorianCalendar. J'en présenterai un couple, chacun avec ses avantages et ses inconvénients. Tout d'abord, tout comme un XMLGregorianCalendarproduit une chaîne comme 2009-05-07T17:05:45.678Z, il peut également être construit à partir d'une telle chaîne:
Pro: c'est court et je ne pense pas que ça donne de surprises. Inconvénient: Pour moi, cela ressemble à un gaspillage formatant l'instant en une chaîne et l'analysant en retour.
ZonedDateTime dateTime = yourInstant.atZone(zone);GregorianCalendar c =GregorianCalendar.from(dateTime);XMLGregorianCalendar date2 =DatatypeFactory.newInstance().newXMLGregorianCalendar(c);System.out.println(date2);
2009-05-07T13: 05: 45.678-04: 00
Pro: C'est la conversion officielle. Le contrôle du décalage vient naturellement. Inconvénient: il passe par plusieurs étapes et est donc plus long.
Et si on avait un rendez-vous?
Si vous avez obtenu un Dateobjet à l' ancienne d'une API héritée que vous ne pouvez pas vous permettre de changer pour l'instant, convertissez-le en Instant:
Instant i = yourDate.toInstant();System.out.println(i);
La sortie est la même qu'avant:
2009-05-07T17: 05: 45.678Z
Si vous souhaitez contrôler le décalage, convertissez-le en un OffsetDateTimede la même manière que ci-dessus.
Si vous avez un ancien Dateet avez absolument besoin d'un ancien XMLGregorianCalendar, utilisez simplement la réponse de Ben Noland.
Est-il possible de conserver getInstance () en tant que variable statique dans une classe de convertisseur? J'ai essayé de le rechercher dans le JavaDoc mais je n'ai rien trouvé. Difficile de savoir s'il y aura des problèmes d'utilisation simultanée?
Martin
36
Si vous souhaitez utiliser JodaTime, vous pouvez le faire sur une seule ligne: DatatypeFactory.newInstance (). NewXMLGregorianCalendar (new DateTime (). ToGregorianCalendar ())
Voici une méthode de conversion d'un GregorianCalendar en XMLGregorianCalendar; Je vais laisser la partie de la conversion d'un java.util.Date à GregorianCalendar comme un exercice pour vous:
Je pensais simplement ajouter ma solution ci-dessous, car les réponses ci-dessus ne répondaient pas exactement à mes besoins. Mon schéma Xml nécessitait des éléments de date et d'heure séparés, pas un champ DateTime unique. Le constructeur XMLGregorianCalendar standard utilisé ci-dessus générera un champ DateTime
Notez-y quelques gothca, comme devoir en ajouter un au mois (car java compte des mois à partir de 0).
J'espère que mon encodage ici est correct; D Pour le rendre plus rapide, il suffit d'utiliser l'appel laid getInstance () de GregorianCalendar au lieu de l'appel du constructeur:
import java.util.GregorianCalendar;import javax.xml.datatype.DatatypeFactory;import javax.xml.datatype.XMLGregorianCalendar;publicclassDateTest{publicstaticvoid main(finalString[] args)throwsException{// do not forget the type cast :/GregorianCalendar gcal =(GregorianCalendar)GregorianCalendar.getInstance();XMLGregorianCalendar xgcal =DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);System.out.println(xgcal);}}
-1 pour utiliser .getInstance (). GregorianCalendar.getInstance()est l'équivalent de Calendar.getInstance(). Le Calendar.getInstance()ne peut pas le rendre plus rapide, car il utilise le même new GregorianCalendar(), mais avant de vérifier également les paramètres régionaux par défaut et pourrait créer un calendrier japonais ou bouddish à la place, donc pour certains utilisateurs chanceux, ce sera le cas ClassCastException!
kan
6
En supposant que vous JAXBdécodez ou encodez du XML et que vous l'utilisez , il est alors possible de remplacer entièrement la liaison dateTime et d'utiliser autre chose que `XMLGregorianCalendar 'pour chaque date du schéma.
De cette façon, vous pouvez avoir JAXB faire des choses répétitives pendant que vous pouvez passer du temps à écrire du code génial qui offre de la valeur.
Exemple pour un jodatime DateTime: (Faire cela avec java.util.Date fonctionnerait également - mais avec certaines limitations. Je préfère le jodatime et il est copié à partir de mon code, donc je sais que cela fonctionne ...)
Si vous êtes heureux de simplement mapper à un instant basé sur le fuseau horaire + horodatage et que le fuseau horaire d'origine n'est pas vraiment pertinent, alors java.util.Datec'est probablement bien aussi.
Je ne pense pas que cette réponse n'apporte rien de nouveau. Vous pouvez peut-être modifier la réponse précédente au lieu d'en poster une autre presque la même.
hiver
1
Comment faire un format de date pour XMLGregorianCalendar?
ZonedDateTime
classe et de nouvelles méthodes de conversion ajoutées aux classes héritées. Détails dans cette réponse par Ole VVRéponses:
Je voudrais prendre du recul et un regard moderne sur cette question vieille de 10 ans. Les classes mentionnées
Date
etXMLGregorianCalendar
sont désormais anciennes. Je conteste leur utilisation et propose des alternatives.Date
a toujours été mal conçu et a plus de 20 ans. C'est simple: ne l'utilisez pas.XMLGregorianCalendar
est vieux aussi et a un design à l'ancienne. Si je comprends bien, il a été utilisé pour produire des dates et des heures au format XML pour les documents XML. Comme2009-05-07T19:05:45.678+02:00
ou2009-05-07T17:05:45.678Z
. Ces formats concordent assez bien avec ISO 8601 pour que les classes de java.time, l'API moderne de date et d'heure Java, puissent les produire, ce que nous préférons.Aucune conversion nécessaire
À de nombreuses fins (la plupart?), Le remplacement moderne d'un
Date
sera unInstant
. AnInstant
est un point dans le temps (tout comme unDate
est).Un exemple de sortie de cet extrait:
C'est le même que le dernier de mes exemples de
XMLGregorianCalendar
chaînes ci-dessus. Comme la plupart d'entre vous le savent, cela vient duInstant.toString
fait d' être implicitement appelé parSystem.out.println
. Avec java.time, dans de nombreux cas , nous ne devons pas les conversions dans les vieux jours que nous avons fait entreDate
,Calendar
,XMLGregorianCalendar
et d' autres classes (dans certains cas , nous faisons des conversions de besoin, cependant, je vous montre un couple dans la section suivante) .Contrôle du décalage
Ni a
Date
ni inInstant
n'ont de fuseau horaire ni de décalage UTC. La réponse précédemment acceptée et toujours la plus votée par Ben Noland utilise le fuseau horaire par défaut actuel des JVM pour sélectionner le décalage duXMLGregorianCalendar
. Pour inclure un décalage dans un objet moderne, nous utilisons unOffsetDateTime
. Par exemple:Encore une fois, cela est conforme au format XML. Si vous souhaitez réutiliser le paramètre de fuseau horaire JVM actuel, définissez
zone
surZoneId.systemDefault()
.Et si j'ai absolument besoin d'un XMLGregorianCalendar?
Il existe plusieurs façons de convertir
Instant
enXMLGregorianCalendar
. J'en présenterai un couple, chacun avec ses avantages et ses inconvénients. Tout d'abord, tout comme unXMLGregorianCalendar
produit une chaîne comme2009-05-07T17:05:45.678Z
, il peut également être construit à partir d'une telle chaîne:Pro: c'est court et je ne pense pas que ça donne de surprises. Inconvénient: Pour moi, cela ressemble à un gaspillage formatant l'instant en une chaîne et l'analysant en retour.
Pro: C'est la conversion officielle. Le contrôle du décalage vient naturellement. Inconvénient: il passe par plusieurs étapes et est donc plus long.
Et si on avait un rendez-vous?
Si vous avez obtenu un
Date
objet à l' ancienne d'une API héritée que vous ne pouvez pas vous permettre de changer pour l'instant, convertissez-le enInstant
:La sortie est la même qu'avant:
Si vous souhaitez contrôler le décalage, convertissez-le en un
OffsetDateTime
de la même manière que ci-dessus.Si vous avez un ancien
Date
et avez absolument besoin d'un ancienXMLGregorianCalendar
, utilisez simplement la réponse de Ben Noland.Liens
la source
la source
Pour ceux qui pourraient se retrouver ici à la recherche de la conversion opposée (de
XMLGregorianCalendar
àDate
):la source
Voici une méthode de conversion d'un GregorianCalendar en XMLGregorianCalendar; Je vais laisser la partie de la conversion d'un java.util.Date à GregorianCalendar comme un exercice pour vous:
EDIT: Slooow :-)
la source
Un exemple d'une ligne utilisant la bibliothèque Joda-Time :
Crédit à Nicolas Mommaerts de son commentaire dans la réponse acceptée .
la source
Je pensais simplement ajouter ma solution ci-dessous, car les réponses ci-dessus ne répondaient pas exactement à mes besoins. Mon schéma Xml nécessitait des éléments de date et d'heure séparés, pas un champ DateTime unique. Le constructeur XMLGregorianCalendar standard utilisé ci-dessus générera un champ DateTime
Notez-y quelques gothca, comme devoir en ajouter un au mois (car java compte des mois à partir de 0).
la source
J'espère que mon encodage ici est correct; D Pour le rendre plus rapide, il suffit d'utiliser l'appel laid getInstance () de GregorianCalendar au lieu de l'appel du constructeur:
la source
GregorianCalendar.getInstance()
est l'équivalent deCalendar.getInstance()
. LeCalendar.getInstance()
ne peut pas le rendre plus rapide, car il utilise le mêmenew GregorianCalendar()
, mais avant de vérifier également les paramètres régionaux par défaut et pourrait créer un calendrier japonais ou bouddish à la place, donc pour certains utilisateurs chanceux, ce sera le casClassCastException
!En supposant que vous
JAXB
décodez ou encodez du XML et que vous l'utilisez , il est alors possible de remplacer entièrement la liaison dateTime et d'utiliser autre chose que `XMLGregorianCalendar 'pour chaque date du schéma.De cette façon, vous pouvez avoir
JAXB
faire des choses répétitives pendant que vous pouvez passer du temps à écrire du code génial qui offre de la valeur.Exemple pour un jodatime
DateTime
: (Faire cela avec java.util.Date fonctionnerait également - mais avec certaines limitations. Je préfère le jodatime et il est copié à partir de mon code, donc je sais que cela fonctionne ...)Et le convertisseur:
Voir ici: comment remplacer XmlGregorianCalendar par Date?
Si vous êtes heureux de simplement mapper à un instant basé sur le fuseau horaire + horodatage et que le fuseau horaire d'origine n'est pas vraiment pertinent, alors
java.util.Date
c'est probablement bien aussi.la source
Découvrez ce code: -
Vous pouvez voir l'exemple complet ici
la source