【问题标题】:Java: Date parsing, why do I get an errorJava:日期解析,为什么会出错
【发布时间】:2018-07-17 21:19:09
【问题描述】:
    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]

【问题讨论】:

  • 你得到什么错误?
  • 您的代码在这里运行良好。什么错误?

标签: java date simpledateformat datetime-parsing unparseable


【解决方案1】:
    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”。

【讨论】:

    【解决方案2】:

    我想提供现代答案。因为我不鼓励使用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 类早已过时并且出了名的麻烦,所以即使你目前没有遇到过问题,我仍然建议你放弃它并使用现代 Java 日期和时间 API java.time ,而是像我在上面所做的那样。

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

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

    链接

    【讨论】:

    • 遗憾的是,我无法更改日期字符串的格式,因为我必须向后兼容,这似乎不适用于它。不过谢谢 :) 它肯定更好
    • 在这种情况下,您应该在没有明确格式化程序的情况下忽略我的变体。格式化程序 DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSxx") (with 3 SSS) 解析并格式化问题中的示例,2018-02-05T18:00:51.001+0000 和 2018-02-07T15:32:13.214+0100,很好,所以请继续。
    【解决方案3】:

    我删除了与时区相关的简单日期格式的 Z 给出了正确的输出 下面是 sn-p。

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

    【讨论】:

    • 但是我得到的日期有一个时区
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多