我在解析以下日期格式时遇到问题:
2017-03-27T08:27:43.326TGMT-05:00
我有DateTimeFormatter
生成ZonedDateTime
字符串的代码,下一步我尝试再次解析此字符串并创建ZonedDateTime
实例,但它不起作用我期待:
String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'T'ZZZZ";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
String dateStr = ZonedDateTime.now().format(formatter);
System.out.println(dateStr);
ZonedDateTime dateParsed = ZonedDateTime.parse(dateStr, formatter);
System.out.println(dateParsed);
上面的代码产生:
2017-03-27T08:27:43.326TGMT-05:00
java.time.format.DateTimeParseException: Text '2017-03-27T08:27:43.326TGMT-05:00' could not be parsed: String index out of range: 33
at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1920)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1855)
寻找有关如何提出能够在ZonedDateTime
2017-03-27T08:27:43.326TGMT-05:00
实例的工作模式的任何见解
答案 0 :(得分:2)
为了理解错误,我查看了引发异常的DateTimeFormatterBuilder.java:3563
源代码。
我看到有一段代码可以解析GMT-05:00
之后的秒部分。
因此只有在添加秒部分时才会起作用...
ZonedDateTime dateParsed = ZonedDateTime.parse(dateStr+":00", formatter);
答案 1 :(得分:0)
要了解ZZZZ
模式的作用,请查看JDK docs,您可以在其中看到其含义:
Pattern Count Equivalent builder methods
------- ----- --------------------------
ZZZZ 4 appendLocalizedOffset(TextStyle.FULL);
因此,ZZZZ
相当于appendLocalizedOffset(TextStyle.FULL)
。如果你看一下appendLocalizedOffset方法:
将本地化区域偏移(例如'GMT + 01:00')附加到格式化程序。 这会将本地化区域偏移附加到构建器,本地化偏移的格式由此方法的指定样式控制:
- 完整 - 具有本地化偏移文字的格式,例如“ GMT ,2位小时和分钟字段,可选第二个字段,如果非零,和冒号。
请注意,在解析和格式化时它有不同的行为:
在格式化期间,使用等效于使用TemporalQueries.offset()查询时间的机制获得偏移量。如果无法获得偏移量,则抛出异常,除非格式化程序的部分是可选的。
在解析期间,使用上面定义的格式解析偏移量。如果无法解析偏移量,则抛出异常,除非格式化程序的部分是可选的。
因此,似乎ZZZZ
模式在格式化时添加GMT-05:00
(没有秒时为零),但在解析时,它会尝试解析秒数(即使它们不存在) )。
这就是为什么在解析时,你需要最后添加:00
(如@freedev in his answer)。
由于ZZZZ
似乎是在偏移之前添加GMT
的唯一模式(所有其他模式只是添加了GMT
的偏移量),我认为唯一的解决方案是添加它用手。您可以使用java.time.format.DateTimeFormatterBuilder
类:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
// append the yyyy-MM-dd'T'HH:mm:ss.SSS pattern
.appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
// append "T" and "GMT"
.appendLiteral("TGMT")
// append the offset (-05:00)
.appendOffsetId()
.toFormatter();
使用此格式化程序,您的代码将按预期工作:
String dateStr = ZonedDateTime.now().format(formatter);
System.out.println(dateStr);
ZonedDateTime dateParsed = ZonedDateTime.parse(dateStr, formatter);
System.out.println(dateParsed);
输出:
2017-05-25T08:42:17.799TGMT-05:00
2017-05-25T08:42:17.799-05:00
使用您的输入进行测试:
String input = "2017-03-27T08:27:43.326TGMT-05:00";
System.out.println(input);
System.out.println(ZonedDateTime.parse(input, formatter));
输出:
2017-03-27T08:27:43.326TGMT-05:00
2017-03-27T08:27:43.326-05:00
PS:在这种情况下,我更喜欢使用DateTimeFormatterBuilder
,但您可以直接使用DateTimeFormatter.ofPattern
执行相同操作:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'TGMT'xxx");
这种方式完全相同。