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

时间:2018-03-16 14:22:55

标签: 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

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

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

对我来说不是一个选择。

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

3 个答案:

答案 0 :(得分:5)

只需使用构建器DateTimeFormatterBuilder

创建自定义格式化程序
sessionInfo()

R version 3.4.1 (2017-06-30)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Debian GNU/Linux 8 (jessie)

Matrix products: default
BLAS: ~/local/anaconda3/envs/mro_env/lib/R/lib/libRblas.so
LAPACK: ~/local/anaconda3/envs/mro_env/lib/R/lib/libRlapack.so

locale:
 [1] LC_CTYPE=en_US.UTF-8      LC_NUMERIC=C              LC_TIME=en_US.utf8       
 [4] LC_COLLATE=en_US.utf8     LC_MONETARY=en_US.utf8    LC_MESSAGES=en_US.utf8   
[7] LC_PAPER=en_US.utf8       LC_NAME=C                 LC_ADDRESS=C             

[10] LC_TELEPHONE=C            LC_MEASUREMENT=en_US.utf8 LC_IDENTIFICATION=C      

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] compiler_3.4.1 magrittr_1.5   tools_3.4.1    yaml_2.1.17

此格式化程序使用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

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

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

答案 1 :(得分:3)

使用keep(...)的Jose的回答很不错。如果您不想使用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()为10例如:上午30点。

答案 2 :(得分:0)

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

由于您需要设置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));

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