タイムゾーンオフセットを使用して、次のISO 8601 DateTime文字列を解析します。
_final String input = "2022-03-17T23:00:00.000+0000";
OffsetDateTime.parse(input);
LocalDateTime.parse(input, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
_
両方のアプローチは失敗します(OffsetDateTime
も_DateTimeFormatter.ISO_OFFSET_DATE_TIME
_を使用するので理にかなっています)タイムゾーンオフセットのコロンのため。
Java.time.format.DateTimeParseException:インデックス23でテキスト「2022-03-17T23:00:00.000 + 0000」を解析できませんでした
しかし Wikipedia によると、タイムゾーンオフセットには4つの有効な形式があります。
_<time>Z
<time>±hh:mm
<time>±hhmm
<time>±hh
_
他のフレームワーク/言語は、問題なくこの文字列を解析できます。 Javascript Date()
またはJacksons _ISO8601Utils
_(この問題について議論します here )
複雑なRegExを使用して独自のDateTimeFormatter
を記述できるようになりましたが、私の意見では、_Java.time
_ライブラリは有効なISO 8601文字列をデフォルトで解析できるはずです。
ここでは、Jacksons _ISO8601DateFormat
_を使用しますが、公式の_date.time
_ライブラリを使用することをお勧めします。この問題に取り組むためのあなたのアプローチは何ですか?
オフセットのすべての有効な形式(Z
、±hh:mm
、±hhmm
および±hh
)をすべて解析する場合、1つの選択肢はJava.time.format.DateTimeFormatterBuilder
をオプションで使用することですパターン(残念ながら、すべてに一致する単一のパターン文字はないようです):
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
// date/time
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// offset (hh:mm - "+00:00" when it's zero)
.optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
// offset (hhmm - "+0000" when it's zero)
.optionalStart().appendOffset("+HHMM", "+0000").optionalEnd()
// offset (hh - "Z" when it's zero)
.optionalStart().appendOffset("+HH", "Z").optionalEnd()
// create formatter
.toFormatter();
System.out.println(OffsetDateTime.parse("2022-03-17T23:00:00.000+0000", formatter));
System.out.println(OffsetDateTime.parse("2022-03-17T23:00:00.000+00", formatter));
System.out.println(OffsetDateTime.parse("2022-03-17T23:00:00.000+00:00", formatter));
System.out.println(OffsetDateTime.parse("2022-03-17T23:00:00.000Z", formatter));
上記の4つのケースはすべて、2022-03-17T23:00Z
に解析されます。
必要に応じて、[]
を使用してオプションのセクションを区切って、単一の文字列パターンを定義することもできます。
// formatter with all possible offset patterns
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS[xxx][xx][X]");
このフォーマッタは、上記の以前のフォーマッタと同様に、すべての場合に機能します。 javadoc をチェックして、各パターンの詳細を取得します。
注:
.SSS
のため)。一方、ISO_LOCAL_DATE_TIME
はより柔軟です。秒とナノ秒はオプションであり、小数点以下0〜9桁も受け入れます。入力データに最適なものを選択してください。複雑な正規表現を書く必要はありません-その形式で簡単に動作するDateTimeFormatter
を構築できます:
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX", Locale.ROOT);
OffsetDateTime odt = OffsetDateTime.parse(input, formatter);
また、「0000」ではなく「Z」も受け入れます。 not accept "+00:00"(コロンなどを使用)。ドキュメントを考えると驚くべきことですが、コロンなしの値に常にUTCオフセットがある場合は問題ありません。