You need to enable JavaScript to run this app. 如何构建带开头可选小时段的DateTimeFormatter以正常解析时间码
优惠活动
大模型
产品
解决方案
定价
更多

如何构建带开头可选小时段的DateTimeFormatter以正常解析时间码

结论验证

你的推测完全正确。DateTimeFormatter的appendOptional采用贪婪匹配策略,解析20:33.123时,开头的20:刚好匹配你定义的UNLIMITED_HOURS规则(两位数字+冒号),会被直接识别为小时段,剩余待解析内容变为33.123,无法匹配后续要求的「两位分钟+冒号」规则,因此抛出索引5位置的解析异常。
此外你原有代码还存在一个隐藏问题:parseDefaulting配置在可选的UNLIMITED_HOURS构造器中,只有当小时段被成功匹配时默认值才会生效,省略小时的场景下默认值不会被注入。

解决方案

推荐采用双可选分支的写法,优先匹配更长的带小时格式,再匹配不带小时的格式,同时调整小时的宽度配置以支持大于24的多位数小时:

DateTimeFormatter TIMECODE = new DateTimeFormatterBuilder()
    // 分支1:优先匹配带小时的完整格式,支持最多10位小时(可按需调整上限)
    .appendOptional(new DateTimeFormatterBuilder()
        .appendValue(ChronoField.HOUR_OF_DAY, 2, 10, SignStyle.NEVER)
        .appendLiteral(':')
        .appendValue(MINUTE_OF_HOUR, 2)
        .appendLiteral(':')
        .appendValue(SECOND_OF_MINUTE, 2)
        .appendFraction(MILLI_OF_SECOND, 3, 3, true)
        .toFormatter(Locale.ENGLISH))
    // 分支2:匹配不带小时的格式,默认小时为0
    .appendOptional(new DateTimeFormatterBuilder()
        .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
        .appendValue(MINUTE_OF_HOUR, 2)
        .appendLiteral(':')
        .appendValue(SECOND_OF_MINUTE, 2)
        .appendFraction(MILLI_OF_SECOND, 3, 3, true)
        .toFormatter(Locale.ENGLISH))
    .toFormatter(Locale.ENGLISH);

如果使用自定义TimecodeHour字段,只需把代码中的ChronoField.HOUR_OF_DAY替换为TimecodeHour.HOUR即可。

内容的提问来源于stack exchange,提问作者Tobias Wohlfarth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 15:36:08