仅将日期解析为Java 8中的LocalDateTime

Kam*_*man 4 java java-8 java-time

我需要解析一个有时作为日期而有时作为日期/时间的字段.是否可以使用Java 8时间API为此使用单一数据类型?目前,我尝试使用LocalDateTime,但是对于以下调用,LocalDateTime.parse("1986-04-08", DateTimeFormatter.ofPattern("yyyy-MM-dd")) 我得到了一个

java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: {},ISO resolved to 1986-04-08 of type java.time.format.Parsed
Run Code Online (Sandbox Code Playgroud)

这是一些通用解析器的一部分,它接受日期/日期时间解析模式作为配置选项.因此,例如遵循具有硬编码解析模式的解决方案

if ("yyyy-MM-dd".equals(pattern)) {
    LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd"))).atStartOfDay()
}
Run Code Online (Sandbox Code Playgroud)

对我来说不是一个选择.

任何其他建议如何以干净的方式编码它是受欢迎的.

Jos*_*lva 8

只需使用构建器DateTimeFormatterBuilder创建自定义格式化程序

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .appendPattern("yyyy-MM-dd[ HH:mm:ss]")
        .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
        .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
        .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
        .toFormatter();
Run Code Online (Sandbox Code Playgroud)

此格式化程序使用[]括号来允许格式中的可选部分,并添加小时HOUR_OF_DAY,分钟MINUTE_OF_HOUR和秒的默认值SECOND_OF_MINUTE.

注意:您可以省略,分钟和秒,只需提供小时即可.

像往常一样使用它.

LocalDateTime localDateTime1 = LocalDateTime.parse("1994-05-13", formatter);
LocalDateTime localDateTime2 = LocalDateTime.parse("1994-05-13 23:00:00", formatter);
Run Code Online (Sandbox Code Playgroud)

这将输出正确的日期时间,默认小时数为0(当天开始).

System.out.println(localDateTime1); // 1994-05-13T00:00
System.out.println(localDateTime2); // 1994-05-13T23:00
Run Code Online (Sandbox Code Playgroud)


小智 5

何塞的回答使用parseDefaulting很好。还有另一种选择,如果您不想使用DateTimeFormatterBuilder.

首先,您使用可选部分创建格式化程序 - 在本例中,是时间部分,由[]以下内容分隔:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd[ HH:mm:ss]");
Run Code Online (Sandbox Code Playgroud)

然后调用parseBest,提供String要解析的 和方法引用列表:

TemporalAccessor parsed = fmt.parseBest("1986-04-08", LocalDateTime::from, LocalDate::from);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,它会首先尝试创建一个LocalDateTime,如果不可能,它会尝试创建一个LocalDate(如果都不可能,它会抛出异常)。

然后,您可以检查返回的是哪种类型,并采取相应措施:

LocalDateTime dt;
if (parsed instanceof LocalDateTime) {
    // it's a LocalDateTime, just assign it
    dt = (LocalDateTime) parsed;
} else if (parsed instanceof LocalDate) {
    // it's a LocalDate, set the time to whatever you want
    dt = ((LocalDate) parsed).atTime(LocalTime.MIDNIGHT);
}
Run Code Online (Sandbox Code Playgroud)

如果结果是LocalDate,您可以atStartOfDay()按照其他人的建议选择调用,或者更改为特定的时间,例如atTime(LocalTime.of(10, 30))上午 10:30。