为了账号安全,请及时绑定邮箱和手机立即绑定

Java 8 DateTimeFormatter解析可选部分

Java 8 DateTimeFormatter解析可选部分

茅侃侃 2021-05-01 10:09:54
我需要将日期时间解析为两种不同格式的字符串:19861221235959Z1986-12-21T23:59:59Z以下dateTimeFormatter模式可以正确解析第一种日期字符串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好像可选部分没有被评估为可选...
查看完整描述

3 回答

?
慕姐4208626

TA贡献1852条经验 获得超7个赞

问题在于您的模式正在将整个字符串视为年份。您可以将.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();


查看完整回答
反对 回复 2021-05-12
?
动漫人物

TA贡献1815条经验 获得超10个赞

从文档中尚不清楚,但是我的猜测是发生了以下情况。

当您uuuuMMddHHmmss在格式模式字符串中使用时,格式化程序可以轻松地看到有几个相邻的数字字段,因此可以使用字段宽度来分隔字段。前4位数字表示年份,依此类推。

相反,使用时uuuu[-]MM[-]dd['T']HH[:]mm[:]ss,格式化程序不会将其视为相邻的数字字段。我同意彼得·劳瑞(Peter Lawrey)的评论,因此,它需要较长的数字来表示年份,最终超过最大年份(999999999),并引发异常。


查看完整回答
反对 回复 2021-05-12
?
扬帆大鱼

TA贡献1799条经验 获得超9个赞

基于模式的DateTimeFormatter不够智能,无法同时处理可选部分和具有两个不分隔的数字字段的可能性。当确实需要数字字段不带分隔符时,不问任何问题,则模式会理解,模式字母从u更改为M意味着它需要对数字进行计数才能知道哪个数字是哪个字段的一部分。但是,如果这不是确定性的,那么模式就不会尝试这种方式。它看到一个完整描述的数字字段,而不是紧随其后的是另一个数字字段。因此,没有理由计算数字。所有数字都是应该在此处表示的字段的一部分。

为此,您不应该尝试使用模式来构建DateTimeFormatter,而应该使用Builder。从DateTimeFormatter.BASIC_ISO_DATE附近以及其他人那里获取灵感。


查看完整回答
反对 回复 2021-05-12
  • 3 回答
  • 0 关注
  • 308 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信