I have two field like below (pay attention that the first field has milliseconds section):
{
"updateTime":"2011-11-02T02:50:12.208Z",
"deliverTime":"1899-12-31T16:00:00Z"
}
I want to deserialize the Json string to an object with Gson, so I get a Gson
instance:
GsonBuilder gb = new GsonBuilder();
gb.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
gson = gb.create();
The first field is deserialized to Java date type: 2011-11-02 02:50:12.208 (looks like ignored the time zone section-‘Z’, that's I expected). However, the second field is deserialized to 1900-01-01 00:00:00 (I live in China, +8 GMT here), it seems that the time zone section-'Z' plays a part in deserialization.
Why the second field uses time zone section? It's not what I expected.
Quick answer
First string is correctly parsed using your date format and your local time zone, second one does not respect it, so will be parsed by a default
SimpleDateFormat
object that has not milliseconds ("yyyy-MM-dd'T'HH:mm:ss'Z' is the parsing format) and uses UTC timezone giving you a "shift" in time part.Full answer
To fully respond to your question you need to dive into Gson source code. More in particular you have to look at code of
DefaultDateTypeAdapter
that is used to parse dates. You can find all this code at link, but for quick reference I will copy here most relevant parts.When you call this in the builder:
you are initializing a DefaultDateTypeAdapter in this way:
where:
enUsFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
andlocalFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US)
since the string you have passed in the builder.
Pay attention that
Locale.US
is not a timezone and thatiso8601Format
is the same asenUsFormat
without milliseconds but with UTC timezone.Parsing happens into
deserializeToDate
method:where all of three date formats are used in a waterfall approach.
First Json string: "2011-11-02T02:50:12.208Z". It's parsed immediately by
localFormat
since has milliseconds and gives you the result you expect using your timezone.Second Json string: "1899-12-31T16:00:00Z". It won't be parsed by
localFormat
since has not milliseconds, so second chance is enUsFormat that is the same pattern, except for the locale. So it will fail at the same way.Last chance to parse:
iso8601Format
, it will, it has no milliseconds, BUT, for construction, it as also a UTC time zone, so it will parse date as UTC while the others parsed using your timezone.