使用可选部分使用 DateTimeFormatter 解析 "integer" 时间
Parsing an "integer" time with DateTimeFormatter using optional sections
我有一些数据库,我有一些 LocalTime
and I am trying to build a DateTimeFormatter
的自定义格式。
规则如下:
- 0 => 00:00
- 10 => 00:10
- 111 => 1:11
- 101 => 1:01
- 1111 => 11:11
在这样的格式化程序中可以有带有 [] 的可选部分,但我不确定是否可以将这些规则应用于这样的格式化程序。
当使用DateTimeFormatter.ofPattern("Hmm")
时,900和1111可以被解析,但11(显然)不能。
但是使用[H]mm
,900和1111都解析不了
但是[HH]mm
,可以解析1111,但不能解析900
我试过
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("[HH][m]m");
// or
formatter = DateTimeFormatter.ofPattern("[H]mm");
System.out.println(LocalTime.parse("1111",formatter));
System.out.println(LocalTime.parse("900",formatter));
System.out.println(LocalTime.parse("1",formatter));
System.out.println(LocalTime.parse("11",formatter));
System.out.println(LocalTime.parse("201",formatter));
System.out.println(LocalTime.parse("1000",formatter));
System.out.println(LocalTime.parse("0",formatter));
// assertions
assertThat(LocalTime.parse("1111",formatter), CoreMatchers.equalTo(LocalTime.of(11,11)));
assertThat(LocalTime.parse("900",formatter), CoreMatchers.equalTo(LocalTime.of(9,00)));
assertThat(LocalTime.parse("1",formatter), CoreMatchers.equalTo(LocalTime.of(0,1)));
assertThat(LocalTime.parse("201",formatter), CoreMatchers.equalTo(LocalTime.of(2,1)));
assertThat(LocalTime.parse("1000",formatter), CoreMatchers.equalTo(LocalTime.of(10,0)));
assertThat(LocalTime.parse("0",formatter), CoreMatchers.equalTo(LocalTime.of(0,0)));
但这不起作用,抛出异常
Exception in thread "main" java.time.format.DateTimeParseException: Text '1111' could not be parsed at index 4
DateTimeFormatter
中没有可以解析您想要的内容的模式。此外,DateTimeFormatterBuilder
无法帮助您。主要问题是解析器是贪婪的,所以任何设置都会将第一个 one/two 数字解析为小时,留下分钟。这与您的规格不符。
选项 1:
使用这种方法:
DateTimeFormatter f = new DateTimeFormatterBuilder()
.appendValue(HOUR_OF_DAY)
.appendValue(MINUTE_OF_HOUR, 2)
.toFormatter();
LocalTime time = LocalTime.parse("0000" + str, f);
这种方法使模式规则化,分钟的位数固定。需要注意的是 DateTimeFormatter.ofPattern("Hmm")
也可以,但是我使用了上面的长格式来使它更明显。
选项 2:
编写一个 TemporalField
的实现来处理上面定义的整数格式。然后在 DateTimeFormatterBuilder
中使用它。对于这种需求来说,这要困难得多,也太过分了,但为了完整起见,在这里提到。
解决方法如下:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.optionalStart()
.appendValue(ChronoField.HOUR_OF_DAY, 2)
.appendValue(ChronoField.MINUTE_OF_HOUR, 2)
.optionalEnd()
.optionalStart()
.appendValue(ChronoField.HOUR_OF_DAY, 1)
.appendValue(ChronoField.MINUTE_OF_HOUR, 2)
.optionalEnd()
.optionalStart()
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.appendValue(ChronoField.MINUTE_OF_HOUR)
.optionalEnd()
.toFormatter();
我有一些数据库,我有一些 LocalTime
and I am trying to build a DateTimeFormatter
的自定义格式。
规则如下:
- 0 => 00:00
- 10 => 00:10
- 111 => 1:11
- 101 => 1:01
- 1111 => 11:11
在这样的格式化程序中可以有带有 [] 的可选部分,但我不确定是否可以将这些规则应用于这样的格式化程序。
当使用DateTimeFormatter.ofPattern("Hmm")
时,900和1111可以被解析,但11(显然)不能。
但是使用[H]mm
,900和1111都解析不了
但是[HH]mm
,可以解析1111,但不能解析900
我试过
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("[HH][m]m");
// or
formatter = DateTimeFormatter.ofPattern("[H]mm");
System.out.println(LocalTime.parse("1111",formatter));
System.out.println(LocalTime.parse("900",formatter));
System.out.println(LocalTime.parse("1",formatter));
System.out.println(LocalTime.parse("11",formatter));
System.out.println(LocalTime.parse("201",formatter));
System.out.println(LocalTime.parse("1000",formatter));
System.out.println(LocalTime.parse("0",formatter));
// assertions
assertThat(LocalTime.parse("1111",formatter), CoreMatchers.equalTo(LocalTime.of(11,11)));
assertThat(LocalTime.parse("900",formatter), CoreMatchers.equalTo(LocalTime.of(9,00)));
assertThat(LocalTime.parse("1",formatter), CoreMatchers.equalTo(LocalTime.of(0,1)));
assertThat(LocalTime.parse("201",formatter), CoreMatchers.equalTo(LocalTime.of(2,1)));
assertThat(LocalTime.parse("1000",formatter), CoreMatchers.equalTo(LocalTime.of(10,0)));
assertThat(LocalTime.parse("0",formatter), CoreMatchers.equalTo(LocalTime.of(0,0)));
但这不起作用,抛出异常
Exception in thread "main" java.time.format.DateTimeParseException: Text '1111' could not be parsed at index 4
DateTimeFormatter
中没有可以解析您想要的内容的模式。此外,DateTimeFormatterBuilder
无法帮助您。主要问题是解析器是贪婪的,所以任何设置都会将第一个 one/two 数字解析为小时,留下分钟。这与您的规格不符。
选项 1:
使用这种方法:
DateTimeFormatter f = new DateTimeFormatterBuilder()
.appendValue(HOUR_OF_DAY)
.appendValue(MINUTE_OF_HOUR, 2)
.toFormatter();
LocalTime time = LocalTime.parse("0000" + str, f);
这种方法使模式规则化,分钟的位数固定。需要注意的是 DateTimeFormatter.ofPattern("Hmm")
也可以,但是我使用了上面的长格式来使它更明显。
选项 2:
编写一个 TemporalField
的实现来处理上面定义的整数格式。然后在 DateTimeFormatterBuilder
中使用它。对于这种需求来说,这要困难得多,也太过分了,但为了完整起见,在这里提到。
解决方法如下:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.optionalStart()
.appendValue(ChronoField.HOUR_OF_DAY, 2)
.appendValue(ChronoField.MINUTE_OF_HOUR, 2)
.optionalEnd()
.optionalStart()
.appendValue(ChronoField.HOUR_OF_DAY, 1)
.appendValue(ChronoField.MINUTE_OF_HOUR, 2)
.optionalEnd()
.optionalStart()
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.appendValue(ChronoField.MINUTE_OF_HOUR)
.optionalEnd()
.toFormatter();