我需要解析一个有时作为日期而有时作为日期/时间的字段。是否可以使用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()
}
对我来说不是一个选择。
欢迎任何其他建议如何以干净的方式编码。
答案 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));
这样,您就不需要使用格式化程序。 :)