2013-02-16 8 views
9

に私は2つのフィールド(最初のフィールドは、ミリ秒部分持っていることを注意を払う)以下のように持っている:DateFormatのパターン "YYYY-MM-dd'T'HH:MM:ss.SSS'Z」" Gson

{ 
    "updateTime":"2011-11-02T02:50:12.208Z", 
    "deliverTime":"1899-12-31T16:00:00Z" 
} 

私はGsonを持つオブジェクトにJSON文字列をデシリアライズしたいので、私はGsonインスタンスを取得:2011-11-02 2時50分:最初のフィールドは、Javaの日付型にデシリアライズされ

GsonBuilder gb = new GsonBuilder(); 
gb.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); 
gson = gb.create(); 

:12.208(tiを無視したようです私のゾーンセクション - 'Z '、それは私が期待している)。ただし、2番目のフィールドは、1900-01-01 00:00:00(私は中国に居住し、ここでは+8 GMT)にデシリアライズされています。タイムゾーンセクション 'Z'はデシリアライゼーションに参加しているようです。

なぜ2番目のフィールドでタイムゾーンセクションが使用されますか?それは私が期待したものではありません。

+0

私にとっては、2番目の日付文字列( 'java.text.ParseException:Unparseable date:" 1899-12-31T16:00:00Z "')を解析できません。どのバージョンのGsonを使用していますか? –

+0

なぜあなたはTとZを簡単な引用符で囲みますか?私はしません(gson 1.7.1) –

+0

ちょうどあなたにもっとフィードバックを与えるために、私のパターンMM/dd/yy HH:mm:ss SSSZは私に次のような日付を与えます:02/20/13 18:03: 089 + 0100 –

答えて

12

クイック答え

最初の文字列が正しく秒1はそれを尊重していない、あなたの日付形式とローカルタイムゾーンを使用して解析されているので、ミリ秒( "YYYYをしていないデフォルトSimpleDateFormatオブジェクトによって解析されます-MM-dd'T'HH:MM:完全に対応するためss'Zは、」構文解析フォーマットである)とあなたの時間の一部で 『シフト』を与えてUTCタイムゾーンを使用しています

全解答

ダイビングに必要な質問Gsonソースコードに変換します。特に、日付の解析に使用されるDefaultDateTypeAdapterのコードを参照する必要があります。このコードはすべてlinkにありますが、ここでは最も関連性の高い部分を簡単に紹介します。あなたはビルダーでこれを呼び出す

gb.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); 

あなたがこの方法でDefaultDateTypeAdapterを初期化されています

DefaultDateTypeAdapter(DateFormat enUsFormat, DateFormat localFormat) { 
    this.enUsFormat = enUsFormat; 
    this.localFormat = localFormat; 
    this.iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); 
    this.iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC")); 
} 

  1. enUsFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
  2. localFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US)

ビルダーで渡した文字列以降です。

Locale.USはタイムゾーンではなく、は、enUsFormatと同じですが、ミリ秒単位ではなく、UTCタイムゾーンであることに注意してください。

private Date deserializeToDate(JsonElement json) { 
    synchronized (localFormat) { 
     try { 
     return localFormat.parse(json.getAsString()); 
     } catch (ParseException ignored) { 
     } 
     try { 
     return enUsFormat.parse(json.getAsString()); 
     } catch (ParseException ignored) { 
     } 
     try { 
     return iso8601Format.parse(json.getAsString()); 
     } catch (ParseException e) { 
     throw new JsonSyntaxException(json.getAsString(), e); 
     } 
    } 
    } 

3つの日付フォーマットのすべてが滝のアプローチで使用されている:

解析は、deserializeToDate方法に起こります。

最初のJson文字列: "2011-11-02T02:50:12.208Z"。それはすぐにlocalFormatによって解析されるので、ミリ秒があり、あなたのタイムゾーンを使用すると予想される結果が得られます。

第2のJson文字列: "1899-12-31T16:00:00Z"。 localFormatは解析されません。ミリ秒単位ではないため、2回目の入力はと同じパターンで、ロケールを除いてです。それで、同じ方法で失敗します。解析する

最終チャンス:iso8601Formatを他の人があなたのタイムゾーンを使用して解析しながら、それはUTCとして日付を解析しますので、それは、それは、また、UTCタイムゾーンとして、建設のために、それを何ミリ秒、しかしを持っていません。