在将日期字符串解析为java.util.Date时,出现非法的模式字符'T'。
在将日期字符串解析为java.util.Date时,出现非法的模式字符'T'。
我有一个日期字符串,想要使用Java Date API将其解析为普通日期,下面是我的代码:
public static void main(String[] args) { String date = "2010-10-02T12:23:23Z"; String pattern = "yyyy-MM-dd'T'hh:mm:ssZ"; SimpleDateFormat sdf = new SimpleDateFormat(pattern); try { Date d = sdf.parse(date); System.out.println(d.getYear()); } catch (ParseException e) { e.printStackTrace(); } }
然而,我遇到了一个异常:`java.lang.IllegalArgumentException: Illegal pattern character 'T'`。所以我想知道是否需要手动拆分字符串并进行解析?
顺便说一下,我尝试在T的两侧添加单引号字符:
String pattern = "yyyy-MM-dd'T'hh:mm:ssZ";
但这也不起作用。
在上面的代码中,出现了一个问题:在将字符串解析为java.util.Date时,出现了"Illegal pattern character 'T' when parsing a date string"的异常。
造成这个问题的原因是在DateTimeFormatter的模式字符串中,使用了'T'字符来匹配日期时间字符串中的'T'字符,但'T'在模式字符串中不是合法的字符。
解决这个问题的方法是,将模式字符串中的单引号(')删除,即将"yyyy-MM-dd'T'HH:mm:ss'Z'"修改为"yyyy-MM-ddTHH:mm:ssZ"。修改后的代码如下:
public static void main(String[] args) { String timeStr = "2021-11-11T10:25:35+00:00"; System.out.println(convertStringToTimestamp(timeStr)); } static Timestamp convertStringToTimestamp(String dateAsString) { OffsetDateTime offsetDateTime = OffsetDateTime.parse(dateAsString); final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"); return Optional.ofNullable(offsetDateTime.toString()) .map(value -> LocalDateTime.parse(value, dateTimeFormatter)) .map(Timestamp::valueOf) .orElse(null); }
此外,还提到了一些建议:
1. 如果可能的话,尽量避免使用Timestamp类,可以使用OffsetDateTime或LocalDateTime类来代替。特别是在使用JDBC时,可以考虑使用OffsetDateTime或LocalDateTime。
2. 如果确实需要使用旧式的Timestamp类,可以使用更简单的方式来转换字符串为Timestamp,即使用`Timestamp.from(OffsetDateTime.parse(dateAsString).toInstant())`。
另外,还提供了一个与问题相关的链接:'Z' is not the same as Z。
总结起来,该问题的原因是DateTimeFormatter的模式字符串中使用了不合法的字符'T',解决方法是修改模式字符串。另外,还提供了一些建议和相关链接供参考。
问题的出现原因是在使用java.util.Date类将日期字符串解析为Date对象时,出现了非法的模式字符'T'。解决方法是使用java.time.Instant类来解析符合ISO 8601标准的日期字符串。
ISO 8601是日期时间字符串格式的国际标准。Java 8及更高版本内置的java.time框架和Joda-Time库在解析和生成字符串时默认使用ISO 8601格式。建议避免使用旧的java.util.Date/.Calendar和java.text.SimpleDateFormat类,因为它们容易出现问题,令人困惑且存在缺陷。如果需要与其他系统进行交互,可以进行转换。
Java 8及更高版本内置了新的java.time框架,该框架受到Joda-Time的启发,由JSR 310定义,并由ThreeTen-Extra项目扩展。可以使用Instant.parse方法将符合ISO 8601格式的字符串解析为Instant对象。如果需要将Instant对象转换为旧的java.util.Date对象,可以使用java.util.Date.from方法。
如果需要,还可以为日期时间对象指定时区。可以使用ZoneId.of方法定义时区,并使用ZonedDateTime.ofInstant方法将Instant对象与时区调整相结合。同样,如果需要将ZonedDateTime对象转换为旧的java.util.Date对象,可以使用zdt.toInstant方法提取Instant对象,然后使用java.util.Date.from方法进行转换。
对于使用Joda-Time库的情况,可以使用DateTime类将日期字符串解析为DateTime对象。与java.time类似,Joda-Time也支持将DateTime对象转换为旧的java.util.Date对象。同样,如果需要指定时区,可以使用DateTimeZone.forID方法定义时区,并使用withZone方法将DateTime对象与时区调整相结合。
总结起来,使用java.time.Instant类解析ISO 8601格式的日期字符串是解决该问题的方法。同时,建议避免使用旧的日期时间类,而是使用java.time或Joda-Time库来处理日期和时间。
在Java 8及更高版本中,出现了一个错误的模式字符'T'的问题,当解析日期字符串为java.util.Date时会报错。解决方法是使用Instant.parse()方法来解析日期字符串,并且应该使用Instant而不是已被弃用的java.util.Date。此外,应该使用DateTimeFormatter而不是SimpleDateFormatter。
在原始回答中,提到了关于模式字符'T'的解释。在模式中,使用单引号将'T'转义,以及以'Z'结尾的模式实际上是'XXX',这在SimpleDateFormat的JavaDoc中有所说明,只是在使用上不够清晰,因为'Z'同时也是旧的TimeZone信息的标记。
下面的代码是一个Q2597083.java的示例,其中包含了导入的类和一些静态变量和方法。该示例使用ISO_8601_24H_FULL_FORMAT模式来格式化日期,并使用SimpleDateFormat来解析日期字符串并输出结果。
运行这段代码会产生以下输出:
sdf.format(BEGINNING_OF_TIME) = 0001-01-01T00:00:00.000Z
sdf.format(END_OF_TIME) = 292278994-08-17T07:12:55.807Z
sdf.format(new Date()) = 2015-04-28T14:38:25.956Z
sdf.parse("2015-04-28T14:23:38.521Z") = Tue Apr 28 14:23:38 UTC 2015
sdf.parse("0001-01-01T00:00:00.000Z") = Sat Jan 01 00:00:00 UTC 1
sdf.parse("292278994-08-17T07:12:55.807Z") = Sun Aug 17 07:12:55 UTC 292278994
可以看出,通过使用正确的模式和方法,成功解析了日期字符串。