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

Mic*_*ard 12 java datetime java-8 java-time

在Java 8时代/ JSR 310/threeten.org backport ...

问:如何在日期部分和时间部分之间用"T"或"空格"解析ISO-8601时间戳?

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

2015-05-12T15:42:00.123
Run Code Online (Sandbox Code Playgroud)

许多应用程序以这种格式生成时间戳,空格为'char而不是'T'.参考文献表明ISO-8601通过相互协议允许这一点.

2015-05-12 15:42:00.123
Run Code Online (Sandbox Code Playgroud)

因为我从多个来源摄取数据,我想要允许'T'或空格''.

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

问:有没有办法在JSR 310模式字符串中"选择一个完全一个"?

我能够通过构造一个带有两个可选模式的DateTimeFormatter来实现这个目的:

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

看到optionalStart()和optionalEnd()导致我:

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

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

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

提前致谢.

Bas*_*que 6

清理输入数据

我自己的做法:

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

String datetimeInput = input.replace( " ", "T" ) ;
Run Code Online (Sandbox Code Playgroud)

我还习惯于调用Google Guava库来修改输入字符串中的空格.请参阅此答案了解详情.

并检查NULL,非打印和其他不适当的字符.那些非printables会造成令人讨厌的错误.

只有在那之后,我才会调用日期时间库(Joda-Timejava.time).

陷阱解析异常

此外,当日期时间输入字符串无法满足您的期望时,您应该使用try-catch来捕获解析异常,以便更优雅地处理.