【问题标题】:Java Unparsable dateJava 无法解析的日期
【发布时间】:2014-03-17 20:25:05
【问题描述】:

我有一个格式为:String dateString = "2014-03-17T20:05:49.2300963Z"的字符串

试试这个:

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'kk:mm:ss.SSSX");
Date date = df.parse(dateString);

导致Unparsable date 异常。

文档:http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html 表示当单个字母用于 TimeZone 时,XISO 8601 一起使用。

编辑 重新阅读文档,我将SimpleDateFormat 调高了一点:

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
dateString = dateString.replace("Z", "");

我删除了Z,因为我知道时区,使用H 而不是k,并添加更多S 以供笑。

现在时间正在解析,但不正确。日期准确,时间似乎是随机的。

编辑 2 问题是java只允许毫秒精度,所以2300963被解释为2300秒和963毫秒。我需要对我的字符串进行一些不同的格式化才能使其正常工作。

编辑 3 事实证明你在 Java 中不能有秒的小数部分。它必须被截断到毫秒。我最终使用了我的数据库提供给我的类型,但一般的解决方案是将秒的小数部分截断为毫秒。我将发布如何做到这一点的示例代码作为答案。

【问题讨论】:

  • 来自文档: 数字:对于格式化,模式字母的数量是最小的位数,较短的数字被零填充到这个数量。解析时,除非需要分隔两个相邻字段,否则忽略模式字母的数量。
  • For parsing, the number of pattern letters is ignored unless it's needed to separate two adjacent fields. 您需要将毫秒与时区分开。
  • 请注意,2300963 是一种奇怪的毫秒数。 2300 将添加为分钟和秒 AFAIK。
  • @fge Hour in day (1-24)

标签: java parsing date simpledateformat


【解决方案1】:

您需要提供尽可能多的S,就像您在约会String 中所拥有的一样多。在这种情况下,7

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'kk:mm:ss.SSSSSSSX");

这是必需的,否则DateFormat 不知道毫秒在哪里结束以及时区从哪里开始。


还要注意,

2300963

作为毫秒值表示 2300 秒和 963 毫秒。你为什么会这样?为什么那些秒不是它们相应位置的值的一部分?当DateFormat解析它时,它们将被添加。

【讨论】:

  • 2300963 是我们部分秒的表示方式。所以它是一秒的文字 .2300963。看起来我误读了文档,我们只能指定毫秒,而不是部分秒,对吗?
  • @TylerDeWitt 据我所知,这是正确的。这些是毫秒值,而不是小数值。
  • @TylerDeWitt 这很奇怪。在这种情况下,您可能需要进行一些手动解析...?
【解决方案2】:

这可行:SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'kk:mm:ss.SSSSSSS'Z'");

  1. 确切地指定您期望的精度(例如,在这种情况下为毫秒)会更安全。有 7 位数字很奇怪,但如果您的所有日期都是这样的,请输入 7 S
  2. X 将解析-0800 类型的时区。所以你的字符串必须看起来像2014-03-17T20:05:49.2300963-0800(或类似的东西)。将Z 视为文字,如@9​​87654328@。

编辑Relevant to your partial seconds issue.

【讨论】:

  • Z 不一定是文字。它可以代表祖鲁时间。
  • 没错,但我的意思是引用它,就像你引用文字一样。否则,它将被解释为 RFC 822 时区。
【解决方案3】:

如何将小数秒截断为毫秒(因为Java无法处理小数秒):

public String truncate(String dateString){
  int numberOfDigits = dateString.substring(dateString.indexOf("."), dateString.length() - 1).length();

  String justMilliSecondsDate = null;
  if (numberOfDigits == 3) {
    justMicrosDate = dateString;
    } 
  else if (numberOfDigits > 3) {
    justMilliSecondsDate = dateString.substring(0, dateString.length() - numberOfDigits + 3);
  } 
  else {
      justMilliSecondsDate = dateString;
      for (int i = numberOfDigits ; i < 3 ; i++) justMilliSecondsDate += "0";
  }

  return justMilliSecondsDate;
}

【讨论】:

    【解决方案4】:

    tl;博士

    Instant.parse( "2014-03-17T20:05:49.2300963Z" )
    

    java.time

    您正在使用麻烦的旧日期时间类,现在已被 java.time 类取代。

    分辨率

    • 毫秒
      旧的日期时间类被限制为毫秒分辨率,最多三位小数。
    • 微秒
      您的输入有六位小数秒的微秒。
    • 纳秒
      java.time 类的分辨率为纳秒,最多可显示九位小数秒。对你的微秒来说绰绰有余。

    ISO 8601

    ISO 8601 标准定义了字符串格式来表示日期时间值。您输入的内容符合 ISO 8601。

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

    Instant instant =
        Instant.parse( "2014-03-17T20:05:49.2300963Z" );
    

    【讨论】:

      猜你喜欢
      • 2021-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多