java.text.ParseException:无法解析的日期“yyyy-MM-dd'T'HH:mm:ss.SSSZ” - SimpleDateFormat

新手上路,请多包涵

对于查找此异常的错误的任何帮助,我将不胜感激:

 java.text.ParseException: Unparseable date: "2007-09-25T15:40:51.0000000Z"

和以下代码:

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
Date date = sdf.parse(timeValue);
long mills = date.getTime();
this.point.time = String.valueOf(mills);

它用 Date date = sdf.parse(timeValue); 抛出异常。

timeValue = "2007-09-25T15:40:51.0000000Z"; ,如异常。

谢谢。

原文由 Jacob 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

Z 代表时区字符。需要引用它:

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

原文由 Reimeus 发布,翻译遵循 CC BY-SA 3.0 许可协议

(答案现已广泛修改,感谢评论中的更正)

Java 7 中,您可以使用 X 模式来匹配 ISO8601 时区,其中包括特殊的 Z (UTC) 值。

X 模式也支持显式时区,例如 +01:00

这种方法正确地尊重时区指示符,并避免将其仅视为字符串的问题,从而避免错误地解析本地时区而不是 UTC 或其他时区中的时间戳。

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
Date date = sdf.parse("2007-09-25T15:40:51Z");
Date date2 = sdf.parse("2007-09-25T15:40:51+01:00");

这也可以与毫秒一起使用:

 SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
Date date3 = sdf2.parse("2007-09-25T15:40:51.500Z");

但是,正如其他人指出的那样,您的格式有 7 位小数秒,大概是十分之一微秒。如果是这样, SimpleDateFormat 无法处理此问题,您将得到不正确的结果,因为每 0.1 微秒将被解释为一毫秒,从而可能导致高达 10,000 秒(数小时)的整体错误。

在极端情况下,如果小数秒值为 0.9999999 秒,则会被错误地解释为 9999999 _毫秒_,即大约 167 分钟或 2.8 小时。

 // Right answer, error masked for zero fractional seconds
Date date6 = sdf2.parse("2007-09-25T15:40:51.0000000Z");
// Tue Sep 25 15:40:51 GMT 2007

// Error - wrong hour
// Should just half a second different to the previous example
Date date5 = sdf2.parse("2007-09-25T15:40:51.5000000Z");
// Tue Sep 25 17:04:11 GMT 2007

如您的示例所示,当小数秒为零时会隐藏此错误,但只要它们不为零就会显示出来。

在许多情况下可以检测到此错误,并通过关闭“宽松”解析来减少其影响,默认情况下,该解析将接受超过一秒的小数部分并将其转移到秒/分钟/小时部分:

 sdf2.setLenient(false);
sdf2.parse("2007-09-25T15:40:51.5000000Z");
// java.text.ParseException: Unparseable date: "2007-09-25T15:40:51.5000000Z"

这将捕获毫秒值大于 999 的情况,但不检查位数,因此它只是部分和间接的防止毫秒/微秒不匹配的保护措施。然而,在许多现实世界的数据集中,这会捕获大量错误,从而指出根本问题,即使某些值漏掉了。

我建议 始终 禁用宽松解析,除非您有特定需要,因为它会捕获大量错误,否则这些错误会被静默隐藏并传播到下游数据中。

如果您的小数秒始终为零,那么您可以在此处使用其中一种解决方案,但如果稍后在非零小数秒上使用代码,则存在它们将无法工作的风险。您可能希望对此进行记录和/或断言该值为零,以避免以后出现错误。

否则,您可能需要将小数秒转换为毫秒,以便 SimpleDateFormat 可以正确解释它们。或者使用一种较新的日期时间 API。

原文由 DNA 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题