在java.time类中,我们如何为DateTimeFormatter
指定一个格式模式,允许句号(.
((句点或点(或逗号(,
(作为小数秒的分隔符?
例如,以下内容适用于解析以 .0Z
结尾的输入日期值或以 20090813145607.0Z
和 20090813145607,0Z
结尾的,0Z
。
String input = "20090813145607.0Z";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "uuuuMMddHHmmss[,S][.S]X" );
但对于打印,输出包含两者,生成一对重复的小数秒。
20090813145607,0.0Z
所以我推断我在格式模式中使用[,S][.S]
不是获得此功能的正确方法。
DecimalStyle
我尝试使用DateTimeFormatter::withDecimalStyle
方法传递DecimalStyle
,但未能按照我在实验中的预期行事。该文档并未真正解释其预期行为。
这个问题很重要,因为ISO 8601标准建议使用逗号,但允许句号。这两种方法在实践中都很常用。
Instant
不能容忍逗号
也许这种逗号和/或点作为小数点的容差在java.time中是不可能的。
我用Java 8 Update 102尝试了以下代码。第一个带有句号(点(的输入成功,而带有逗号的第二个输入失败。
String inputDot = "2016-01-02T12:34:56.7Z"; // Succeeds.
Instant instantDot = Instant.parse ( inputDot );
String inputComma = "2016-01-02T12:34:56,7Z"; // Fails. Throws a DateTimeParseException.
Instant instantComma = Instant.parse ( inputComma );
在我的经验中,点与逗号更常见。RFC3339仅像 XML 架构一样使用点。该点不再是"首选"(根据维基百科(:
小数点,逗号或点(没有任何首选项 在第二十二届大会 CGPM 第 10 号决议中指出 2003,[16]但根据ISO优先使用逗号 8601:2004(
鉴于所有这些,JSR-310更喜欢一个点。
DecimalStyle
类确实提供了一些控件,其中 DateTimeFormatterBuilder.appendFraction
方法与 true
一起使用以输出 DecimalStyle
的小数点。
无法解析点或逗号。这被跟踪为 JDK-8132536,它在解析中处理了一般的"或"概念。
使用ISO_INSTANT
解析时刻,该表示"不使用本地化的十进制样式"。
因此,JSR-310 的格式化程序不能做你想要的。
String fmt1 = "uuuuMMddHHmmss,SX";
String fmt2 = "uuuuMMddHHmmss.SX";
DateTimeFormatter f = DateTimeFormatter.ofPattern(fmt1);
TemporalAccessor dateObject = null;
try {
dateObject = f.parse("20090813145607.0Z");
} catch (DateTimeParseException e) {
f = DateTimeFormatter.ofPattern(fmt2);
try {
dateObject = f.parse(input);
} catch (DateTimeParseException e1) {
throw new IllegalArgumentException("invalid format "+input);
}
}
也许使用不同的 RuntimeException 子类,但这应该对你进行排序。
(基于我有问题的评论(
如果"日期时间格式化程序"允许这种"或"模式,我会发现。
我能想到的两种解决方法是
-
使用多个格式化程序。 例如,一个用于
,
,一个用于.
,如果第一个解析失败,请使用第二个。伪代码
List<DateTimeFormatter> formatters = Arrays.asList( DateTimeFormatter.ofPattern( "uuuuMMddHHmmss.SX" ), DateTimeFormatter.ofPattern( "uuuuMMddHHmmss,SX" )); TemporalAccessor result = null; for (DateTimeFormatter f: formatters) { try { result = f.parse(input); break; } catch(DateTimeParseException ignored) { } } if (result == null) { throw new WhateverException(); }
-
通过将倒数第 3 个字符替换为
.
来"规范化"输入,如果它是一个,
,您可以使用一个格式化程序。 例如f = DateTimeFormatter.ofPattern( "uuuuMMddHHmmss.SX" ) result = f.parse(input.matches(",..$") ? input.replaceAll("^(.*),(..)$", "\1.\2") : input);