已经存在问题Java 8 DateTimeFormatter with optional part,但是当可选部分仅为小时和分钟而没有秒时,该问题的答案将无效:
DateTimeFormatter patternWithOptional = new DateTimeFormatterBuilder()
.appendPattern("M/d/yyyy[ h:mm]")
.toFormatter();
TemporalAccessor tmp = patternWithOptional.parseBest("4/11/2020 1:20", LocalDateTime::from, LocalDate::from);
System.out.println(tmp);
System.out.println(tmp.getClass().getSimpleName());
// prints 2020-04-11, without time
// class is LocalDate in this case
这是因为LocalDateTime.from(TemporalAccessor temporal)
使用TemporalQueries.LOCAL_TIME
来查询temporal
。 TemporalQueries.LOCAL_TIME
依次要求ChronoField.NANO_OF_DAY
中的temporal
可用。
System.out.println(patternWithOptional.parse("4/11/2020 1:20"));
// prints:
{HourOfAmPm=1, MinuteOfHour=20},ISO resolved to 2020-04-11
由于HourOfAmPm
和MinuteOfHour
可用,因此可以提出我所需的最简单方法:
private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
.appendPattern("M/d/yyyy[ h:mm]")
.toFormatter();
public static void main(String[] args) {
// demo
System.out.println(parse("3/20/1995")); // without time
System.out.println(parse("4/11/2020 1:20")); // with time
}
private static LocalDateTime parse(String s) {
TemporalAccessor parsed = FORMATTER.parse(s);
return LocalDateTime.of(
LocalDate.from(parsed),
LocalTime.of(
parsed.isSupported(ChronoField.HOUR_OF_AMPM)
? (int) ChronoField.HOUR_OF_AMPM.getFrom(parsed)
: 0,
parsed.isSupported(ChronoField.MINUTE_OF_HOUR)
? (int) ChronoField.MINUTE_OF_HOUR.getFrom(parsed)
: 0
) // minor note: this part could also be used as a lambda argument for parseBest method.
);
}
有没有更简单的方法而无需显式isSupported
检查?
答案 0 :(得分:3)
在格式模式字符串中,您需要在一天中的时间中使用大写的H
:
.appendPattern("M/d/yyyy[ H:mm]")
进行此更改后,您的第一段代码就会打印
2020-04-11T01:20
LocalDateTime
小写h
在AM或PM内持续一个小时。因此,您的时间可能意味着01:20 AM或01:20 PM,即13:20。 Java无法决定,因此选择不解释一天中的时间,只给您LocalDate
。
如果您始终想要LocalDateTime
,则也可以使用parseDefaulting
:
DateTimeFormatter patternWithOptional = new DateTimeFormatterBuilder()
.appendPattern("M/d/yyyy[ H:mm]")
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.toFormatter();
System.out.println(LocalDateTime.parse("4/11/2020 1:20", patternWithOptional));
System.out.println(LocalDateTime.parse("4/11/2020", patternWithOptional));
输出:
2020-04-11T01:20
2020-04-11T00:00
另一方面,如果您要做要根据字符串中是否有一天中的可用时间来使用LocalDate
或LocalDateTime
,则不需要DateTimeFormatterBuilder
:
DateTimeFormatter patternWithOptional = DateTimeFormatter.ofPattern("M/d/yyyy[ H:mm]");