java.util.DateからXMLGregorianCalendar


601

java.util.DateからXMLGregorianCalendarに取得する便利な方法はありませんか?


参考:これらのひどいクラスは両方とも、数年前にJSR 310で定義されたjava.timeクラスに取って代わられました。ZonedDateTimeクラス、およびレガシークラスに追加された新しい変換メソッドを参照してください。Ole VVによるこの回答の詳細
Basil Bourque

回答:


36

私は一歩下がって、この10年前の質問を現代的に見ていきたいと思います。言及されたクラス、DateおよびXMLGregorianCalendarは現在古いものです。私はそれらの使用に挑戦し、代替案を提供します。

  • Date常にデザインが不十分で、20年以上前のものです。これは簡単です。使用しないでください。
  • XMLGregorianCalendar古く、昔ながらのデザインです。私が理解しているように、XMLドキュメントのXML形式で日付と時刻を生成するために使用されていました。同様2009-05-07T19:05:45.678+02:002009-05-07T17:05:45.678Z。これらの形式はISO 8601と十分に一致しており、最新のJavaの日付と時刻のAPIであるjava.timeのクラスで生成できます。

変換は不要

多くの(ほとんど?)目的で、aの最新の置き換えはにDateなりますInstant。An Instantは、(あるのと同様にDate)ある時点です。

    Instant yourInstant = // ...
    System.out.println(yourInstant);

このスニペットからの出力例:

2009-05-07T17:05:45.678Z

これは、XMLGregorianCalendar上記の例の文字列の後半と同じです。ほとんどの人が知っているように、これはInstant.toStringによって暗黙的に呼び出されたことが原因System.out.printlnです。java.timeでは、多くの場合、我々は昔に我々は間で行わという変換を必要としないDateCalendarXMLGregorianCalendarおよび他のクラス(私たちが必要変換を行ういくつかのケースでは、しかし、私はあなたの次のセクションでカップルを示しています) 。

オフセットの制御

a DateもinもInstantタイムゾーンもUTCオフセットもありません。ベンノーランドが以前に承認し、現在も最も投票数の多い回答では、JVMの現在のデフォルトのタイムゾーンを使用してのオフセットを選択していXMLGregorianCalendarます。最新のオブジェクトにオフセットを含めるには、を使用しOffsetDateTimeます。例えば:

    ZoneId zone = ZoneId.of("America/Asuncion");
    OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();
    System.out.println(dateTime);

2009-05-07T13:05:45.678-04:00

これもXML形式に準拠しています。現在のJVMタイムゾーン設定を再度使用する場合は、に設定zoneZoneId.systemDefault()ます。

XMLGregorianCalendarが絶対に必要な場合はどうなりますか?

に変換Instantする方法は他にもありますXMLGregorianCalendar。それぞれの長所と短所を備えたカップルを紹介します。まず、がのXMLGregorianCalendarような文字列を生成するのと同じように2009-05-07T17:05:45.678Z、そのような文字列から構築することもできます。

    String dateTimeString = yourInstant.toString();
    XMLGregorianCalendar date2
            = DatatypeFactory.newInstance().newXMLGregorianCalendar(dateTimeString);
    System.out.println(date2);

2009-05-07T17:05:45.678Z

長所:短いので、驚くことはないと思います。短所:私にとっては、インスタントを文字列にフォーマットして解析し直すのは無駄だと感じています。

    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

プロ:それは公式の転換です。オフセットの制御は自然に起こります。短所:それはより多くのステップを経るため、より長くなります。

日付を取得したらどうなりますか?

Date今すぐ変更する余裕がないレガシーAPIから古いスタイルのオブジェクトを取得した場合は、次のように変換しInstantます。

    Instant i = yourDate.toInstant();
    System.out.println(i);

出力は前と同じです:

2009-05-07T17:05:45.678Z

オフセットを制御したい場合はOffsetDateTime、上記と同じ方法でさらにに変換します。

昔ながらの方法がDateあり、絶対に昔ながらの方法が必要な場合は、XMLGregorianCalendarBen Nolandの回答を使用してください。

リンク集


1034
GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);

5
getInstance()を一部のコンバータークラスの静的変数として保持することは節約ですか?JavaDocで調べようとしましたが何も見つかりませんでした。同時使用で問題が発生するかどうかはわかりませんか?
マーティン

36
あなたがJodaTimeを使用して喜んでいる場合は、1行で行うことができます。DatatypeFactory.newInstance()newXMLGregorianCalendar(新しい日時()toGregorianCalendar()。)。
ニコラスMommaerts

3
XMLGregorianCalendar date2 = DatatypeFactory.newInstance()。newXMLGregorianCalendar(new GregorianCalendar(YYYY、MM、DD));
Junchen Liu 2015

3
Calendarはスレッドセーフではないため、GregorianCalenderもスレッドセーフではないことに注意してください。stackoverflow.com/questions/12131324/…
質問票

1行バージョン-DatatypeFactory.newInstance()。newXMLGregorianCalendar(new GregorianCalendar(){{setTime(yourDate);}})
Alex Vayda

205

ここで逆の変換(からXMLGregorianCalendarDate)を探している可能性がある場合:

XMLGregorianCalendar xcal = <assume this is initialized>;
java.util.Date dt = xcal.toGregorianCalendar().getTime();

31

以下は、GregorianCalendarからXMLGregorianCalendarに変換するメソッドです。演習として、java.util.DateからGregorianCalendarへの変換の部分は残しておきます。

import java.util.GregorianCalendar;

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

public class DateTest {

   public static void main(final String[] args) throws Exception {
      GregorianCalendar gcal = new GregorianCalendar();
      XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(gcal);
      System.out.println(xgcal);
   }

}

編集:Slooow :-)


6
これは、GregorianCalendarをXMLGregorianCalendarに変換するためのソリューションであり、質問に示されているものではありません
ftrujillo


12

上記の答えは私の正確なニーズを満たしていなかったので、私は以下に私のソリューションを追加すると思いました。私のXMLスキーマには、単一のDateTimeフィールドではなく、別個のDate要素とTime要素が必要でした。上記で使用されている標準のXMLGregorianCalendarコンストラクタは、DateTimeフィールドを生成します

月に1を追加する必要があるなど、いくつかのgothcaがあることに注意してください(Javaは0から月をカウントするため)。

GregorianCalendar cal = new GregorianCalendar();
cal.setTime(yourDate);
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH), 0);
XMLGregorianCalendar xmlTime = DatatypeFactory.newInstance().newXMLGregorianCalendarTime(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), 0);

10

ここでのエンコーディングが正しいことを願っています; D高速化するには、コンストラクター呼び出しの代わりにGregorianCalendarの醜いgetInstance()呼び出しを使用するだけです。

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

public class DateTest {

   public static void main(final String[] args) throws Exception {
      // do not forget the type cast :/
      GregorianCalendar gcal = (GregorianCalendar) GregorianCalendar.getInstance();
      XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(gcal);
      System.out.println(xgcal);
   }

}

14
.getInstance()を使用する場合は-1。GregorianCalendar.getInstance()はと同等ですCalendar.getInstance()Calendar.getInstance()それは同じ使用しているため、より速くそれを作ることはできませんnew GregorianCalendar()が、それはまた、デフォルトのロケールをチェックし、代わりに、日本やBuddishカレンダーを作成することができる前に、ので、いくつかの幸運のユーザーのために、それは次のようになりますClassCastException
kan

6

xmlをデコードまたはエンコードしてを使用していると仮定するとJAXB、dateTimeバインディングを完全に置き換え、スキーマ内のすべての日付に「XMLGregorianCalendar」以外の何かを使用することが可能です。

JAXBそうすることで、価値のある素晴らしいコードを書くことに時間を費やすことができると同時に、反復的なことを行うことができます。

jodatimeの例DateTime:(java.util.Dateでこれを実行しても機能しますが、一定の制限があります。jodatimeを使用し、コードからコピーしたので、機能することがわかります...)

<jxb:globalBindings>
    <jxb:javaType name="org.joda.time.LocalDateTime" xmlType="xs:dateTime"
        parseMethod="test.util.JaxbConverter.parseDateTime"
        printMethod="se.seb.bis.test.util.JaxbConverter.printDateTime" />
    <jxb:javaType name="org.joda.time.LocalDate" xmlType="xs:date"
        parseMethod="test.util.JaxbConverter.parseDate"
        printMethod="test.util.JaxbConverter.printDate" />
    <jxb:javaType name="org.joda.time.LocalTime" xmlType="xs:time"
        parseMethod="test.util.JaxbConverter.parseTime"
        printMethod="test.util.JaxbConverter.printTime" />
    <jxb:serializable uid="2" />
</jxb:globalBindings>

そしてコンバータ:

public class JaxbConverter {
static final DateTimeFormatter dtf = ISODateTimeFormat.dateTimeNoMillis();
static final DateTimeFormatter df = ISODateTimeFormat.date();
static final DateTimeFormatter tf = ISODateTimeFormat.time();

public static LocalDateTime parseDateTime(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        LocalDateTime r = dtf.parseLocalDateTime(s);
        return r;
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printDateTime(LocalDateTime d) {
    try {
        if (d == null)
            return null;
        return dtf.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static LocalDate parseDate(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        return df.parseLocalDate(s);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printDate(LocalDate d) {
    try {
        if (d == null)
            return null;
        return df.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printTime(LocalTime d) {
    try {
        if (d == null)
            return null;
        return tf.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static LocalTime parseTime(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        return df.parseLocalTime(s);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

ここを参照してください: XmlGregorianCalendarをどのように日付で置き換えますか?

タイムゾーン+タイムスタンプに基づいてインスタントにマッピングするだけで満足し、元のタイムゾーンが実際には関係ない場合java.util.Dateは、おそらく問題ありません。


0

このコードをチェックしてください:-

/* Create Date Object */
Date date = new Date();
XMLGregorianCalendar xmlDate = null;
GregorianCalendar gc = new GregorianCalendar();

gc.setTime(date);

try{
    xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
}
catch(Exception e){
    e.printStackTrace();
}

System.out.println("XMLGregorianCalendar :- " + xmlDate);

ここで完全な例を見ることができます


この回答が新しいものを提供することはないと思います。おそらく、ほぼ同じように別の回答を投稿する代わりに、前の回答を編集できます。
冬の

1
XMLGregorianCalendarのdateFormatを行う方法は?
Panadol Chong
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.