110 votes

Conversion simple entre java.util.Date et XMLGregorianCalendar

Je suis à la recherche d'une méthode simple de convertir entre java.util.Date et javax.xml.type de données.XMLGregorianCalendar dans les deux directions.

Voici le code que j'utilise maintenant:

import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

/**
 * Utility class for converting between XMLGregorianCalendar and java.util.Date
 */
public class XMLGregorianCalendarConverter {  

    /**
     * Needed to create XMLGregorianCalendar instances
     */
    private static DatatypeFactory df = null;
    static {
        try {
            df = DatatypeFactory.newInstance();
        } catch (DatatypeConfigurationException dce) {
            throw new IllegalStateException(
                "Exception while obtaining DatatypeFactory instance", dce);
        }
    }  

    /**
     * Converts a java.util.Date into an instance of XMLGregorianCalendar
     *
     * @param date Instance of java.util.Date or a null reference
     * @return XMLGregorianCalendar instance whose value is based upon the
     *  value in the date parameter. If the date parameter is null then
     *  this method will simply return null.
     */
    public static XMLGregorianCalendar asXMLGregorianCalendar(java.util.Date date) {
        if (date == null) {
            return null;
        } else {
            GregorianCalendar gc = new GregorianCalendar();
            gc.setTimeInMillis(date.getTime());
            return df.newXMLGregorianCalendar(gc);
        }
    }

    /**
     * Converts an XMLGregorianCalendar to an instance of java.util.Date
     *
     * @param xgc Instance of XMLGregorianCalendar or a null reference
     * @return java.util.Date instance whose value is based upon the
     *  value in the xgc parameter. If the xgc parameter is null then
     *  this method will simply return null.
     */
    public static java.util.Date asDate(XMLGregorianCalendar xgc) {
        if (xgc == null) {
            return null;
        } else {
            return xgc.toGregorianCalendar().getTime();
        }
    }
}

Est-il rien de plus simple, comme certains l'appel de l'API que j'ai oublié?

La conversion entre une norme XML de date/heure et un Java objet date semble comme une jolie tâche de routine et je suis surpris de voir que j'ai à écrire ce code.

Toutes les suggestions?

NOTES: Mon JAXB classes sont générés automatiquement à partir d'un schéma. Le processus de build sur mon projet ne permet pas pour moi de faire des modifications manuelles pour les classes générées. Le xs:dateTime éléments sont générés par XJC comme XMLGregorianCalendar dans le JAXB classes. Le schéma est étendu et modifié périodiquement, de sorte que je suis autorisé à apporter des modifications limitées au schéma XSD fichier.

MISE À JOUR SUR LA SOLUTION: La solution proposée par Blaise m'a permis de prendre XMLGregorianCalendar de les mélanger et de les traiter avec java.util.Calendrier des objets à la place. Par l'ajout d'un JAXB clause contraignante en haut de mon fichier de schéma, XJC est en mesure de générer plus de mappages appropriés pour xs:dateTime dans ma JAXB classes. Voici quelques extraits qui montrent les modifications de mon fichier XSD.

L'élément racine du fichier XSD:

<xs:schema xmlns:mydata="http://my.example.com/mydata" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" targetNamespace="http://my.example.com/mydata" elementFormDefault="unqualified" attributeFormDefault="unqualified" version="0.2" xml:lang="en" jaxb:version="2.0">

JAXB liaison annotation bloc, inséré immédiatement après l'élément racine dans XSD:

<xs:annotation>
    <xs:appinfo>
        <jaxb:globalBindings>
            <jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime" parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />
        </jaxb:globalBindings>
    </xs:appinfo>
</xs:annotation>

Depuis le XML xs:dateTime champ stocke également fuseau horaire, il peut être préférable pour moi de travailler avec le Calendrier au lieu de la Date de toute façon puisque le Calendrier des objets ont une assez bonne API pour travailler avec les paramètres régionaux et les fuseaux horaires. En tout cas, je suis beaucoup plus heureux de traiter avec le Calendrier des objets au lieu de XMLGregorianCalendar. Pas besoin pour les méthodes de conversion que j'ai énuméré ci-dessus plus. Je n'ai pas à faire tout le chemin à java.util.Date, mais assez proche!

81voto

Zé Carlos Points 1276

De XMLGregorianCalendar à java.util.Date, vous pouvez simplement faire :

47voto

Blaise Doughan Points 75613

Pourquoi ne pas utiliser un fichier de liaison externe pour dire XJC pour générer des champs java.util.Date au lieu de XMLGregorianCalendar ?

Voir aussi :- http://weblogs.java.net/blog/kohsuke/archive/2006/03/how_do_i_map_xs.html

6voto

De java.util.Date à XMLGregorianCalendar vous pouvez tout simplement faire :

Code modifié après le premier commentaire de @f-puras, selon la cause, je fais une erreur.

5voto

Gregor Points 312

J'ai dû faire quelques modifications pour le faire fonctionner, que certaines choses semblent avoir changé dans l'intervalle:

  • xjc puisse se plaindre que ma carte ne s'étend pas XmlAdapter
  • quelques bizarres et inutiles, les importations ont été établis en (org.w3._2001.xmlschema)
  • l'analyse des méthodes ne doit pas être statique lors de l'extension de la XmlAdapter, évidemment

Voici un exemple de travail, espérons que cette aide (je suis en utilisant JodaTime mais dans ce cas SimpleDate serait suffisant):

import java.util.Date;
import javax.xml.bind.DatatypeConverter;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.joda.time.DateTime;

public class DateAdapter extends XmlAdapter<Object, Object> {
    @Override
    public Object marshal(Object dt) throws Exception {
        return new DateTime((Date) dt).toString("YYYY-MM-dd");
    }

    @Override
        public Object unmarshal(Object s) throws Exception {
        return DatatypeConverter.parseDate((String) s).getTime();
    }
}

Dans le fichier xsd, j'ai suivi l'excellent références données ci-dessus, j'ai donc inclus cette annotation en xml:

<xsd:appinfo>
    <jaxb:schemaBindings>
        <jaxb:package name="at.mycomp.xml" />
    </jaxb:schemaBindings>
    <jaxb:globalBindings>
        <jaxb:javaType name="java.util.Date" xmlType="xsd:date"
              parseMethod="at.mycomp.xml.DateAdapter.unmarshal"
          printMethod="at.mycomp.xml.DateAdapter.marshal" />
    </jaxb:globalBindings>
</xsd:appinfo>

1voto

Alex Points 66

J’ai aussi eu ce genre de maux de tête. Débarrassé de celui-ci en simplement représentant les champs heure tant primitifs dans mon POJO. Maintenant la génération de mon code de client WS tout gérer correctement et XML-à-Java n’est plus la merde. Et bien sûr traitant de millis du côté de Java est simple et indolore. Roches de principe KISS !

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