`DateTimeFormatter` 以小数秒处理句号或逗号
`DateTimeFormatter` to handle either a FULL STOP or COMMA in fractional second
在 java.time classes, how do we specify a formatting pattern for a DateTimeFormatter
中允许使用句号 (.
)(句点或点)或逗号 (,
) 作为小数秒的分隔符?
例如,以下内容用于解析 20090813145607.0Z
和 20090813145607,0Z
中以 .0Z
或 ,0Z
结尾的输入日期值。
String input = "20090813145607.0Z";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "uuuuMMddHHmmss[,S][.S]X" );
但对于打印,输出包含两者,生成重复的小数秒对。
20090813145607,0.0Z
所以我推断我在格式化模式中使用 [,S][.S]
并不是获得此功能的正确方法。
DecimalStyle
我尝试使用 DateTimeFormatter::withDecimalStyle
method passing a DecimalStyle
,但它没有像我在实验中预期的那样运行。该文档并未真正解释其预期行为。
这个问题很重要,因为 ISO 8601 标准建议使用逗号但允许句号。两者都在实践中很常用。
Instant
不能容忍逗号
也许在 java.time 中不可能像 decimal mark 那样容忍逗号 and/or 点。
我用 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 );
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 子类,但这应该适合你。
(基于我的相关评论)
我不知道 "DateTimeFormatter" 是否允许这种 "or" 模式。
我能想到的两个解决方法是
使用多个格式化程序。例如。一个用于 ,
,一个用于 .
,如果第一个解析失败,则使用第二个。
伪代码
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();
}
"Normalize" 通过将倒数第 3 个字符替换为 .
输入 ,
,您可以使用一个格式化程序。例如
f = DateTimeFormatter.ofPattern( "uuuuMMddHHmmss.SX" )
result = f.parse(input.matches(",..$")
? input.replaceAll("^(.*),(..)$", "\1.\2")
: input);
关于点与逗号,根据我的经验,点比逗号更常见。 RFC3339 uses a dot only as does XML schema. The dot is no longer "preferred" (according to wikipedia):
A decimal mark, either a comma or a dot (without any preference as
stated in resolution 10 of the 22nd General Conference CGPM in
2003,[16] but with a preference for a comma according to ISO
8601:2004)
鉴于所有这些,JSR-310 更喜欢一个点。
DecimalStyle
class 确实提供了一些控制,其中 DateTimeFormatterBuilder.appendFraction
方法与 true
一起使用以从 DecimalStyle
输出小数点。
无法解析点或逗号。这被跟踪为 JDK-8132536,它解决了解析中的一般 "or" 概念。
Instants 使用 ISO_INSTANT
解析,表示 "The localized decimal style is not used".
因此,JSR-310 的格式化程序无法执行您想要的操作。
在 java.time classes, how do we specify a formatting pattern for a DateTimeFormatter
中允许使用句号 (.
)(句点或点)或逗号 (,
) 作为小数秒的分隔符?
例如,以下内容用于解析 20090813145607.0Z
和 20090813145607,0Z
中以 .0Z
或 ,0Z
结尾的输入日期值。
String input = "20090813145607.0Z";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "uuuuMMddHHmmss[,S][.S]X" );
但对于打印,输出包含两者,生成重复的小数秒对。
20090813145607,0.0Z
所以我推断我在格式化模式中使用 [,S][.S]
并不是获得此功能的正确方法。
DecimalStyle
我尝试使用 DateTimeFormatter::withDecimalStyle
method passing a DecimalStyle
,但它没有像我在实验中预期的那样运行。该文档并未真正解释其预期行为。
这个问题很重要,因为 ISO 8601 标准建议使用逗号但允许句号。两者都在实践中很常用。
Instant
不能容忍逗号
也许在 java.time 中不可能像 decimal mark 那样容忍逗号 and/or 点。
我用 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 );
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 子类,但这应该适合你。
(基于我的相关评论)
我不知道 "DateTimeFormatter" 是否允许这种 "or" 模式。
我能想到的两个解决方法是
使用多个格式化程序。例如。一个用于
,
,一个用于.
,如果第一个解析失败,则使用第二个。伪代码
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(); }
"Normalize" 通过将倒数第 3 个字符替换为
.
输入,
,您可以使用一个格式化程序。例如f = DateTimeFormatter.ofPattern( "uuuuMMddHHmmss.SX" ) result = f.parse(input.matches(",..$") ? input.replaceAll("^(.*),(..)$", "\1.\2") : input);
关于点与逗号,根据我的经验,点比逗号更常见。 RFC3339 uses a dot only as does XML schema. The dot is no longer "preferred" (according to wikipedia):
A decimal mark, either a comma or a dot (without any preference as stated in resolution 10 of the 22nd General Conference CGPM in 2003,[16] but with a preference for a comma according to ISO 8601:2004)
鉴于所有这些,JSR-310 更喜欢一个点。
DecimalStyle
class 确实提供了一些控制,其中 DateTimeFormatterBuilder.appendFraction
方法与 true
一起使用以从 DecimalStyle
输出小数点。
无法解析点或逗号。这被跟踪为 JDK-8132536,它解决了解析中的一般 "or" 概念。
Instants 使用 ISO_INSTANT
解析,表示 "The localized decimal style is not used".
因此,JSR-310 的格式化程序无法执行您想要的操作。