要解析Z(即UTC designator),您必须使用X 模式(如javadoc 中所述):
SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
String dateString = "2017-07-15T10:52:59Z";
Date newDate = mSimpleDateFormat.parse(dateString);
如果您仅使用 yyyy-MM-dd'T'HH:mm:ss 作为模式,SimpleDateFormat 将使用系统的默认时区并忽略 Z,从而给出不正确的结果:它会将日期/时间解析为默认时区中的 10:52 ,它可能与 UTC 中的 10:52 不同。通过使用X 模式,您可以获得正确的结果。
我还删除了Locale,因为此格式化程序不处理任何区域设置敏感信息(如月份和星期几名称),因此在这种情况下它不会影响解析(并且SimpleDateFormat 已经使用如果您不指定,则使用默认语言环境)。
PS:X 模式是在 JDK 7 中引入的。如果您使用的是旧版本,它将不可用。在这种情况下,您可以将 UTC 设置为格式化程序的时区:
SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
mSimpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
显然,这段代码假设输入始终为 UTC(最后是 Z)。
Java 新日期/时间 API
旧的类(Date、Calendar 和 SimpleDateFormat)有 lots of problems 和 design issues,它们正在被新的 API 取代。
对于 Android,您可以使用 ThreeTen Backport,它是 Java 8 新日期/时间类的出色反向移植。为了使它工作,你还需要ThreeTenABP(更多关于如何使用它here)。
由于输入字符串在ISO 8601 format,您可以轻松地将其解析为org.threeten.bp.OffsetDateTime:
String dateString = "2017-07-15T10:52:59Z";
OffsetDateTime odt = OffsetDateTime.parse(dateString);
然后,您可以使用 org.threeten.bp.DateTimeUtils 类轻松地将其转换为 java.util.Date:
Date date = DateTimeUtils.toDate(odt.toInstant());
如果输入始终为 UTC(始终以 Z 结尾),您也可以使用 org.threeten.bp.Instant:
String dateString = "2017-07-15T10:52:59Z";
Instant instant = Instant.parse(dateString);
Date date = DateTimeUtils.toDate(instant);
唯一的区别是Instant 只解析UTC 输入(以Z 结尾),而OffsetDateTime 接受任何有效的UTC 偏移量(如-03:00 或+05:30)。