快速解答
第一个字符串使用您的日期格式和本地时区正确解析,第二个字符串不尊重它,因此将由没有毫秒的默认对象解析(“yyyy-MM-dd'T'HH:mm:ss'Z'是解析格式),并使用UTC时区为您提供时间部分的”移位”。SimpleDateFormat
完整答案
要完全回答您的问题,您需要深入研究Gson源代码。更具体地说,您必须查看用于解析日期的代码。您可以在链接中找到所有这些代码,但为了快速参考,我将在这里复制最相关的部分。DefaultDateTypeAdapter
当您在构建器中调用此参数时:
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"));
}
哪里:
-
enUsFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
和
localFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US)
自您在构建器中传递的字符串以来。
请注意,这不是一个时区,这与没有毫秒但使用UTC时区相同。Locale.US
iso8601Format
enUsFormat
解析发生在方法中:deserializeToDate
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);
}
}
}
其中,所有三种日期格式都用于瀑布方法。
第一个 Json 字符串:“2011-11-02T02:50:12.208Z”。它立即解析,因为有毫秒,并为您提供使用时区预期的结果。localFormat
第二个 Json 字符串:“1899-12-31T16:00:00Z”。它不会被解析,因为没有毫秒,所以第二次机会是enUsFormat是相同的模式,除了区域设置。因此,它将以同样的方式失败。localFormat
解析的最后机会:,它将没有毫秒,但是,对于构造,它也是一个UTC时区,因此它将解析日期为UTC,而其他时间则使用您的时区进行解析。iso8601Format