Java:日期解析,为什么会出现错误

Java:日期解析,为什么会出现错误,java,date,simpledateformat,datetime-parsing,unparseable,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 = da

前三行很好用。当我再次尝试将字符串解析为日期时,我得到一个错误。我怎样才能解决这个问题

错误如下所示:

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

我删除了与时区相关的简单日期格式中的Z,它给出了正确的输出,下面是代码片段

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,它给出了正确的输出,下面是代码片段

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]
为我工作。在模式的末尾使用“SSSZ”而不是“SZ”


为我工作。在模式的末尾用“SSSZ”代替“SZ”。

我想给出一个现代的答案。因为我不鼓励使用
SimpleDateFormat
,所以稍后将详细介绍这一点

java.time 这将生成一个类似于
2018-02-07T17:51:21.087+0100
的字符串,非常接近我认为您在问题中所追求的内容,并很好地解析了它。在格式模式字符串中使用
SSS
时,它总是在几秒钟内产生3个小数,并且通过解析也需要正好3个小数。例如,您可以使用
S
SSSSSS
获取1或6位小数。在我的Java 9上,
OffsetDateTime.now()
的精度为6位小数(微秒),因此如果我指定更少的值,我的格式将失去精度

编辑:为了向后兼容,您不能使用以下内容,但对于阅读本文的任何人,我希望提供一个没有显式格式化程序的变体:

    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);
生成的字符串中的两个差异是:

  • 它生成渲染精度所需的任意多组3位小数。在我的Java8上通常是3位小数,在Java9上通常是6位小数,但有时它会达到整数毫秒,产生的小数更少。它解析一个从0到9位小数的字符串,所以这在解析中不会出现问题。我始终保留原始
    OffsetDateTime
    对象的完整信息
  • UTC的偏移量用冒号表示,例如
    +01:00
  • 你的代码出了什么问题?
    SimpleDataFormat
    类已经过时很久了,而且出了名的麻烦,所以即使您目前还没有遇到问题,我仍然建议您放弃它,改用现代java日期和时间API
    java.time
    ,就像我上面所做的那样

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

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

    链接
    • 解释如何使用
      java.time

      • 我想提供一个现代的答案。因为我不鼓励使用
        SimpleDateFormat
        ,所以稍后将详细介绍这一点

        java.time 这将生成一个类似于
        2018-02-07T17:51:21.087+0100
        的字符串,非常接近我认为您在问题中所追求的内容,并很好地解析了它。在格式模式字符串中使用
        SSS
        时,它总是在几秒钟内产生3个小数,并且通过解析也需要正好3个小数。例如,您可以使用
        S
        SSSSSS
        获取1或6位小数。在我的Java 9上,
        OffsetDateTime.now()
        的精度为6位小数(微秒),因此如果我指定更少的值,我的格式将失去精度

        编辑:为了向后兼容,您不能使用以下内容,但对于阅读本文的任何人,我希望提供一个没有显式格式化程序的变体:

            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);
        
        生成的字符串中的两个差异是:

      • 它生成渲染精度所需的任意多组3位小数。在我的Java8上通常是3位小数,在Java9上通常是6位小数,但有时它会达到整数毫秒,产生的小数更少。它解析一个从0到9位小数的字符串,所以这在解析中不会出现问题。我始终保留原始
        OffsetDateTime
        对象的完整信息
      • UTC的偏移量用冒号表示,例如
        +01:00
      • 你的代码出了什么问题?
        SimpleDataFormat
        类已经过时很久了,而且出了名的麻烦,所以即使您目前还没有遇到问题,我仍然建议您放弃它,改用现代java日期和时间API
        java.time
        ,就像我上面所做的那样

        旧的
        SimpleDateFormat
        和现代的
        DateTimeFormatter
        之间的一个区别是,虽然现代格式化程序中的
        S
        表示秒的分数,但在
        SimpleDateFormat
        中,它表示毫秒,因此除3以外的任何数字都没有意义。然而,它接受其他数字。格式化时,格式化程序生成了足够毫秒的数字,例如,如果有21.089秒,则为
        89
        ,如果有13.214秒,则为
        214
        。前者不正确,21.089秒呈现为
        21.89
        。我坚信三位数的毫秒
            String text = dateTime.toString();
            OffsetDateTime test = OffsetDateTime.parse(text);