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.
// displaying current date and time Calendar cal = Calendar.getInstance (); SimpleDateFormat simpleformat = new SimpleDateFormat ("E, dd MMM yyyy HH:mm:ss Z"); System.out.println ("Today's date and time = "+simpleformat.format (cal.getTime ())); Since we have used the Format and SimpleDateFormat class above, therefore import the following packages.
Date Format [YYYY]-[MM]-[DD]T[HH]:[MM]:[SS]Z Date Format [YYYY]-[MM]-[DD]T[HH]:[MM]:[SS]Z Comments PostPosting GuidelinesFormatting
Since we have used the Format and SimpleDateFormat class above, therefore import the following packages. With that, we have also used the Date − import java.text.Format; import java.text.SimpleDateFormat; import java.util.Date;
Regular Expression to Date Format [YYYY]-[MM]-[DD]T[HH]:[MM]:[SS]Z Toggle navigation RegEx TestingFrom Dan's Tools
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:
gb.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
you are initializing a DefaultDateTypeAdapter in this way:
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"));
}
where:
enUsFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
and localFormat = 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 that iso8601Format
is the same as enUsFormat
without milliseconds but with UTC timezone.
Parsing happens into deserializeToDate
method:
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);
}
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With