将字符串解析为日期:非法的模式字符“T”。

16

我需要在Java中将字符串解析为日期。我的字符串具有以下格式:

2014-09-17T12:00:44.0000000Z

当尝试解析这种格式时,Java会抛出以下异常:java.lang.IllegalArgumentException: Illegal pattern character 'T'。 有什么好的方法来解析它吗?

谢谢!


1
current_date=formatter.parse(date) - mbezunartea
将格式化程序对象也添加到这里。 - Abimaran Kugathasan
当然可以,抱歉:SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-ddTHH:mm:ss.SSS"); - mbezunartea
使用“T”而不是只使用T - Rajiv Kumar
4个回答

36
鉴于你提供的输入为 2014-09-17T12:00:44.0000000Z,仅转义字母T是不够的,还需要处理尾随的Z。但是要注意,这个Z并不是一个字面量,而是根据ISO-8601-standard标准表示UTC+00:00时区偏移量。因此,仅转义Z是不正确的。 SimpleDateFormat 通过模式符号X处理这个特殊字符Z。因此,最终解决方案如下:
 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSX");
 Date d = sdf.parse("2014-09-17T12:00:44.0000000Z");
 System.out.println(d); // output: Wed Sep 17 14:00:44 CEST 2014

请注意,不同的时钟时间适用于时区CESTtoString()使用系统时区),结果等同于UTC时间12:00:44。此外,我不得不插入七个符号S以便正确处理您的输入,这些输入伪装成精度达到100ns(尽管Java 8之前只能处理毫秒)。


但是有一个注释,您需要在构造函数SimpleDateFormat中将最后一个X字符替换为'Z'。好的解决方案,对我有效。 - Victor Ponomarenko
@VictorPonomarenko,符号字母X是在Java 7中引入的。对于Java 6,我不确定Z是否可以作为替代,即解析文字“Z”是否会被识别为UTC+00!也许最好使用Java 6的解决方法来转义Z(仅将其解释为文字),并在SimpleDateFormat对象上设置时区为“GMT”。 - Meno Hochschild
在Android上,当我离开X字符时,会出现运行时异常,但是替换为'Z'后就可以正常工作了(Android现在在Java 7上运行)。 - Victor Ponomarenko
@VictorPonomarenko,Z 似乎是 Android 的正确符号,尽管文档不是很详细,但也要记住:Android != Java(在这两个世界中,SimpleDateFormat-APIs 真的非常不同)。 - Meno Hochschild

15

您需要转义'T'字符:

    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
    format.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date parse = format.parse("2014-09-17T12:00:44.0000000Z");

使用Answer来解答这个问题:这个日期格式是什么? 2011-08-12T20:17:46.384Z


谢谢您的回答,现在我不再遇到相同的异常了,但是出现了这个异常:“java.text.ParseException: Unparseable date: "Date"”。我认为日期格式还没有定义好... - mbezunartea

3

java.time

现在是时候使用现代的Java日期和时间API - java.time 来处理日期和时间了。当这个问题被提出时,java.time已经随着Java 8发布了7个月。今天(2020年)没有人应该使用SimpleDateFormat类,因为它已经过时并且容易出错。

使用java.time,我们不需要显式地指定格式化程序:

    String str = "2014-09-17T12:00:44.0000000Z";
    Instant i = Instant.parse(str);
    System.out.println("As Instant: " + i);

输出结果为:

时间戳: 2014-09-17T12:00:44Z

您使用的是 ISO 8601 格式(底部链接),java.time 类通常将其作为默认格式解析 ISO 8601 并从其 toString 方法中返回 ISO 8601。在 ISO 8601 中,秒的小数部分是可选的。

如果您需要一个 Date 对象用于尚未升级到 java.time 的旧版 API:

    Date oldfashionedDate = Date.from(i);
    System.out.println("As old-fashioned Date: " + oldfashionedDate);

以我的时区为准的输出:

旧的Date时间: Wed Sep 17 14:00:44 CEST 2014

输出结果会因为使用 Date.toString() 方法导致受到时区影响而变化,因为该方法混淆了JVM的默认时区并将其用于渲染字符串。

你在哪里出错了?

虽然您没有向我们展示代码,但我们已经可以看出有几个问题:

  1. SimpleDateFormat无法正确解析带有7个小数位秒数的字符串。它仅支持毫秒,即恰好三个小数点。
  2. 在您的格式模式字符串中,您需要通过用单引号括起来(例如'T')来转义字面上的字符T,否则SimpleDateFormat会将其理解为格式模式字符而且实际上不存在T格式模式字符。 这就是您的异常消息所指的。

链接


2

试一下这个。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateClass {
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        Date d = sdf.parse("2014-09-17T12:00:44.0000000Z");
        System.out.println(d); //output Wed Sep 17 12:00:44 IST 2014
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接