【问题标题】:SimpleDateFormat not parsing time correctly [duplicate]SimpleDateFormat 无法正确解析时间 [重复]
【发布时间】:2019-02-11 16:49:48
【问题描述】:

这发生在一个(可能更多)日期时间,其中时间部分在解析中完全错误。

代码:

import java.text.*;
import java.util.*;

public class TestTimeParse {
    public static void main(String[] args) {
        SimpleDateFormat dateFmt = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault());
        dateFmt.applyPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z'");
        ParsePosition pos = new ParsePosition(0);
        Date date = dateFmt.parse("2018-11-01T18:07:55.6725292Z", pos);
        System.out.println("Text 2018-11-01T18:07:55.6725292Z parses as " + date);
    }
}

输出:

文本 2018-11-01T18:07:55.6725292Z 解析为 Thu Nov 01 20:00:00 MDT 2018

时间组件发生了什么?小时是错误的,分钟和秒被清零。

【问题讨论】:

  • 将模式更改为"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" 并将输入更改为"2018-11-01T18:07:55.672Z" 似乎可以解决问题。不确定这是否是与亚秒值相关的错误...
  • 如果我可以... 大多数时间,人们编写具有yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z' 模式的日期格式解析器实际上是在尝试解析 ISO-8601 日期(时间)。并且使用这种基于字符串的固定时区不感知模式来解析 ISO 8601 日期是一个可怕的想法。因此,如果这确实是您想要做的,请查看stackoverflow.com/questions/2201925/…
  • java.util.Date 只能处理毫秒。因此,SimpleDateFormat 对此唯一支持的模式是“yyyy-MM-dd'T'HH:mm:ss.SSS'Z'”,这意味着您的日期也必须用毫秒表示。
  • 我建议你不要使用DateFormat 和Date。这些类设计不良且过时,尤其是前者,尤其是出了名的麻烦。而是使用来自java.time, the modern Java date and time API 的LocalDateTime 和DateTimeFormatter。
  • @OleV.V.我同意。不幸的是,这是在 java 1.8 之前编写的代码,我们需要对其进行重构。但与此同时,我们需要使用它。

标签: java simpledateformat java-time


【解决方案1】:

这是 one of the problems 与过时的 Date、Calendar 和 SimpleDateFormat 类。您不应该使用它,因为它已被 Java 8 中的新日期和时间 API 取代。它在 java.time 包中可用。

String str = "2018-11-01T18:07:55.6725292Z";
String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z'";

LocalDateTime ts = LocalDateTime.parse(str, DateTimeFormatter.ofPattern(pattern));
System.out.println("Text 2018-11-01T18:07:55.6725292Z parses as " + ts);

似乎 SimpleDateFormat 最多只能读取三毫秒数字。如果将日期的小数部分截断为三位数,即“2018-11-01T18:07:55.672”而不是“2018-11-01T18:07:55.6725292Z”,则解析过程有效,并且还会更改相应的 ' S'模式说明符,即“yyyy-MM-dd'T'HH:mm:ss.SSS'Z'”。

【讨论】:

  • 您介意解释一下确切的问题吗?众所周知,旧 API 在大多数情况下都可以使用。为什么在这里不起作用?
  • 我认为问题在于 SimpleDateFormat 的分辨率只有毫秒。您指定的精度远高于可用的三位数字(000-999 毫秒)。 SimpleDateFormat 可能会与超出范围的条件混淆。
  • @ernest_k 6725292 毫秒等于 1 小时 52 分 5.292 秒。将这些添加到时间 18:07:55,以获得 - 是的,准确地说是 20:00:00.292 - 呈现为 20:00:00,因为不打印毫秒。
  • @OleV.V.谢谢你解开谜团。没看懂
  • MC Emperor 更好更简单,无需任何显式格式化程序:只需 Instant.parse(str) 或 OffsetDateTime.parse(str)。这是可行的,因为格式是标准 ISO 8601。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多