1. ホーム
  2. java

[解決済み] java.util.DateとXMLGregorianCalendarの簡易変換機能

2022-10-03 18:06:29

質問

java.util.Date と javax.xml.datatype.XMLGregorianCalendar の間で双方向に変換する簡単な方法を探しています。

以下は、私が今使用しているコードです。 :

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();
        }
    }
}

私が見落としているAPIコールのような、もっと単純なものはありますか?

標準的なXMLの日付/時刻とJavaの日付オブジェクトの間で変換することは、かなりルーチンなタスクのように思われ、私はこのコードをまったく書かなければならないことに驚いています。

何か提案はありますか?

注意事項 私のJAXBクラスはスキーマから自動生成されます。私のプロジェクトのビルド プロセスでは、生成されたクラスを手動で変更することはできません。xs:dateTime要素はXJCによってJAXBクラス内でXMLGregorianCalendarとして生成されています。スキーマは定期的に拡張および調整されるので、私はスキーマ XSD ファイルに限定的な変更を加えることが許されています。

解決策を更新しました。 Blaiseが提案した解決策によって、XMLGregorianCalendarをミックスから外し、代わりにjava.util.Calendarオブジェクトを扱うことができるようになりました。スキーマファイルの先頭にJAXBバインディング句を追加することで、XJCは私のJAXBクラスでxs:dateTimeに対してより適切なマッピングを生成できるようになりました。以下は、私の XSD ファイルにおける変更を示すいくつかのスニペットです。

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バインディングアノテーションブロック、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>

XML xs:dateTime フィールドはタイムゾーンも格納するので、Calendar オブジェクトはロケールやタイムゾーンを扱うのにかなり良い API を持っているので、いずれにしても Date ではなく Calendar で作業したほうが良いかもしれません。いずれにせよ、XMLGregorianCalendarの代わりにCalendarオブジェクトを扱う方がはるかに幸せです。上に挙げたような変換方法はもう必要ない。java.util.Dateまでたどり着けなかったけど、十分近いよ!

どう解決したのか?

外部バインディングファイルを使って、XMLGregorianCalendarの代わりにjava.util.Dateフィールドを生成するようにXJCに指示してはどうでしょうか?

また、以下を参照してください。 xs:dateをjava.util.Dateにマップするにはどうすればよいですか?ブログ