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

时间:2018-02-07 14:28:09

标签: java date simpledateformat datetime-parsing unparseable

    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]

3 个答案:

答案 0 :(得分:3)

    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"在模式的最后。

答案 1 :(得分:1)

我想提供现代答案。因为我不鼓励使用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对象的完整预设。
  2. UTC的偏移量使用冒号进行渲染,例如+01:00
  3. 您的代码出了什么问题?

    SimpleDateFormat类已经过时且非常麻烦,所以即使你目前没有遇到问题,我仍然会建议你放弃它并使用现代Java java.time相反,日期和时间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文档一致,该文档指出:“对于格式化,模式字母的数量是最小位数,较短的数字是零填充到此数量。对于解析,除非需要分隔两个相邻字段,否则将忽略模式字母的数量。“

    链接

答案 2 :(得分:0)

我删除了Z的简单日期格式,该格式与时区相关,这使得Correct out Put下面是片段。

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();
}