【问题标题】:java.text.ParseException: Unparseable date “yyyy-MM-dd'T'HH:mm:ss.SSSXXX” - SimpleDateFormatjava.text.ParseException:无法解析的日期“yyyy-MM-dd'T'HH:mm:ss.SSSXXX” - SimpleDateFormat
【发布时间】:2018-02-22 08:52:35
【问题描述】:

我使用以下代码解析datetime

String parseDate(String tranDateTime, String originalDateFormat, String toDateFormat) throws ParseException {
    SimpleDateFormat originalMonthYear = new SimpleDateFormat(originalDateFormat);
    Date date = originalMonthYear.parse(tranDateTime);

    SimpleDateFormat formatter = new SimpleDateFormat(toDateFormat);
    return formatter.format(date);
}

并尝试解析如下日期时间值:

parseDate("2017-08-16T00:00:00Z", 
          "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", "yyyy-MM-dd HH:mm:ss");

抛出异常:

java.text.ParseException:无法解析的日期:“2017-08-16T00:00:00Z”

但是,当我将日期值更改为 "2017-08-16T02:54:15.537Z" 时,该函数运行良好。我不知道为什么。

【问题讨论】:

  • “我不知道为什么?”因为你告诉你的程序这样做。该模式包括 .SSS 毫秒部分。
  • 2017-08-16T02:54:15.537Z 之所以有效,是因为您使用了正确的秒部分格式 SS.SSS。
  • SimpleDateFormatDate 早已过时,尤其是前者非常麻烦。我建议您不要使用它们,而是使用java.time, the modern Java date and time API,。作为奖励,OffsetDateTime.parse(String) 将在没有任何显式格式化程序的情况下解析您的两个示例字符串。
  • Instant.parse( "2017-08-16T00:00:00Z" ) 工作得很好,就像you can see in IdeOne.com。是时候放弃那些可怕的旧遗留课程DateSimpleDateFormat。现在被 Java 8 和 Java 9 中内置的 java.time 类所取代。请参阅 Tutorial by Oracle
  • @PeterT,也许您应该考虑接受答案?如果不是太难选择。见What should I do when someone answers my question?

标签: java date simpledateformat datetime-parsing


【解决方案1】:

问题来自:

Date date = originalMonthYear.parse(tranDateTime);

这个日期

2017-08-16T00:00:00Z

与模式不匹配

yyyy-MM-dd'T'HH:mm:ss.SSSXXX

因为缺少毫秒(SSS 部分)

所以

Date date = originalMonthYear.parse(tranDateTime);

抛出异常

java.text.ParseException: Unparseable date: "2017-08-16T00:00:00Z"

解决方案

  • 将您的日期 2017-08-16T00:00:00Z 更改为 2017-08-16T00:00:00.000Z(将毫秒添加到您的日期)
  • 将您的模式 yyyy-MM-dd'T'HH:mm:ss.SSSXXX 更改为 yyyy-MM-dd'T'HH:mm:ssXXX(从您的模式中删除毫秒)

【讨论】:

  • 此外,从数据库中检索的日期时间值可以是“2017-08-16T00:00:00Z”或“2017-08-16T00:00:15.537Z”。我们有解析这两种格式的通用模式吗?如果不是,我必须使用 if 条件来解析每种格式
  • @PeterT 您可以轻松检查String 的长度以解析以了解要使用的模式。
  • 我建议你只坚持一种模式。用于表示日期和时间的国际标准化组织 (ISO) 是 ISO_8601,它定义使用此 DateTime 模式 yyyy-MM-dd'T'HH:mm:ssXXX(即:2018-02-20T18:50:31Z
  • @PeterT,您可以正确使用抛出的异常来使用多种格式模式,看看我编辑的答案。
【解决方案2】:

您在评论中提问:

此外,日期时间值可以是“2017-08-16T00:00:00Z”或 从数据库中检索到“2017-08-16T00:00:15.537Z”。我们有没有 解析这两种格式的通用模式?

更好的是,它们都可以在 没有显式模式的情况下进行解析:

    System.out.println(OffsetDateTime.parse("2017-08-16T00:00:00Z"));
    System.out.println(OffsetDateTime.parse("2017-08-16T00:00:15.537Z"));

打印出来:

2017-08-16T00:00Z
2017-08-16T00:00:15.537Z

要格式化,例如:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    System.out.println(OffsetDateTime.parse("2017-08-16T00:00:00Z").format(formatter));

打印出来

2017-08-16 00:00:00

我正在使用并热烈推荐 java.time,这是现代 Java 日期和时间 API。 SimpleDateFormatDate 早已过时,尤其是前者出了名的麻烦。现代 API 更易于使用。

您的字符串(尽管存在差异)都符合 ISO 8601,即日期和时间格式的标准。 java.time 类无需任何显式格式化程序即可解析这些格式。

链接:Oracle tutorial: Date Time解释如何使用java.time

【讨论】:

    【解决方案3】:

    2017-08-16T00:00:00Z 更改为2017-08-16T00:00:00.000Z,它对我有用。

    【讨论】:

    • 这是正确答案。您正在使用SSSXXX 设置时间格式,因此您期望以毫秒和时区为单位。您使用 Z 作为时区,但没有以毫秒为单位的测量值,因此您的解析器无法解析它。
    【解决方案4】:

    问题来源:

    问题来自尝试使用日期格式 yyyy-MM-dd'T'HH:mm:ss.SSSXXX 解析日期值 2017-08-16T00:00:00Z,在该行中:

    Date date = originalMonthYear.parse(tranDateTime);
    

    查看值和格式的区别:

     ______________________________
    |2017|08|16| T |00|00|00Z      |
    |yyyy|MM|dd|'T'|HH|mm|ss.SSSXXX|
    |____|__|__|___|__|__|_________|
    

    解决方案

    简单的一个是:

    Date date = originalMonthYear.parse("2017-08-16T00:00:00.000Z")
    

    但是,如果你会得到许多不同的格式,你可以使用类似(nevertested):

    List<SimpleDateFormat> myUsedPatterns = new ArrayList<>();
    
    myUsedPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"));
    myUsedPatterns.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"));
    
    for (SimpleDateFormat myPattern : myUsedPatterns) {
        try {
            SimpleDateFormat originalMonthYear = new SimpleDateFormat(myPattern );
            Date date = originalMonthYear.parse(tranDateTime);
    
            SimpleDateFormat formatter = new SimpleDateFormat(toDateFormat);
            return formatter.format(date);
            
        } catch (ParseException e) {
            // Loop
        }
    }
    

    【讨论】:

    • 谁对答案投了反对票,你愿意写评论为什么吗?供我们大家学习。
    猜你喜欢
    • 2013-12-08
    • 1970-01-01
    • 2016-04-04
    • 2016-01-06
    • 1970-01-01
    • 2021-07-05
    • 2013-05-28
    • 1970-01-01
    相关资源
    最近更新 更多