Java: 日期解析,为什么会报错

Java: Date parsing, why do I get an error

    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]

我删除了与时区相关的简单日期格式的 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();
}
    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 对象的完整预测。
  2. 与 UTC 的偏移量用冒号呈现,例如 +01:00

你的代码出了什么问题?

SimpleDateFormat class 早已过时且出了名的麻烦,所以即使你目前没有遇到问题,我仍然建议你放弃它并使用 java.time,现代 Java 日期和时间 API,而不是像我在上面所做的那样。

SimpleDateFormat 和现代 DateTimeFormatter 之间的一个区别是,虽然 S 在现代格式化程序中表示秒的分数,但在 SimpleDateFormat 中表示毫秒,所以除三之外的任何其他数字都是没有意义的。但是,它接受其他数字。格式化时,您的格式化程序为毫秒生成了足够的数字,例如 89 如果有 21.089 秒或 214 当您有 13.214 时 question.The 前者是不正确的,21.089 秒是呈现为 21.89。我坚信,当你只有一个 S 时,三位数的毫秒数会导致你的解析失败。在我的 Java 8 和 9 上,它可以工作并且还将 21.89 解析为 21 秒 89 毫秒,因此错误会消失。

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

Link