如何处理 Java 8 / JSR 310 / threeten.org 中 ISO-8601 时间戳中的 'optional' T?

How to deal with 'optional' T in ISO-8601 timestamp in Java 8 / JSR 310 / threeten.org ?

在Java 8 次/JSR 310/threeten.org 向后移植...

问:如何在日期部分和时间部分之间使用 'T' 或 space ' ' 解析 ISO-8601 时间戳?

时间戳的 ISO-8601 格式指定文字 'T' 以将日期规范与时间规范分开:

2015-05-12T15:42:00.123

许多应用程序使用 space ' ' 字符而不是 'T' 生成此格式的时间戳。参考文献表明 ISO-8601 通过 相互协议.

允许这样做
2015-05-12 15:42:00.123

因为我正在从多个来源获取数据,所以我想允许 'T' 或 space ' '。

我观察到模式字符串允许指定可选组件,但我看不出有任何方法可以在模式字符串中指定 "choice" ...

问:有什么方法可以在 JSR 310 模式字符串中制作 "choose-exactly-one-of-the-following" 吗?

我能够通过构建具有两个可选模式的 DateTimeFormatter 来实现它:

DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder()
    .appendOptional(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
    .optionalStart().appendPattern("yyyy-MM-dd HH:mm:ss.SSS").optionalEnd()
    .toFormatter();

看到 optionalStart() 和 optionalEnd() 让我想到:

DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder()
    .appendPattern("[yyyy-MM-dd HH:mm:ss.SSS][yyyy-MM-dd'T'HH:mm:ss.SSS]")
    .toFormatter();

但是,我不确定这是处理这种情况的正确方法...

问:处理多个日期时间模式的最佳实践解决方案是什么?

提前致谢。

清理您的输入数据

我自己的做法:

当从我自己的代码之外接受文本时,我从不相信这样的外部输入。哎呀,我什至不相信自己的 内部 输入。我总是把这些数据通过清洁器。作为清理的一部分,我将任何预期的 ISO 8601 字符串中的任何 SPACE 字符替换为 T

String datetimeInput = input.replace( " ", "T" ) ;

我也养成了打电话Google Guava library to trim whitespace from the input string. See this Answer询问详情的习惯。

并检查 NULL、非打印字符和其他不当字符。那些不可打印的内容会导致严重的错误。

只有在那之后我才会调用日期时间库 ( Joda-Time or java.time )。

陷阱解析异常

此外,当日期时间输入字符串不符合您的期望时,您应该使用 try-catch to trap for the parsing exception 来更优雅地处理。