[英]Parsing an “integer” time with DateTimeFormatter using optional sections
[英]Java 8 DateTimeFormatter parsing optional sections
我需要将日期时间解析为两种不同格式的字符串:
以下dateTimematmat模式正确解析第一种日期字符串
DateTimeFormatter.ofPattern ("uuuuMMddHHmmss[,S][.S]X")
但是第二个失败,因为没有预期破折号,冒号和T.
我的尝试是使用如下可选部分:
DateTimeFormatter.ofPattern ("uuuu[-]MM[-]dd['T']HH[:]mm[:]ss[,S][.S]X")
出乎意料的是,这解析了第二种日期字符串(带有破折号的日期字符串),但不是第一种,抛出一个
java.time.format.DateTimeParseException: Text '19861221235959Z' could not be parsed at index 0
就像可选部分没有被评估为可选部分一样......
正如彼得在评论中所说,问题在于你的模式正在考虑整个字符串作为年份。 您可以使用.appendValue(ChronoField.YEAR, 4)
将其限制为四个字符:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.appendPattern("[-]MM[-]dd['T']HH[:]mm[:]ss[,S][.S]X")
.toFormatter();
这可以用你的两个例子正确解析。
如果你想要更加冗长,你可以这样做:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.optionalStart().appendLiteral('-').optionalEnd()
.appendPattern("MM")
.optionalStart().appendLiteral('-').optionalEnd()
.appendPattern("dd")
.optionalStart().appendLiteral('T').optionalEnd()
.appendPattern("HH")
.optionalStart().appendLiteral(':').optionalEnd()
.appendPattern("mm")
.optionalStart().appendLiteral(':').optionalEnd()
.appendPattern("ss")
.optionalStart().appendPattern("X").optionalEnd()
.toFormatter();
从文档中不清楚,但我的猜测是以下是发生的事情。
在格式模式字符串中使用uuuuMMddHHmmss
时,格式化程序可以很容易地看到有几个相邻的数字字段,因此使用字段宽度来分隔字段。 前4位数字表示年份,依此类推。
相反,当您使用uuuu[-]MM[-]dd['T']HH[:]mm[:]ss
,格式化程序不会将其视为相邻的数字字段。 我同意Peter Lawrey的评论,因此它需要更长时间的数字运行,最后溢出最大年份(999999999)并抛出异常。
解决方案? 请参考Michael的回答 。
基于模式的DateTimeFormatter不够智能,无法处理可选节和可能有两个数字字段而不分离。 当你确实需要你的数字字段没有分隔符时,没有问题,那么模式理解模式字母从u到M的变化意味着它需要计算数字以知道哪个数字是哪个字段的一部分。 但是当这不确定时,那么模式就不会尝试。 它会看到一个完整描述的数字字段,而不会立即跟随另一个数字字段。 因此,没有理由计算数字。 所有数字都是应该在此处表示的字段的一部分。
要做到这一点,你不应该尝试使用模式构建DateTimeFormatter,而是使用Builder。 从DateTimeFormatter.BASIC_ISO_DATE
和附近的其他人那里获取灵感。
乍一看,您的第二种格式应适用于这两种情况。 不知道为什么不这样做。 顺便说一句,我很好奇你为什么用'u'而不是'y'一年。 所以我也会尝试使用'y'来看看它是否有所作为。 但总的来说,你正在触及一个有趣的观点 - 如何解析未知格式的日期(想象一下,你处理未知数量的格式而不是2种可能的格式)。 我实际上曾经写过一次这样的解析器。 我用来解决这个问题的想法在我的文章Java 8 java.time包中有所描述:解析迄今为止的任何字符串 。 您可能会发现这个想法很有用。 简而言之,我们的想法是拥有包含所有支持格式的外部文件,并尝试逐个应用每种格式,直到一个工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.