繁体   English   中英

将日期或日期时间都解析为 Java 8 中的 LocalDateTime

[英]Parse date or datetime both as LocalDateTime in Java 8

我需要解析一个字段,该字段有时作为日期给出,有时作为日期/时间给出。 是否可以使用 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

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

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

不是我的选择。

欢迎任何其他建议如何以干净的方式对其进行编码。

只需使用构建器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();

此格式化程序使用[]括号来允许格式中的可选部分,并添加小时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);

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

System.out.println(localDateTime1); // 1994-05-13T00:00
System.out.println(localDateTime2); // 1994-05-13T23:00

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

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

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd[ HH:mm:ss]");

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

TemporalAccessor parsed = fmt.parseBest("1986-04-08", LocalDateTime::from, LocalDate::from);

在这种情况下,它会首先尝试创建一个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);
}

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

我知道答案迟到了,但它可以帮助其他人......

由于 LocalDateTime 需要设置时间,否则您可以只使用 LocalDate,我搜索了 LocalDateTime 内置解决方案来处理这个问题。 我没有找到,但是我使用了以下方法:

// For specific date (the same as the question)
LocalDateTime specificDate LocalDateTime.of(LocalDate.of(1986, 4, 8), LocalTime.MIN);

其他例子:

// For the start of day
LocalDateTime startToday = LocalDateTime.of(LocalDate.now(), LocalTime.MIN));

// For the end of day
LocalDateTime endOfToday = LocalDateTime.of(LocalDate.now(), LocalTime.MAX));

这样你就不需要使用格式化程序。 :)

根据何塞·达席尔瓦的回答

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .parseCaseInsensitive()
    .append(DateTimeFormatter.ISO_LOCAL_DATE)
    .optionalStart()
    .appendLiteral(' ') // might be 'T' in your case
    .append(DateTimeFormatter.ISO_LOCAL_TIME)
    .optionalEnd()
    .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
    .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
    .toFormatter()
    .withResolverStyle(ResolverStyle.STRICT); // parse STRICT instead of SMART!

用法:

LocalDateTime localDateTime1 = LocalDateTime.parse("1994-05-13", formatter);
LocalDateTime localDateTime2 = LocalDateTime.parse("1994-05-13 23:00:00", formatter);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM