【问题标题】:Date formatting exception日期格式异常
【发布时间】:2023-03-22 23:46:02
【问题描述】:

我有以下日期2017-02-19T12:23:37.000000-00:00

还有这段代码:

    Long tt = null;
    String date = "2017-02-19T12:23:37.000000-00:00";
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
    try {
        Date parsedDate = formatter.parse(date);
        tt =  parsedDate.getTime();
    } catch (ParseException e) {
        System.out.println(e);
        tt = (long) 9999999;
    }

    System.out.println(tt);

输出:

java.text.ParseException:无法解析的日期:“2017-02-19T12:23:37.000000-00:00”

9999999

感谢您的帮助。

【问题讨论】:

  • 您的输入与您的格式不符。输入的精度为微秒,格式的精度为毫秒。
  • 仅供参考,麻烦的旧日期时间类,如 java.util.Datejava.util.Calendarjava.text.SimpleTextFormat 现在是 legacy,被 java.time 类取代。

标签: java date format date-formatting


【解决方案1】:

您的毫秒部分有 6 位数字而不是三位,并且时区不是作为 RFC 822 时区而是作为 ISO 8601 时区给出的。

这将起作用:

"yyyy-MM-dd'T'HH:mm:ss.SSSSSSX"

正如 cmets 中正确指出的那样,如果它偏离 000000,这将导致毫秒部分出现乱码。

从 Java 8 开始,有一种更好的方法来解析日期和时间。对于您的 ISO-8601 日期,只需使用以下命令:

OffsetDateTime.parse("2017-02-19T12:23:37.000000-00:00")

另请参阅Basil Bourque's great answer 以获得更详细的说明。

【讨论】:

  • S 代表毫秒,而不是微秒。如果字符串是“2017-02-19T12:23:37.000999-00:00”,那么您的解析方式将增加 999 毫秒而不是 999 微秒(即没有,因为 Date 具有毫秒精度)到日期。因此,基本上,它仅在微秒部分始终为 000000 时才有效。
  • 正如 JB Nizet 指出的那样,如果您不总是有零,则此代码失败。另一个例子:“2017-02-19T12:23:37.123456-00:00”给出1487507140456错误结果。请参阅此code run live at IdeOne.com。旧的日期时间类仅限于毫秒分辨率,并且您建议的格式模式行为不正确。请改用 java.time 类。
  • @JB Nizet 和 Basil Bourque:感谢 cmets 的启发,我更新了我的答案以反映这一点。
【解决方案2】:

tl;博士

OffsetDateTime.parse( "2017-02-19T12:23:37.000000-00:00" )

使用 java.time

您正在使用麻烦的旧日期时间类,它们现在是遗留的,被 java.time 类所取代。

毫秒与纳秒

旧类仅支持milliseconds 分辨率,限制为小数秒后三位小数。 java.time 类使用nanoseconds 分辨率,最多九位小数秒小数。您的六位小数的示例数据是microseconds

ISO 8601

您的输入字符串恰好是标准ISO 8601 格式。

嗯,几乎是标准的:你的例子有一个负零offset-from-UTC。 ISO 8601 标准明确禁止负零偏移。该标准要求将零偏移量标记为带有+ 符号而不是- 符号的正数。然而,声称是 ISO 8601 概要的RFC 3339 违反了这条规则,将不幸和不明智的选择作为不同的内涵。

java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。所以根本不需要指定格式模式。

OffsetDateTime

幸运的是,OffsetDateTime 类在解析您的输入时可以容忍负零偏移。

String input = "2017-02-19T12:23:37.123456-00:00" ;
OffsetDateTime odt = OffsetDateTime.parse( input );

看到这个code run live at IdeOne.com

odt.toString(): 2017-02-19T12:23:37.123456Z

注意OffsetDateTime::toString 在从我们的OffsetDateTime 生成字符串时使用了ISO 8601 格式。末尾的ZZulu 的缩写,意思是UTC


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

从哪里获取 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

    【解决方案3】:

    您输入的日期与您指定的模式不匹配。尝试改变模式:

        String date = "2017-02-19T12:23:37.000000-00:00";
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX");
    

    有关更多信息,您可以查看文档示例here

    【讨论】:

    • S 代表毫秒,而不是微秒。如果字符串是“2017-02-19T12:23:37.000999-00:00”,那么您的解析方式会将 999 毫秒而不是 999 微秒(即没有,因为 Date 具有毫秒精度)添加到日期
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多