Java:日期解析,为什么我会收到错误

Date date = new Date(); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SZ");//2018-02-05T18:00:51.001+0000 String text = dateFormat.format(date); Date test = dateFormat.parse(text); 

前三行很好。 当我尝试再次将字符串解析为日期时,我收到错误。 我怎么解决这个问题?

错误如下所示:

 Caused by: java.text.ParseException: Unparseable date: "2018-02-07T15:32:13.214+0100" at java.text.DateFormat.parse(DateFormat.java:366) ~[na:1.8.0_151] at TimeRange.parseDateFromIsoString(TimeRange.java:33) ~[classes/:na] 

  Date date = new Date(); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");//2018-02-05T18:00:51.001+0000 String text = dateFormat.format(date); try { Date test = dateFormat.parse(text); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } 

为我工作。 在模式结束时使用“SSSZ”而不是“SZ”。

我想提出现代的答案。 因为我不鼓励使用SimpleDateFormat ,稍后会详细介绍。

java.time

  OffsetDateTime dateTime = OffsetDateTime.now(ZoneId.of("Europe/Rome")); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSxx"); String text = dateTime.format(formatter); OffsetDateTime test = OffsetDateTime.parse(text, formatter); 

这会产生一个像2018-02-07T17:51:21.087+0100这样的字符串,非常接近我认为你在问题中所追求的,并且很好地解析它。 使用格式模式字符串中的SSS ,它始终在秒上生成3个小数,并且通过解析也需要正好3个小数。 例如,您可以使用SSSSSSS获得1或6位小数。 在我的Java 9上, OffsetDateTime.now()具有6位小数(微秒)的精度,因此如果我指定更少,我将失去格式的精度。

编辑:为了向后兼容,你不能使用以下,但对于任何阅读的人我想呈现一个没有明确的格式化程序的变体:

  String text = dateTime.toString(); OffsetDateTime test = OffsetDateTime.parse(text); 

生成的字符串中的两个差异是:

  1. 它生成尽可能多的3个小数组,以提供精度。 通常在我的Java 8上有3个小数,在我的Java 9上有6个小数,但有时它会达到一个圆形的毫秒并产生更少的小数。 它解析一个包含从0到9小数的所有内容的字符串,因此这不会在解析时出现问题。 而且我总是保留原始OffsetDateTime对象的完整OffsetDateTime
  2. UTC的偏移量用冒号表示,例如+01:00

您的代码出了什么问题?

SimpleDateFormat类已经过时且非常麻烦,所以即使你目前没有遇到任何问题,我仍然建议你删除它并使用java.time ,现代Java日期和时间API,而不是做上面。

SimpleDateFormat和现代DateTimeFormatter之间的一个区别是,现代格式化程序中的S意味着小数秒,而在SimpleDateFormat它意味着毫秒,因此除了三个之外的任何其他数字都是无意义的。 但是,它接受其他数字。 格式化时,格式化程序产生足够数字的毫秒数,例如89如果有21.089秒)或214如果问题中有13.214)。前者不正确,21.089秒呈现为21.89 。 我坚信,当你只有一个S时,三位数毫秒会导致你的解析失败。 在我的Java 8和9上它可以工作,并且还解析21.89为21秒89毫秒,所以错误平衡了。

此行为与Java 9文档一致,该文档指出:“对于格式化,模式字母的数量是最小位数,较短的数字是零填充到此数量。 对于解析,除非需要分隔两个相邻的字段,否则忽略模式字母的数量。“

链接

  • Oracle教程:Date Time解释了如何使用java.time
  • Java 9的SimpleDateFormat文档

我删除了Z的简单日期格式,该格式与时区有关,这给出了正确的放置下面是片段。

 Date date = new Date(); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S");//2018-02-05T18:00:51.001+0000 String text = dateFormat.format(date); try { Date test = dateFormat.parse(text); } catch (ParseException e) { e.printStackTrace(); }