解析字符串到日期:非法模式字符'T'。
Posted
技术标签:
【中文标题】解析字符串到日期:非法模式字符\'T\'。【英文标题】:Parsing string to date: Illegal pattern character 'T'.解析字符串到日期:非法模式字符'T'。 【发布时间】:2014-12-11 11:32:39 【问题描述】:我需要在 java 中解析一个字符串到日期。我的字符串格式如下:
2014-09-17T12:00:44.0000000Z
但是 java 在尝试解析这种格式时会抛出以下异常...java.lang.IllegalArgumentException: Illegal pattern character 'T'
。
关于如何解析它的任何想法?
谢谢!
【问题讨论】:
current_date=formatter.parse(date) 将格式化程序对象也添加到此处 是的,当然,抱歉:SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-ddTHH:mm:ss.SSS"); 使用 'T' 而不是只使用 T 【参考方案1】: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);
在我的时区输出:
作为老式日期:2014 年 9 月 17 日星期三 14:00:44 CEST
输出会因时区而异,因为 Date.toString()
容易混淆地采用 JVM 的默认时区并将其用于呈现字符串。
你出了什么问题?
您没有向我们展示您的代码,但我们已经可以看出有几处是错误的:
SimpleDateFormat
无法正确解析秒上有 7 个小数的字符串。它仅支持毫秒,精确到小数点后三位。
在您的格式模式字符串中,您需要通过将文字 T
括在单引号中来转义它,'T'
或 SimpleDateFormat
会将其理解为模式字母,并且没有格式模式字母 T
.这就是您的异常消息的含义。
链接
Oracle tutorial: Date Time 解释如何使用 java.time。 Wikipedia article: ISO 8601。 Related question: Date object SimpleDateFormat not parsing timestamp string correctly in Java (android) environment 关于解析超过三位小数的秒数。 Related question: ISO 8601 String to Date/Time object in Android。【讨论】:
【参考方案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
【讨论】:
【参考方案3】:鉴于您输入的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
请注意,不同的时钟时间适用于时区CEST
(toString()
使用系统时区),结果等价于UTC-time 12:00:44
。此外,我必须插入七个符号 S 才能正确处理您的输入,该输入假装精度低至 100ns
(尽管 Java pre 8 只能处理毫秒)。
【讨论】:
但有一条评论,您需要在构造函数 SimpleDateFormat 中将最后一个 X 字符替换为“Z”。很好的解决方案,对我有用 @VictorPonomarenko 符号字母 X 是在 Java 7 中引入的。对于 Java 6,如果解析的文字“Z”将被识别为 UTC+00,我不确定 Z 是否可以作为替换含义!也许最好使用 Java 6 的解决方法来转义 Z(仅将其解释为文字)并将SimpleDateFormat
-object 上的区域设置为“GMT”。
在 android 上我得到运行时异常,当离开 X 字符时,但在替换为 'Z' 后效果很好(android 现在可以在 java 7 上运行)
@VictorPonomarenko Z 似乎是Android 的正确符号,虽然文档不是很详细,但请记住:Android != Java(和SimpleDateFormat
-API 确实不同在两个世界中)。【参考方案4】:
您必须转义“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");
使用答案:What is this date format? 2011-08-12T20:17:46.384Z
【讨论】:
感谢您的回答,现在我没有得到同样的异常,但是这个:“java.text.ParseException: Unparseable date: "Date"”。我认为日期格式还没有很好的定义......以上是关于解析字符串到日期:非法模式字符'T'。的主要内容,如果未能解决你的问题,请参考以下文章
无法解析ISO 8601格式的字符串,缺少冒号的冒号,到Java 8 Date
如何将RFC 3339日期字符串解析为ZonedDateTime?
Java - LocalDateTime解析日期字符串值时丢弃秒值“00“,如“2021-07-01 15:33:00“ 转换为“2021-07-01T15:33“