ISO 8601準拠の文字列をjava.util.Dateに変換する


667

ISO 8601形式の文字列をに変換しようとしていjava.util.Dateます。

yyyy-MM-dd'T'HH:mm:ssZロケールと共に使用した場合、パターンはISO8601に準拠していることがわかりました(サンプルを比較)。

ただし、を使用java.text.SimpleDateFormatすると、正しくフォーマットされたStringを変換できません2010-01-01T12:00:00+01:00。最初に2010-01-01T12:00:00+0100、コロンなしでに変換する必要があります。

したがって、現在のソリューションは

SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.GERMANY);
String date = "2010-01-01T12:00:00+01:00".replaceAll("\\+0([0-9]){1}\\:00", "+0$100");
System.out.println(ISO8601DATEFORMAT.parse(date));

これは明らかにそれほど良くありません。何か不足していますか、それとももっと良い解決策がありますか?


回答

JuanZeのコメントのおかげで、Joda -Timeマジックが見つかりました。これもここで説明されています

したがって、解決策は

DateTimeFormatter parser2 = ISODateTimeFormat.dateTimeNoMillis();
String jtdate = "2010-01-01T12:00:00+01:00";
System.out.println(parser2.parseDateTime(jtdate));

より簡単には、コンストラクターを介してデフォルトのパーサーを使用します。

DateTime dt = new DateTime( "2010-01-01T12:00:00+01:00" ) ;

私にとって、これは素晴らしいことです。


243
「Use JodaTime」の回答をたくさん受け取る準備をしてください...
JuanZe

3
@ Ice09:DateTimeFormatのAPIドキュメントが正しい場合(ただし、JoDaドキュメントが誤解を招く、誤っている、または不完全である可能性があります)、独自の「回答」で使用したパターンは、ISO8601と互換性がありません。
jarnbjo 2010

21
これがいつ追加されたかはわかりませんが、「X」はSimpleDateFormat内のこの問題を解決するようです。パターン "yyyy-MM-dd'T'HH:mm:ssX"は、質問の例を正常に解析します。
mlohbihler

12
「X」はJava 7以降で使用可能です
Lars Grammel

3
Java 8なら簡単です!以下の回答には、Adamの隠された宝石があります。stackoverflow.com
Fabian Keller

回答:


477

残念ながら、SimpleDateFormat(Java 6以前)で使用可能なタイムゾーン形式は、ISO 8601に準拠していません。SimpleDateFormatは、 "GMT + 01:00"や "+0100"のようなタイムゾーン文字列を理解します。後者はRFC#822に準拠しています

Java 7がISO 8601に従ってタイムゾーン記述子のサポートを追加した場合でも、SimpleDateFormatはオプションの部分をサポートしていないため、完全な日付文字列を適切に解析できません。

正規表現を使用して入力文字列を再フォーマットすることは確かに1つの可能性ですが、置換規則は質問ほど単純ではありません。

  • 一部のタイムゾーンはUTCの完全な時間ではないため、文字列が必ずしも「:00」で終わっているわけではありません。
  • ISO8601は時間帯に含まれる時間数のみを許可するため、「+ 01」は「+01:00」と同等です
  • ISO8601では、「+ 00:00」の代わりに「Z」を使用してUTCを示すことができます。

JAXBは、XMLスキーマ仕様に従ってISO8601日付文字列を解析できる必要があるため、JAXBでデータ型コンバータを使用する方が簡単な解決策になる可能性があります。javax.xml.bind.DatatypeConverter.parseDateTime("2010-01-01T12:00:00Z")あなたを与えるだろうCalendar、オブジェクトを、あなたが必要な場合は、単純に、それにgetTime()を使用することができDate、オブジェクトを。

おそらくJoda-Timeを使用することもできますが、なぜそれを気にする必要があるのか​​はわかりません。


18
JAXBソリューションは本当に創造的なアプローチです!それは同様に機能します、私は私のサンプルでそれをテストしました。ただし、問題に直面し、JodaTimeの使用が許可されている人は、より自然に感じるので、使用することをお勧めします。しかし、ソリューションには追加のライブラリは必要ありません(少なくともJava 6では)。
Ice09、

36
これが逆です:Calendar c = GregorianCalendar.getInstance(); c.setTime(aDate); return javax.xml.bind.DatatypeConverter.printDateTime(c);
Alexander Ljungberg、

4
実際には、jaxb datatypeConverterを初期化する必要があるほど単純なb / cではありません。DataTypeConverterImplが内部で行ったように、私は自分でDatatypeFactoryを使用することになりました。頭痛の種だ。
gtrak 2010

3
@Simon:いいえ、タイムゾーンはもちろん無視されません。あなたは何か間違ったことをしているに違いありません。数文字以上入力して実際に何をしているのかを教えてくれると、誰かが説明してくれるかもしれません。
jarnbjo

4
@jarnbjoあなたは、joda-timeよりも標準の1.8より前のJava日付クラスを好む、私が遭遇した最初で唯一の人物です。私はjoda-timeを使用するのが文字通りの喜びだと思っています。
NimChimpsky 14年

244

Java 7のドキュメントで祝福されている方法:

DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
String string1 = "2001-07-04T12:08:56.235-0700";
Date result1 = df1.parse(string1);

DateFormat df2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
String string2 = "2001-07-04T12:08:56.235-07:00";
Date result2 = df2.parse(string2);

SimpleDateFormat javadocのセクションの例に、より多くの例があります。

UPD 2020年2月13日:あり全く新しい方法 Javaでこれを行うには、8


7
あなたの答えは、MongoDBのISODateをローカル日付に変換するのに役立ちました。よろしく。
Blue Sky

9
@ b.long Javaは、このようなISO 8601準拠の形式の定数以上のものを追加しました。Javaは、そのようなフォーマットの組み込みのデフォルトサポートを含む、日時作業用のまったく新しいフレームワークを取得しました。面倒なjava.util.Date、.Calendar、SimpleDateFormatクラスに取って代わり、Joda -Timeに触発されたJava 8の新しいjava.timeフレームワークをご覧ください。
バジルブルク

2
これは、日付の形式を事前に知っておく必要があるという意味ではありませんか?あなたが受け入れなければならない場合string1string2が、あなたが得るであろうか分かりません。
Timmmm 2015

16
'Z'は引用符で
囲む

7
@kervin Zが引用符で囲まれている場合、フォーマッタは文字Zを具体的に探しているのではなく、Zが表すことができるすべてのオフセット文字列を探しているのではないですか?日付文字列がたまたまUTCである場合、Zを引用すると偶然にしか機能しないようです。
spaaarky21

201

さて、この質問はすでに回答されていますが、とにかく私の回答は破棄します。それは誰かを助けるかもしれません。

私はAndroid(API 7)のソリューションを探していました。

  • ジョーダは問題外でした-それは巨大で、遅い初期化に悩まされています。それはまた、その特定の目的のための大きなやり過ぎのように見えました。
  • 回答javax.xmlはAndroid API 7では機能しません。

この単純なクラスを実装することになりました。最も一般的な形式のISO 8601文字列のみをカバーしていますが、場合によってはこれで十分です(入力がこの形式であることが確実である場合)。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * Helper class for handling a most common subset of ISO 8601 strings
 * (in the following format: "2008-03-01T13:00:00+01:00"). It supports
 * parsing the "Z" timezone, but many other less-used features are
 * missing.
 */
public final class ISO8601 {
    /** Transform Calendar to ISO 8601 string. */
    public static String fromCalendar(final Calendar calendar) {
        Date date = calendar.getTime();
        String formatted = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
            .format(date);
        return formatted.substring(0, 22) + ":" + formatted.substring(22);
    }

    /** Get current date and time formatted as ISO 8601 string. */
    public static String now() {
        return fromCalendar(GregorianCalendar.getInstance());
    }

    /** Transform ISO 8601 string to Calendar. */
    public static Calendar toCalendar(final String iso8601string)
            throws ParseException {
        Calendar calendar = GregorianCalendar.getInstance();
        String s = iso8601string.replace("Z", "+00:00");
        try {
            s = s.substring(0, 22) + s.substring(23);  // to get rid of the ":"
        } catch (IndexOutOfBoundsException e) {
            throw new ParseException("Invalid length", 0);
        }
        Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(s);
        calendar.setTime(date);
        return calendar;
    }
}

パフォーマンスのメモ: Android 2.1のバグを回避する手段として、毎回新しいSimpleDateFormatをインスタンス化します。あなたが私と同じくらい驚いたなら、この謎を見てください。他のJavaエンジンの場合は、インスタンスをプライベート静的フィールドにキャッシュできます(スレッドセーフにするためにThreadLocalを使用)。


2
おそらく、これは独自の質問になり、独自の答えを持つべきでしたか?
Thorbear 2012

5
これは私が答えを探していたときに私が頑張った最初のページだったので、それは合うように見えました。ほとんどのJava開発者にとって、Androidは正確にはJavaではありません。ただし、ほとんどの場合、一方は他方と同じように機能するため、多くのAndroid開発者はこれを探すときに「java」を検索します。
wrygiel 2012

1
これはミリ秒の精度を考慮していないことに注意してください。これは簡単に追加できます。
スカイケルシー2012

6
小数秒のために.SSSを追加する必要がありましたが、素晴らしいthxを機能します。なぜあなたはそうするのですかs = s.substring(0, 22) + s.substring(23);-私はこの点を理解していません
ドリ

1
input = input.replaceAll( "[Zz]"、 "+0000"); も機能し、部分文字列操作を回避できます。
Javanator 2015年

115

java.time

java.timeのAPI(後のJava 8とに組み込まれた)は、このaは少し楽になります。

最後に(Zuluの場合)など、入力がUTCであることがわかっている場合ZInstantクラスは解析できます。

java.util.Date date = Date.from( Instant.parse( "2014-12-12T10:39:40Z" ));

入力が、末尾の(Zulu)で示されるUTCではなく、UTC からの別のオフセット値である可能性がある場合は、クラスを使用して解析します。ZOffsetDateTime

OffsetDateTime odt = OffsetDateTime.parse( "2010-01-01T12:00:00+01:00" );

次にを抽出しInstant、をjava.util.Date呼び出してに変換しfromます。

Instant instant = odt.toInstant();  // Instant is always in UTC.
java.util.Date date = java.util.Date.from( instant );

8
この答えは働きすぎです。定義上、java.util.Dateにはタイムゾーンがありません。:コードを関連するすべてのその時間帯の必要はありませんがそうLocalDateTimeZoneIdしてatZone。この簡単なワンライナーを行います:java.util.Date date = Date.from( ZonedDateTime.parse( "2014-12-12T10:39:40Z" ).toInstant() );
バジルボーク

5
@BasilBourqueこれは不必要に複雑です:Date.from(Instant.parse("2014-12-12T10:39:40Z" ));十分です。
assylias

3
@assyliasは正しいですが、日付文字列がUTCゾーンである場合にのみ機能します。ISO8601は任意のタイムゾーンを許可します...
Adam

2
@Adam My bad-質問があなたの例よりも一般的であることに気づかなかった。副次的なコメントとして、OffsetDateTimeISO8601(タイムゾーン情報は含まれず、オフセットのみが含まれる)を解析するには、これで十分です。
アッシリア2015年

1
@assylias Instant解析の実行についてのコメントありがとうございます。この特定の質問には不十分ですが、指摘する価値のある重要な違いです。そこで、コードの2番目の例を追加しました。おっと、これは元々私の回答ではないことに気づきました。アダムが承認してくれることを願っています。
バジルブルク2015年

67

ジャクソン・データバインドライブラリはまた、持っているISO8601DateFormatクラスのもの(実際の実装んISO8601Utilsを

ISO8601DateFormat df = new ISO8601DateFormat();
Date d = df.parse("2010-07-28T22:25:51Z");

この日付の解析に失敗しました:2015-08-11T13:10:00。私が取得しますString index out of range: 19。コードを見ると、ミリ秒とタイムゾーンを指定する必要があるようです。それらはオプションである必要があります。
Timmmm 2015

2
ドキュメントを引用すると、解析形式は次のようになり[yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]]ます。つまり、ミリ秒はオプションですが、タイムゾーンは必須です。
david_p

2
ああ、そうです、あなたが正しいようです。それでも、ISO8601ではタイムゾーンを省略できるため、間違いがあります。JodaTime作品かかわら:new DateTime("2015-08-11T13:10:00").toDate()
Timmmm

3
そのクラスは非推奨になりました。新しいクラスはStdDateFormatです。それ以外は同じように機能します。
JohnEye 2018年

51

tl; dr

OffsetDateTime.parse ( "2010-01-01T12:00:00+01:00" )

java.timeの使用

Java 8以降の新しいjava.timeパッケージは、Joda -Timeに触発されました。

このOffsetDateTimeクラスは、タイムゾーンではなく、UTCからのオフセットでタイムライン上の瞬間を表します。

OffsetDateTime odt = OffsetDateTime.parse ( "2010-01-01T12:00:00+01:00" );

呼び出すとtoString、標準のISO 8601形式の文字列が生成されます。

2010-01-01T12:00 + 01:00

UTCのレンズを通して同じ値を表示するには、を抽出するInstantか、から+01:00へのオフセットを調整し00:00ます。

Instant instant = odt.toInstant();  

…または…

OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC );

必要に応じて、タイムゾーンに調整します。タイムゾーンが履歴であるオフセットから-UTC例えば夏時間(DST)などの異常を処理するためのルールのセットを用いて、領域の値。したがって、可能な限り、単なるオフセットではなくタイムゾーンを適用してください。

ZonedDateTime zonedDateTimeMontréal = odt.atZoneSameInstant( ZoneId.of( "America/Montreal" ) );

java.timeについて

java.timeのフレームワークは、Java 8に組み込まれており、後にされています。これらのクラスは面倒古い取って代わるレガシーのような日付時刻クラスをjava.util.DateCalendar、& SimpleDateFormat

ジョダタイムプロジェクトは、今でメンテナンスモードへの移行をアドバイスjava.timeのクラス。

詳細については、Oracleチュートリアルを参照してください。スタックオーバーフローで多くの例と説明を検索してください。仕様はJSR 310です。

java.timeオブジェクトをデータベースと直接交換することができます。JDBC 4.2以降に準拠したJDBCドライバーを使用します。文字列もクラスも必要ありません。java.sql.*

java.timeクラスはどこで入手できますか?

  • Java SE 8 Java SE 9 Java SE 10以降
    • ビルトイン。
    • 実装がバンドルされた標準Java APIの一部。
    • Java 9では、いくつかのマイナーな機能と修正が追加されています。
  • Java SE 6および Java SE 7
    • java.time機能の多くは、ThreeTen-BackportでJava 6および7にバックポートされています。
  • アンドロイド
    • Androidの新しいバージョンには、java.timeクラスの実装がバンドルされています。
    • 以前のAndroid(<26)では、ThreeTenABPプロジェクトはThreeTen-Backport(上記)を採用しています。ThreeTenABPの使用方法…を参照してください。

ThreeTen-エクストラプロジェクトでは、追加のクラスでjava.timeを拡張します。このプロジェクトは、java.timeに将来追加される可能性があることを証明する場です。あなたはここにいくつかの有用なクラスのような見つけることがIntervalYearWeekYearQuarter、および多くを



27

Javaバージョン7の場合

Oracleのドキュメントに従ってください:http : //docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

X-ISO 8601タイムゾーンに使用されます

TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());

System.out.println(nowAsISO);

DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
//nowAsISO = "2013-05-31T00:00:00Z";
Date finalResult = df1.parse(nowAsISO);

System.out.println(finalResult);

つまり、タイムゾーンが必要です。ISO 8601によると、これはオプションです。これが唯一のISO 8601の特定のサブセット解析するようになど、秒です
Timmmm

1
Java 1.8
チアゴペレイラ

20

DatatypeConverterソリューションは、すべてのVMで機能するわけではありません。次は私のために働きます:

javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar("2011-01-01Z").toGregorianCalendar().getTime()

私はjodaがそのままでは機能しないことを発見しました(特に、日付のタイムゾーンを指定した上記の例では、有効でなければなりません)


15

使うべきだと思います

DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")

日付 2010-01-01T12:00:00Z


5
なぜこれは、76の賛成票で受け入れられた回答を含め、他の回答よりも優れた回答なのですか?
エリックロバートソン

3
@ErickRobertson:シンプルで、すぐに使用でき、柔軟性があり、変換なしで、ほとんどの人はタイムゾーンを気にしません。
TWiStErRob 2013

7
タイムゾーンを気にしないのであれば、時間を扱うのはあまり意味がありません!
ドリ

16
これはタイムゾーンを完全に無視します。これが起こっていることに気づくまでこれを使用していたため、JodaTimeに切り替えました。
Joshua Pinter、

3
タイムゾーンを破棄すると、ある時点でエラーが発生するだけです。
Bart van Kuik 14年

10

ISO8601タイムスタンプを解析するもう1つの非常に簡単な方法は、次のものを使用すること org.apache.commons.lang.time.DateUtilsです。

import static org.junit.Assert.assertEquals;

import java.text.ParseException;
import java.util.Date;
import org.apache.commons.lang.time.DateUtils;
import org.junit.Test;

public class ISO8601TimestampFormatTest {
  @Test
  public void parse() throws ParseException {
    Date date = DateUtils.parseDate("2010-01-01T12:00:00+01:00", new String[]{ "yyyy-MM-dd'T'HH:mm:ssZZ" });
    assertEquals("Fri Jan 01 12:00:00 CET 2010", date.toString());
  }
}

10

Java 8以降、これを行うための完全に新しい公式にサポートされた方法があります。

    String s = "2020-02-13T18:51:09.840Z";
    TemporalAccessor ta = DateTimeFormatter.ISO_INSTANT.parse(s);
    Instant i = Instant.from(ta);
    Date d = Date.from(i);

2
ストリングがインスタント形式で、末尾Zがオフセットである場合、これを明示的に指定する必要はありません。ただInstant i = Instant.parse(s);。質問の文字列にはが+01:00ありましたが、その場合DateTimeFormatter.ISO_INSTANTは機能しません(少なくとも私のJava 11では機能しません)。
Ole VV

2
@ OleV.V。(docs.oracle.com/javase/8/docs/api/java/time/format/…)のISO_OFFSET_DATE_TIMEようなオフセットで日付をフォーマットするために使用できます+01:00
Lucas Basquerotto

1
それは本当です、@ LucasBasquerotto。そのフォーマッターについては明示的に言及していませんが、AdamBasil Bourqueによる回答はすでに同様のことをしています。
Ole VV

6

java.time

Java 8では、java.time.ZonedDateTimeクラスとその静的parse(CharSequence text)メソッドを使用できることに注意してください。


質問の入力文字列には、UTCからのオフセットのみがあり、完全なタイムゾーンはありません。したがってInstantZonedDateTimeここでは適切ですZonedDateTime
バジルブルク

6

Java 7以降の回避策は、SimpleDateFormatを使用することです。
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);

このコードは、次のようなISO8601形式を解析できます。

  • 2017-05-17T06:01:43.785Z
  • 2017-05-13T02:58:21.391+01:00

しかし、Java6では、文字がSimpleDateFormat理解できず、Xスロー
IllegalArgumentException: Unknown pattern character 'X'
されます。ISO8601の日付を、Java 6で読み取り可能な形式に正規化する必要がありSimpleDateFormatます。

public static Date iso8601Format(String formattedDate) throws ParseException {
    try {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);
        return df.parse(formattedDate);
    } catch (IllegalArgumentException ex) {
        // error happen in Java 6: Unknown pattern character 'X'
        if (formattedDate.endsWith("Z")) formattedDate = formattedDate.replace("Z", "+0000");
        else formattedDate = formattedDate.replaceAll("([+-]\\d\\d):(\\d\\d)\\s*$", "$1$2");
        DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
        return df1.parse(formattedDate);
    }
}

上記の方法は、[置き換えるためZ+0000]または[ +01:00+0100エラーは、Java 6で発生したとき](あなたは、if文でのtry / catchをJavaのバージョンを検出し、置き換えることができます)。


いいえ、Dateおよびなどの厄介な古い日時クラスSimpleDateFormatは、設計が不十分で、混乱し、欠陥があります。それらは現在レガシーであり、Java 8以降に組み込まれたjava.timeクラスに取って代わられました。Java 6およびJava 7の場合、java.time機能の多くはThreeTen-Backportプロジェクトにバックポートされています。これらのレガシークラスを使用するよりも、ライブラリをアプリに追加する方がはるかに優れています。java.timeの1行のソリューション:OffsetDateTime.parse( "2010-01-01T12:00:00+01:00" )
Basil Bourque

5

同じ問題に直面し、次のコードで解決しました。

 public static Calendar getCalendarFromISO(String datestring) {
    Calendar calendar = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault()) ;
    SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
    try {
        Date date = dateformat.parse(datestring);
        date.setHours(date.getHours() - 1);
        calendar.setTime(date);

        String test = dateformat.format(calendar.getTime());
        Log.e("TEST_TIME", test);

    } catch (ParseException e) {
        e.printStackTrace();
    }

    return calendar;
}

以前使用していた SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.getDefault());

しかし、その後、私は例外の主な原因だった見つけyyyy-MM-dd'T'HH:mm:ss.SSSZ

だから私は使った

SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());

それは私にとってはうまくいきました。


joda-time、XML apiなどを使用せずに必要なものだけです。ちょうど正しいパターン。
フィリップジョセフィ2016年


4

ここでの優れた答えが示すように、Javaには日時を解析するためのさまざまな方法があります。しかし、驚くべきことに、Javaの時間クラスはISO 8601を完全に実装していません。

Java 8では、次のことをお勧めします。

ZonedDateTime zp = ZonedDateTime.parse(string);
Date date = Date.from(zp.toInstant());

これは、UTCと「2017-09-13T10:36:40Z」や「2017-09-13T10:36:40 + 01:00」のようなオフセットのある例の両方を処理します。ほとんどのユースケースでそれを行います。

しかし、それはのような例扱えないだろう「2017-09-13T10を:36:40 + 01」、これ有効なISO 8601日時。
「2017-09-13」のように、日付のみを処理することもできません。

これらを処理する必要がある場合は、最初に正規表現を使用して構文を確認することをお勧めします。

多くのコーナーケースを含むISO 8601の例の良いリストがあります:https : //www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/ I'mそれらすべてに対処できるJavaクラスを認識していません。


OffsetDateTimeし、概念的にはより良いオフセットで日時を一致させます。
Ole VV

@ OleV.Vさん、こんにちは。提案をありがとう。悲しいことに、No:OffsetDateTime.parse()は、いくつかの有効なISO 8601文字列、たとえば「2017-09-13T10:36:40 + 01」や「2017-09-13」に対して例外をスローします
Daniel Winterstein

OffsetDateTime処理する例を処理することだけを意味しますZonedDateTime。私はそれが処理しない例のどれも処理しないと思いますZonedDateTime。その意味では、それは改善ではありません(しかし、より悪くはありません)。すみません、はっきりしていませんでした。
Ole VV

1
現状を考えると、これは2020年に受け入れられる答えになるはずです。
slashCoder

3

Apache Jackrabbitは日付の永続化にISO 8601形式を使用し、それらを解析するヘルパークラスがあります。

org.apache.jackrabbit.util.ISO8601

jackrabbit-jcr-commonsが付属しています。


Jackrabbitのサブセットは機能するかもしれませんが、本格的な専用ライブラリを使用する方が理にかなっています。Javaでは、Joda-Timeまたはjava.timeを意味します。
バジルブルク2014

3

他の人が述べたように、AndroidはSDKに含まれているクラスを使用してISO 8601日付の解析/フォーマットをサポートする良い方法がありません。このコードを複数回書いたので、ついにISO 8601とRFC 1123の日付のフォーマットと解析をサポートするDateUtilsクラスを含むGistを作成しました。Gistには、Gistがサポートするものを示すテストケースも含まれています。

https://gist.github.com/mraccola/702330625fad8eebe7d3


2

JAVA 1.7のSimpleDateFormatには、ISO 8601形式のクールなパターンがあります。

クラスSimpleDateFormat

これが私がしたことです:

Date d = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
         Locale.ENGLISH).format(System.currentTimeMillis());

2
Zフォーマット文字列がISO 8601タイムゾーンではない場合、ISO 8601タイムゾーンが必要な場合はX(またはXXまたはXXX)を使用する必要があります
Vojta

dは文字列型です
Tim Child

1

次のようにします。

public static void main(String[] args) throws ParseException {

    String dateStr = "2016-10-19T14:15:36+08:00";
    Date date = javax.xml.bind.DatatypeConverter.parseDateTime(dateStr).getTime();

    System.out.println(date);

}

出力は次のとおりです。

2016年10月19日水曜日15:15:36 CST


1

次のような文字列を使用 LocalDate.parse(((String) data.get("d_iso8601")),DateTimeFormatter.ISO_DATE)


1

https://en.wikipedia.org/wiki/ISO_8601のように、1つのJavaライブラリでもすべてのISO 8601日付形式をサポートしていないことに驚いています。Joda DateTimeはそれらのほとんどをサポートしていましたが、すべてではないため、それらすべてを処理するカスタムロジックを追加しました。これが私の実装です。

import java.text.ParseException;
import java.util.Date;

import org.apache.commons.lang3.time.DateUtils;
import org.joda.time.DateTime;

public class ISO8601DateUtils {
	
	/**
	 * It parses all the date time formats from https://en.wikipedia.org/wiki/ISO_8601 and returns Joda DateTime.
	 * Zoda DateTime does not support dates of format 20190531T160233Z, and hence added custom logic to handle this using SimpleDateFormat.
	 * @param dateTimeString ISO 8601 date time string
	 * @return
	 */
	public static DateTime parse(String dateTimeString) {
		try {
			return new DateTime( dateTimeString );
		} catch(Exception e) {
			try {
				Date dateTime = DateUtils.parseDate(dateTimeString, JODA_NOT_SUPPORTED_ISO_DATES);
				return new DateTime(dateTime.getTime());
			} catch (ParseException e1) {
				throw new RuntimeException(String.format("Date %s could not be parsed to ISO date", dateTimeString));
			}
		}
	}
  
  	private static String[] JODA_NOT_SUPPORTED_ISO_DATES = new String[] {
			// upto millis
			"yyyyMMdd'T'HHmmssSSS'Z'",
			"yyyyMMdd'T'HHmmssSSSZ",
			"yyyyMMdd'T'HHmmssSSSXXX",
			
			"yyyy-MM-dd'T'HHmmssSSS'Z'",
			"yyyy-MM-dd'T'HHmmssSSSZ",
			"yyyy-MM-dd'T'HHmmssSSSXXX",
			
			// upto seconds
			"yyyyMMdd'T'HHmmss'Z'",
			"yyyyMMdd'T'HHmmssZ",
			"yyyyMMdd'T'HHmmssXXX",
			
			"yyyy-MM-dd'T'HHmmss'Z'", 
			"yyyy-MM-dd'T'HHmmssZ",
			"yyyy-MM-dd'T'HHmmssXXX",
			
			// upto minutes
			"yyyyMMdd'T'HHmm'Z'",
			"yyyyMMdd'T'HHmmZ",
			"yyyyMMdd'T'HHmmXXX",

			"yyyy-MM-dd'T'HHmm'Z'",
			"yyyy-MM-dd'T'HHmmZ",
			"yyyy-MM-dd'T'HHmmXXX",
			
			//upto hours is already supported by Joda DateTime
	};
}


1

ISO8601で日付を解析する方法と、LocalDateTimeがDSTを処理しないことを示す小さなテスト。

 @Test
    public void shouldHandleDaylightSavingTimes() throws ParseException {

        //ISO8601 UTC date format
        SimpleDateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");

        // 1 hour of difference between 2 dates in UTC happening at the Daylight Saving Time
        Date d1 = utcFormat.parse("2019-10-27T00:30:00.000Z");
        Date d2 = utcFormat.parse("2019-10-27T01:30:00.000Z");

        //Date 2 is before date 2
        Assert.assertTrue(d1.getTime() < d2.getTime());
        // And there is 1 hour difference between the 2 dates
        Assert.assertEquals(1000*60*60, d2.getTime() - d1.getTime());

        //Print the dates in local time
        SimpleDateFormat localFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm z Z", Locale.forLanguageTag("fr_CH"));
        localFormat.setTimeZone(TimeZone.getTimeZone("Europe/Zurich"));

        //Both dates are at 02h30 local time (because of DST), but one is CEST +0200 and the other CET +0100 (clock goes backwards)
        Assert.assertEquals("2019-10-27 02:30 CEST +0200", localFormat.format(d1));
        Assert.assertEquals("2019-10-27 02:30 CET +0100", localFormat.format(d2));

        //Small test that shows that LocalDateTime does not handle DST (and should not be used for storing timeseries data)
        LocalDateTime ld1 = LocalDateTime.ofInstant(d1.toInstant(), ZoneId.of("Europe/Zurich"));
        LocalDateTime ld2 = LocalDateTime.ofInstant(d2.toInstant(), ZoneId.of("Europe/Zurich"));

        //Note that a localdatetime does not handle DST, therefore the 2 dates are the same
        Assert.assertEquals(ld1, ld2);

        //They both have the following local values
        Assert.assertEquals(2019, ld1.getYear());
        Assert.assertEquals(27, ld1.getDayOfMonth());
        Assert.assertEquals(10, ld1.getMonthValue());
        Assert.assertEquals(2, ld1.getHour());
        Assert.assertEquals(30, ld1.getMinute());
        Assert.assertEquals(0, ld1.getSecond());

    }

3
以下のようなFYI、ひどく面倒日時クラスjava.util.Datejava.util.Calendarjava.text.SimpleDateFormat今のレガシーに取って代わられ、java.timeの Javaの8に、後に内蔵されたクラス。Oracleによるチュートリアル参照してください。
バジルブルク

LocalDateTimeタイムゾーンをまったく処理しないため、夏時間(DST)を処理しないのはあなたの言うとおりです。そのために必要ZonedDateTimeです。提案DateしてSimpleDateFormatいる—私見は悪い
Ole VV

1
確かにZonedDateTimeは機能します。また、java.time.Instantは、DSTを処理するための優れた代替手段でもあります。java.util.Dateは非推奨であり、使用すべきではないことを知っていますが、元の質問に答えていました:8601の文字列をjava.util.date ....に変換する方法
ddtxra

0

同様のニーズがありました。事前に正確な形式を知らなくても、ISO8601に準拠した任意の日付を解析できる必要があり、Androidでも機能する軽量のソリューションが必要でした。

私が自分のニーズをググったとき、私はこの質問に出くわしました、そして、AFAIUが私のニーズに完全に一致する答えがないことに気付きました。そこで私はjISO8601を開発し、Maven Centralにプッシュしました。

あなたに追加するだけですpom.xml

<dependency>
  <groupId>fr.turri</groupId>
  <artifactId>jISO8601</artifactId>
  <version>0.2</version>
</dependency>

そして、あなたは行ってもいいです:

import fr.turri.jiso8601.*;
...
Calendar cal = Iso8601Deserializer.toCalendar("1985-03-04");
Date date = Iso8601Deserializer.toDate("1985-03-04T12:34:56Z");

お役に立てば幸いです。


0

このように日付をフォーマットするだけで、Java 6ベースのアプリケーションで次のように機能しました。thymeleafプロジェクトには、欠落しているコロンを挿入するDateFormatクラスがありますJacksonThymeleafISO8601DateFormat

https://github.com/thymeleaf/thymeleaf/blob/40d27f44df7b52eda47d1bc6f1b3012add6098b3/src/main/java/org/thymeleaf/standard/serializer/StandardJavaScriptSerializer.java

ECMAScriptの日付形式の互換性のために使用しました。


-1

基本機能の礼儀:@wrygiel。

この関数は、ISO8601形式を、オフセット値を処理できるJava Dateに変換できます。ISO 8601定義に従って、オフセットはさまざまな形式で記述できます。

±[hh]:[mm]
±[hh][mm]
±[hh]

Eg:  "18:30Z", "22:30+04", "1130-0700", and "15:00-03:30" all mean the same time. - 06:30PM UTC

このクラスには、変換する静的メソッドがあります

  • ISO8601文字列からDate(Local TimeZone)オブジェクト
  • ISO8601文字列の日付
  • 夏時間は自動的に計算されます

ISO8601文字列のサンプル

/*       "2013-06-25T14:00:00Z";
         "2013-06-25T140000Z";
         "2013-06-25T14:00:00+04";
         "2013-06-25T14:00:00+0400";
         "2013-06-25T140000+0400";
         "2013-06-25T14:00:00-04";
         "2013-06-25T14:00:00-0400";
         "2013-06-25T140000-0400";*/


public class ISO8601DateFormatter {

private static final DateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
private static final DateFormat DATE_FORMAT_2 = new SimpleDateFormat("yyyy-MM-dd'T'HHmmssZ");
private static final String UTC_PLUS = "+";
private static final String UTC_MINUS = "-";

public static Date toDate(String iso8601string) throws ParseException {
    iso8601string = iso8601string.trim();
    if(iso8601string.toUpperCase().indexOf("Z")>0){
        iso8601string = iso8601string.toUpperCase().replace("Z", "+0000");
    }else if(((iso8601string.indexOf(UTC_PLUS))>0)){
        iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_PLUS));
        iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_PLUS), UTC_PLUS);
    }else if(((iso8601string.indexOf(UTC_MINUS))>0)){
        iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_MINUS));
        iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_MINUS), UTC_MINUS);
    }

    Date date = null;
    if(iso8601string.contains(":"))
        date = DATE_FORMAT_1.parse(iso8601string);
    else{
        date = DATE_FORMAT_2.parse(iso8601string);
    }
    return date;
}

public static String toISO8601String(Date date){
    return DATE_FORMAT_1.format(date);
}

private static String replaceColon(String sourceStr, int offsetIndex){
    if(sourceStr.substring(offsetIndex).contains(":"))
        return sourceStr.substring(0, offsetIndex) + sourceStr.substring(offsetIndex).replace(":", "");
    return sourceStr;
}

private static String appendZeros(String sourceStr, int offsetIndex, String offsetChar){
    if((sourceStr.length()-1)-sourceStr.indexOf(offsetChar,offsetIndex)<=2)
        return sourceStr + "00";
    return sourceStr;
}

}


2
注意してください-DateFormatと派生クラスはマルチスレッド互換ではありません!DATE_FORMAT_1やDATE_FORMAT_2などの静的なSimpleDateFormatオブジェクトを使用すると、ISO8601DateFormatter関数を呼び出す複数のスレッドが同じDateFormatオブジェクトを共有することになります。これにより、データが破損し、DateFormat呼び出しから誤った日付が返されます。これを修正するには、パターン文字列を定数にし、必要に応じてローカルのSimpleDateFormat変数を作成するだけです。これにより、各オブジェクトが1つのスレッドによってのみ使用されることが保証されます。
Theo

スレッドセーフティのより良い修正は、代わりにスレッドセーフティ用に構築された日時ライブラリを使用することです。Javaでは、その世界はJoda-Timeまたはjava.timeです。
バジルブルク14

-1

これは私にとって最もうまくいくように見えました:

public static Date fromISO8601_( String string ) {

    try {
            return new SimpleDateFormat ( "yyyy-MM-dd'T'HH:mm:ssXXX").parse ( string );
    } catch ( ParseException e ) {
        return Exceptions.handle (Date.class, "Not a valid ISO8601", e);
    }


}

JavaScriptの日付文字列をJavaに変換する必要があります。上記は推奨事項で動作することがわかりました。SimpleDateFormatを使用するいくつかの例がありましたが、それらは推奨されるサブセットではないようです。

http://www.w3.org/TR/NOTE-datetime

PLISTとJavaScript文字列などでサポートされています。

これは、ISO8601文字列の最も一般的な形式であり、優れたサブセットのようです。

彼らが与える例は:

1994-11-05T08:15:30-05:00 corresponds 
November 5, 1994, 8:15:30 am, US Eastern Standard Time.

 1994-11-05T13:15:30Z corresponds to the same instant.

私は高速版も持っています:

final static int SHORT_ISO_8601_TIME_LENGTH =  "1994-11-05T08:15:30Z".length ();
                                            // 01234567890123456789012
final static int LONG_ISO_8601_TIME_LENGTH = "1994-11-05T08:15:30-05:00".length ();


public static Date fromISO8601( String string ) {
    if (isISO8601 ( string )) {
        char [] charArray = Reflection.toCharArray ( string );//uses unsafe or string.toCharArray if unsafe is not available
        int year = CharScanner.parseIntFromTo ( charArray, 0, 4 );
        int month = CharScanner.parseIntFromTo ( charArray, 5, 7 );
        int day = CharScanner.parseIntFromTo ( charArray, 8, 10 );
        int hour = CharScanner.parseIntFromTo ( charArray, 11, 13 );

        int minute = CharScanner.parseIntFromTo ( charArray, 14, 16 );

        int second = CharScanner.parseIntFromTo ( charArray, 17, 19 );

        TimeZone tz ;

         if (charArray[19] == 'Z') {

             tz = TimeZone.getTimeZone ( "GMT" );
         } else {

             StringBuilder builder = new StringBuilder ( 9 );
             builder.append ( "GMT" );
             builder.append( charArray, 19, LONG_ISO_8601_TIME_LENGTH - 19);
             String tzStr = builder.toString ();
             tz = TimeZone.getTimeZone ( tzStr ) ;

         }
         return toDate ( tz, year, month, day, hour, minute, second );

    }   else {
        return null;
    }

}

...

public static int parseIntFromTo ( char[] digitChars, int offset, int to ) {
    int num = digitChars[ offset ] - '0';
    if ( ++offset < to ) {
        num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
        if ( ++offset < to ) {
            num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
            if ( ++offset < to ) {
                num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                if ( ++offset < to ) {
                    num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                    if ( ++offset < to ) {
                        num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                        if ( ++offset < to ) {
                            num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                            if ( ++offset < to ) {
                                num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                                if ( ++offset < to ) {
                                    num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return num;
}


public static boolean isISO8601( String string ) {
      boolean valid = true;

      if (string.length () == SHORT_ISO_8601_TIME_LENGTH) {
          valid &=  (string.charAt ( 19 )  == 'Z');

      } else if (string.length () == LONG_ISO_8601_TIME_LENGTH) {
          valid &=  (string.charAt ( 19 )  == '-' || string.charAt ( 19 )  == '+');
          valid &=  (string.charAt ( 22 )  == ':');

      } else {
          return false;
      }

    //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
    // "1 9 9 4 - 1 1 - 0 5 T 0 8 : 1 5 : 3 0 - 0 5 : 0 0

    valid &=  (string.charAt ( 4 )  == '-') &&
                (string.charAt ( 7 )  == '-') &&
                (string.charAt ( 10 ) == 'T') &&
                (string.charAt ( 13 ) == ':') &&
                (string.charAt ( 16 ) == ':');

    return valid;
}

ベンチマークはしていませんが、かなり高速になると思います。動作するようです。:)

@Test
public void testIsoShortDate() {
    String test =  "1994-11-05T08:15:30Z";

    Date date = Dates.fromISO8601 ( test );
    Date date2 = Dates.fromISO8601_ ( test );

    assertEquals(date2.toString (), date.toString ());

    puts (date);
}

@Test
public void testIsoLongDate() {
    String test =  "1994-11-05T08:11:22-05:00";

    Date date = Dates.fromISO8601 ( test );
    Date date2 = Dates.fromISO8601_ ( test );

    assertEquals(date2.toString (), date.toString ());

    puts (date);
}

-2

多くの人がやりたいことは、JSON日付文字列を解析することだと思います。このページにアクセスすると、JavaScript JSONの日付をJavaの日付に変換する可能性が高くなります。

JSON日付文字列がどのように見えるかを示すには:

    var d=new Date();
    var s = JSON.stringify(d);

    document.write(s);
    document.write("<br />"+d);


    "2013-12-14T01:55:33.412Z"
    Fri Dec 13 2013 17:55:33 GMT-0800 (PST)

JSON日付文字列は2013-12-14T01:55:33.412Zです。

日付はJSON仕様ではカバーされていませんが、上記は非常に具体的なISO 8601形式ですが、ISO_8601ははるかに大きく、非常に重要ですが単なるサブセットです。

参照してくださいhttp://www.json.org を参照してくださいhttp://en.wikipedia.org/wiki/ISO_8601 くださいhttp://www.w3.org/TR/NOTE-datetimeを

たまたま、JSONパーサーとPLISTパーサーを作成しました。どちらもISO-8601を使用していますが、同じビットは使用していません。

/*
    var d=new Date();
    var s = JSON.stringify(d);

    document.write(s);
    document.write("<br />"+d);


    "2013-12-14T01:55:33.412Z"
    Fri Dec 13 2013 17:55:33 GMT-0800 (PST)


 */
@Test
public void jsonJavaScriptDate() {
    String test =  "2013-12-14T01:55:33.412Z";

    Date date = Dates.fromJsonDate ( test );
    Date date2 = Dates.fromJsonDate_ ( test );

    assertEquals(date2.toString (), "" + date);

    puts (date);
}

私のプロジェクトでは、これを行う2つの方法を書きました。1つの標準、1つの高速。

繰り返しますが、JSON日付文字列はISO 8601の非常に具体的な実装です...

(私は別の回答で他の1つを投稿しましたが、これはPLIST日付で機能するはずですが、ISO 8601形式は異なります)。

JSONの日付は次のとおりです。

public static Date fromJsonDate_( String string ) {

    try {

        return new SimpleDateFormat ( "yyyy-MM-dd'T'HH:mm:ss.SSSXXX").parse ( string );
    } catch ( ParseException e ) {
        return Exceptions.handle (Date.class, "Not a valid JSON date", e);
    }


}

PLISTファイル(ASCII非GNUNext)もISO 8601を使用しますが、ミリ秒は使用しないため、ISO-8601の日付がすべて同じではありません。(少なくとも、milisを使用するものをまだ見つけていません。また、パーサーでタイムゾーンを完全にスキップしてOMGを見つけました)。

さて、高速バージョン(Boonでそれを見つけることができます)。

public static Date fromJsonDate( String string ) {

    return fromJsonDate ( Reflection.toCharArray ( string ), 0, string.length () );

}

Reflection.toCharArrayは、使用可能な場合は安全でないものを使用しますが、使用できない場合はデフォルトでstring.toCharArrayに設定されることに注意してください。

(Reflection.toCharArray(string)をstring.toCharArray()に置き換えることで、例からそれを取り除くことができます)。

public static Date fromJsonDate( char[] charArray, int from, int to ) {

    if (isJsonDate ( charArray, from, to )) {
        int year = CharScanner.parseIntFromTo ( charArray, from + 0, from + 4 );
        int month = CharScanner.parseIntFromTo ( charArray,  from +5,  from +7 );
        int day = CharScanner.parseIntFromTo ( charArray,  from +8,  from +10 );
        int hour = CharScanner.parseIntFromTo ( charArray,  from +11,  from +13 );

        int minute = CharScanner.parseIntFromTo ( charArray,  from +14,  from +16 );

        int second = CharScanner.parseIntFromTo ( charArray,  from +17,  from +19 );

        int miliseconds = CharScanner.parseIntFromTo ( charArray,  from +20,  from +23 );

        TimeZone tz = TimeZone.getTimeZone ( "GMT" );


        return toDate ( tz, year, month, day, hour, minute, second, miliseconds );

    }   else {
        return null;
    }

}

isJsonDateは次のように実装されます。

public static boolean isJsonDate( char[] charArray, int start, int to ) {
    boolean valid = true;
    final int length = to -start;

    if (length != JSON_TIME_LENGTH) {
        return false;
    }

    valid &=  (charArray [ start + 19 ]  == '.');

    if (!valid) {
        return false;
    }


    valid &=  (charArray[  start +4 ]  == '-') &&
            (charArray[  start +7 ]  == '-') &&
            (charArray[  start +10 ] == 'T') &&
            (charArray[  start +13 ] == ':') &&
            (charArray[  start +16 ] == ':');

    return valid;
}

とにかく...私の推測では、ここに来るかなりの数の人がJSON日付文字列を探している可能性があり、ISO-8601日付ですが、非常に具体的な解析が必要な非常に具体的な日付です。

public static int parseIntFromTo ( char[] digitChars, int offset, int to ) {
    int num = digitChars[ offset ] - '0';
    if ( ++offset < to ) {
        num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
        if ( ++offset < to ) {
            num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
            if ( ++offset < to ) {
                num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                if ( ++offset < to ) {
                    num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                    if ( ++offset < to ) {
                        num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                        if ( ++offset < to ) {
                            num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                            if ( ++offset < to ) {
                                num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                                if ( ++offset < to ) {
                                    num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return num;
}

https://github.com/RichardHightower/boonを参照してください 。BoonにはPLISTパーサー(ASCII)とJSONパーサーがあります。

JSONパーサーは、私が知る限り最速のJava JSONパーサーです。

ガトリングパフォーマンスの人物によって独立して検証されました。

https://github.com/gatling/json-parsers-benchmark

Benchmark                               Mode Thr     Count  Sec         Mean   Mean error        Units
BoonCharArrayBenchmark.roundRobin      thrpt  16        10    1   724815,875    54339,825    ops/s
JacksonObjectBenchmark.roundRobin      thrpt  16        10    1   580014,875   145097,700    ops/s
JsonSmartBytesBenchmark.roundRobin     thrpt  16        10    1   575548,435    64202,618    ops/s
JsonSmartStringBenchmark.roundRobin    thrpt  16        10    1   541212,220    45144,815    ops/s
GSONStringBenchmark.roundRobin         thrpt  16        10    1   522947,175    65572,427    ops/s
BoonDirectBytesBenchmark.roundRobin    thrpt  16        10    1   521528,912    41366,197    ops/s
JacksonASTBenchmark.roundRobin         thrpt  16        10    1   512564,205   300704,545    ops/s
GSONReaderBenchmark.roundRobin         thrpt  16        10    1   446322,220    41327,496    ops/s
JsonSmartStreamBenchmark.roundRobin    thrpt  16        10    1   276399,298   130055,340    ops/s
JsonSmartReaderBenchmark.roundRobin    thrpt  16        10    1    86789,825    17690,031    ops/s

ストリーム、リーダー、bytes []、char []、CharSequence(StringBuilder、CharacterBuffer)、およびString向けの最速のJSONパーサーを備えています。

以下のベンチマークを参照してください。

https://github.com/RichardHightower/json-parsers-benchmark


JSONに関するこの回答は、質問とは無関係です。さらに、ごく少数のJSONデータ型には「JSON日付」などがないため、この質問は正しくありません。:そして、今日、すべてこのコードは、ビルトインのJava機能へのシングルラインの呼び出しに置き換えることができますInstant.parse( "2013-12-14T01:55:33.412Z" )
バジルボーク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.