web-dev-qa-db-ja.com

Java DateからXML Date Formatへの変換(およびその逆))

Java日付をXML日付文字列形式に、またはその逆に変換する素敵で簡単な方法はありますか?

乾杯、

アンデス

21
Andez

元の答え

ここでは、「XML Date Format」とは「2010-11-04T19:14Z」のようなものを意味すると推測しています。実際には ISO 8601 形式です。

他の人が示唆しているように、FastDateFormatのSimpleDateFormatを使用して、または この目的 のために特別に作成された Joda Time を使用して変換できます。

編集:コードサンプルなど

earnshae がコメントで述べたように、この答えは例で改善できます。

最初に、元の回答がかなり古いことを明確にする必要があります。これは、Java 8が日付と時刻を操作するクラスを導入したためです。_Java.time_パッケージは興味深いはずです。幸運にもJava = 8のいずれかを使用する必要がありますが、これらを正しく使用するのは驚くほど困難です。

LocalDate(Time)ではありません

この例を考えてみましょう:

_LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T18:21");
System.out.println(dateTime); // 2016-03-23T18:21
_

最初は、ここで使用しているのはローカル(ユーザーの日時)であるように思われるかもしれません。ただし、あえて質問すると、異なる結果が得られます。

_System.out.println(dateTime.getChronology()); // ISO
_

これは、実際にはISO時間です。 「UTC」と読むべきだと思いますが、それでもローカルタイムゾーンの概念はありません。したがって、私たちはそれを普遍的なものと考えるべきです。
解析中の文字列の末尾に「Z」がないことに注意してください。日付と時刻以外に何かを追加すると、_Java.time.format.DateTimeParseException_が表示されます。したがって、ISO8601文字列を解析する場合、このクラスは役に立たないようです。

ZonedDateTimeが助けに

幸いなことに、ISO8601文字列を解析できるクラスがあります-これは 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
_

ここでの唯一の問題は、実際にタイムゾーン指定を使用する必要があるということです。生の日付時刻(つまり、「2016-03-23T18:21」)を解析しようとすると、既に説明したRuntimeExceptionになります。状況に応じて、LocalDateTimeZonedDateTimeのいずれかを選択する必要があります。
もちろん、これら2つの間で簡単に変換できるため、問題になることはありません。

_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]
_

最近、このクラスを使用することをお勧めします。ただし、仕事の説明に考古学が含まれている場合(2歳以上の場合Java 8 ...).

SimpleDateFormatの喜び

私はhttps://docs.Oracle.com/javase/8/docs/api/Java/text/SimpleDateFormat.htmlの大ファンではありませんが、他に選択肢がない場合があります。問題は、スレッドセーフではないため、何かが嫌いな場合は、チェックされたException(つまりParseException)が顔にスローされることです。したがって、コードスニペットはかなりratherいです。

_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

FastDateFormatは同期されているため、少なくとも同期ブロックを取り除くことができます。ただし、これは外部依存関係です。しかし、それは Apache Commons Lang であり、徹底的に使用されているため、許容できると思います。実際の使用法は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);
}
_

JodaTime

Joda-Timeを使用すると、次のように動作すると思うかもしれません。

_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
_

残念ながら、最後の位置(Z、+ 03:00、...)に何を入れても、結果は同じになります。明らかに、機能していません。
まあ、あなたは本当にそれを直接解析すべきです:

_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
_

これで問題ありません。他の回答の1つとは異なり、dateTimeParser()notdateTime()を使用したことに注意してください。微妙ですが、それらの間の動作に重要な違いがあることに気付きました(Joda-Time 2.9.2)。しかし、私はそれをテストして確認するために読者に任せます。

23
Paweł Dyda

すでに提案されているように、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);

私の推測では、あなたが探しているフォーマット/パターンはyyyy-MM-dd'T'HH:mm:ssまた、 http://www.w3schools.com/schema/schema_dtypes_date.asp もご覧ください。

19
Kennet

Joda Time を使用すると、次のことができます。

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

スレッドセーフ、不変、シンプル。

9
Gary Rowe

Perfectメソッド、XMLGregorianCalendarを使用:

GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(v);
DatatypeFactory df = DatatypeFactory.newInstance();
XMLGregorianCalendar dateTime = df.newXMLGregorianCalendar(calendar);
return dateTime.toString();
8
loic vaugeois

JavaでSimpleDateFormatを使用するだけで、これを実行できます...

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date date = sdf.parse("2011-12-31T15:05:50+1000");
7
Sridhar Nalam

Java組み込みクラス javax.xml.bind.DatatypeConverter を使用することをお勧めします。ほとんどのxml単純型との間の変換を処理できます。 Calendarオブジェクトを通過する必要がある日付には少し面倒ですが、一方でxml datetimeフィールドで発生する可能性があるゾーン情報のすべてのバリアントを処理します。

Xmlから:

    Calendar c = DatatypeConverter.parseDateTime("2015-10-21T13:25");
    Date d = c.getTime();

Xmlへ:

    Date yourDate = new Date()
    Calendar c = Calendar.getInstance();
    c.setTime(yourDate);
    String xmlDateTime = DatatypeConverter.printDateTime(c);

[〜#〜] edit [〜#〜]

DatatypeConverterクラスは、javax.xml.bindパッケージに属しているため、Java 9以降で公開されなくなりました。 この質問 を参照してください。 =詳細および可能な解決策について。この場合、XmlGregorianCalendarを使用するためにloic vaugeoisによって提案された解決策の方がはるかに優れています

4
stenix

SimpleDateFormat を使用して、任意の形式との間で日付を解析およびフォーマットできます。

3
Eugene Kuleshov

ISO8601に準拠するには、タイムゾーンは+ HH:MMまたは-HH:MMの形式である必要があります

Simpledateformatでは、Zの代わりにXXXを使用する必要があります(NovelGuyの回答を参照)

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
2
arkhos

必要な形式を正確に知らなくても、一般的な応答は次のとおりです。DateFormatまたはSimpleDateFormatが必要になります。両方の here に素敵なチュートリアルがあります。

1
javamonkey79