2017-03-27 21 views
2

我有解析以下日期格式问题:DateTimeFormatter无法解析由自身产生串

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

+1

改变你的模式为:'String pattern =“yyyy-MM-dd'T'HH:mm:ss.SSS'T'ZZZZZ”;'(一个Z更多),它的工作原理 – Jens

+0

似乎也适用于刚三个Zs。 –

+1

@BrianClapper,但是三个Z会导致输出与OP有'.512T-0500'而不是'.512TGMT-05:00' –

回答

2

贪图明白什么是错的我一起来看看DateTimeFormatterBuilder.java:3563源代码,其中的例外是上调。

我看到有一段代码可以解析GMT-05:00之后的秒部分。

所以,如果你添加秒情况下它只会工作...

ZonedDateTime dateParsed = ZonedDateTime.parse(dateStr+":00", formatter); 
+0

谢谢,它是这样工作的,但这仍然是奇怪的情况,我想尝试找出更好的解决方案 – endryha

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.799 TGMT-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"); 

这工作方式完全相同。

相关问题