You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用java.time类解析省略分钟的日期时间输入字符串

解决省略分钟的类ISO 8601字符串解析问题

这种数据源格式不规范的情况太常见了,默认的DateTimeFormatter.ISO_LOCAL_DATE_TIME确实搞不定——因为它要求分钟是必填项。不过我们可以自定义格式化器,轻松让缺失的分钟自动填充为0,同时还能兼容标准ISO 8601格式。

方法一:用带可选片段的模式字符串

Java的DateTimeFormatter支持用方括号[]标记可选的格式部分,我们可以直接定义一个兼容多种场景的模式:

// 兼容"yyyy-MM-dd'T'HH"、"yyyy-MM-dd'T'HH:mm"、标准ISO格式的格式化器
DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH[:mm[:ss[.SSS]]]");

// 测试解析缺分钟的输入
String input = "2018-01-23T12";
LocalDateTime dateTime = LocalDateTime.parse(input, customFormatter);
System.out.println(dateTime); // 输出:2018-01-23T12:00

// 也能完美兼容带分钟/秒的标准格式
String standardInput = "2018-01-23T12:34:56.123";
LocalDateTime standardDateTime = LocalDateTime.parse(standardInput, customFormatter);
System.out.println(standardDateTime); // 输出:2018-01-23T12:34:56.123000000

这里的[:mm]表示分钟部分是可选的,输入里没有的话就自动填充0;后面的秒和毫秒片段也是可选的,完全适配标准ISO 8601的各种变体。

方法二:用DateTimeFormatterBuilder构建(逻辑更直观)

如果想更清晰地控制每一部分的可选性,推荐用DateTimeFormatterBuilder逐步构建格式化器:

DateTimeFormatter customFormatter = new DateTimeFormatterBuilder()
        // 复用ISO标准的日期解析规则
        .append(DateTimeFormatter.ISO_LOCAL_DATE)
        .appendLiteral('T')
        // 小时部分是必填项
        .appendHour(2)
        // 标记后续为可选的分钟部分
        .optionalStart()
        .appendLiteral(':')
        .appendMinute(2)
        // 标记后续为可选的秒部分
        .optionalStart()
        .appendLiteral(':')
        .appendSecond(2)
        // 标记后续为可选的小数秒部分
        .optionalStart()
        .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
        .toFormatter();

这种方式的优势是逻辑一目了然,每一个optionalStart()都明确标记了后续片段的可选性,同样能实现缺分钟自动补0的效果。

为什么默认的ISO_LOCAL_DATE_TIME不行?

默认的ISO_LOCAL_DATE_TIME对应的模式是yyyy-MM-dd'T'HH:mm[:ss[.SSS]],其中分钟mm是强制必填的,所以当输入缺少分钟时,会直接抛出DateTimeParseException。我们自定义的格式化器把分钟也设为可选,就完美解决了这个数据源的异常问题。

内容的提问来源于stack exchange,提问作者Basil Bourque

火山引擎 最新活动