【问题标题】:Why am i getting the error "Unparseable date" from SimpleDateFormat?为什么我从 SimpleDateFormat 收到错误“无法解析的日期”?
【发布时间】:2017-11-17 17:08:44
【问题描述】:

我试图将不带时区的日期字符串解析为带时区的新日期,但出现错误:
java.text.ParseException: Unparseable date: "2017-11-17 10:49:39.772 "

这是我的代码:

 String date = "2017-11-17 10:49:39.772 "
 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z");
 sdf.setTimeZone(TimeZone.getTimeZone("Europe/Amsterdam"));
 sdf.parse(date);  //here´s the error
 return date.getTime();

有什么建议吗?

【问题讨论】:

  • 您的日期字符串末尾有空格?就是想。当然还是可以解析的。
  • 你的代码能编译吗? date 被声明为String,而String 没有getTime 方法,但您的最后一行代码尝试调用一个。
  • 您仍在使用SimpleDateFormat 的任何特殊原因?我认为它已经过时了,而且从 Stack Overflow 上的问题数量来看,它给许多人带来了麻烦。 java.time,现代 Java 日期和时间 API,也称为 JSR-310,更易于使用。
  • 这里有误会吗?你说“到一个带有时区的新日期”。 Date 从来没有时区。见All about java.util.Date

标签: java timestamp simpledateformat


【解决方案1】:

您的问题已经得到解答。我只是想贡献你的代码的现代版本。

java.time

您正在使用早已过时的课程SimpleDateFormatDatejava.time,现代 Java 日期和时间 API(也称为 JSR-310)通常更易于使用。在您的特定情况下,代码非常相似:

    String date = "2017-11-17 10:49:39.772 ";
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS ");
    ZoneId zid = ZoneId.of("Europe/Amsterdam");
    ZonedDateTime zdt = LocalDateTime.parse(date, dtf).atZone(zid);
    System.out.println(zdt);

打印出来

2017-11-17T10:49:39.772+01:00[Europe/Amsterdam]

我不需要重复@DarrenW 已经说过的内容:当您的输入字符串以空格结尾并且没有时间偏移时,那么您的格式模式字符串也应该以空格结尾并且没有Z,因为Z 匹配从UTC(现在我还是重复了它)。

Date 不同,ZonedDateTime 有一个时区(顾名思义),所以我认为这可能更符合您的要求。

从纪元获取毫秒数

这可能是猜测:您的电话 date.getTime() 给我的印象是,您正在追踪自 1970 年 1 月 1 日 00:00:00 GMT(“纪元”)以来的毫秒数。如果是这样,请这样做:

    long millisSinceEpoch = zdt.toInstant().toEpochMilli();

结果是

1510912179772

在字符串中使用时区偏移进行解析

更多猜测,我不禁想到 可能发生的事情是您收到了与您的格式模式字符串匹配的日期时间字符串,但时区偏移不正确,其中你脱掉了,在你的绳子末端留下了悬空的空间。如果是这种情况,现代 API 可以通过在解析时忽略不正确的偏移量来更轻松、更优雅地处理这种情况:

    String date = "2017-11-17 10:49:39.772 +0000";
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS Z");
    ZoneId zid = ZoneId.of("Europe/Amsterdam");
    ZonedDateTime zdt = LocalDateTime.parse(date, dtf).atZone(zid);

结果又是2017-11-17T10:49:39.772+01:00[Europe/Amsterdam],与上面第一个sn-p的结果完全相同。 LocalDateTime 是一个没有任何时区或偏移信息的日期和时间,因此字符串中的错误偏移不可能通过。无论如何atZone() 仍然设置正确的时区。

获得相同的另一种方法是直接解析为ZonedDateDate,然后调用它的withZoneSameLocal() 以消除不需要的偏移量。

【讨论】:

    【解决方案2】:

    您在 SimpleDateFormat 中明确表示您需要在末尾添加时区偏移量(Z 参数),但您的字符串缺少偏移量。最后你需要像+0000 这样的东西。

    【讨论】:

      【解决方案3】:

      如果您希望正确解析字符串,它必须与您在构造函数中提供的 SimpleDateFormat 模式匹配:

      旧线:

      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z");
      

      换行:

      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS ");
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-23
        • 1970-01-01
        • 2019-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多