本文最后更新于:2020年12月30日 凌晨
场景 在 Java 中使用 LocalDateTime
解析 String
失败
代码如下
1 2 final LocalDateTime result = LocalDateTime.parse("2000-01-01" , DateTimeFormatter.ofPattern("yyyy-MM-dd" )); log.info("result: {}" , result);
抛出异常
1 java.time.format.DateTimeParseException: Text '2000-01-01' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {},ISO resolved to 2000-01-01 of type java.time.format.Parsed
吾辈也在 SegmentFault 上提出了这个问题,然而直到写出这篇记录时然而没有人告诉吾辈答案。。。
解决 先转换为 LocalDate 再二次转换 吾辈首先找到了一种笨方法
先解析为 LocalDate
将 LocalDate
转换为 LocalDateTime
。
1 2 3 final LocalDateTime localDateTime = LocalDate.parse("2018-12-11" , DateTimeFormatter.ISO_DATE).atStartOfDay(); assertThat(localDateTime) .isNotNull();
使用 DateTimeFormatter.ISO_DATE
解析文本并得到 TemporalAccessor
对象
使用 temporalAccessor.get
方法获取指定属性
使用 LocalDateTime.of
构造一个 LocalDateTime
对象
1 2 3 4 5 6 7 8 9 10 11 final TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_DATE.parse("2018-12-11" );final LocalDateTime localDateTime = LocalDateTime.of( secureGet(temporalAccessor, ChronoField.YEAR), secureGet(temporalAccessor, ChronoField.MONTH_OF_YEAR), secureGet(temporalAccessor, ChronoField.DAY_OF_MONTH), secureGet(temporalAccessor, ChronoField.HOUR_OF_DAY), secureGet(temporalAccessor, ChronoField.MINUTE_OF_HOUR), secureGet(temporalAccessor, ChronoField.SECOND_OF_MINUTE), secureGet(temporalAccessor, ChronoField.NANO_OF_SECOND) ); log.info("localDateTime: {}" , localDateTime);
secureGet
是吾辈自定义的一个工具方法,具体看下面的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 private static int secureGet (TemporalAccessor temporalAccessor, ChronoField chronoField) { if (temporalAccessor.isSupported(chronoField)) { return temporalAccessor.get(chronoField); } return 0 ; }
吾辈在 StackOverflow 找到了一个好的方法
使用 DateTimeFormatterBuilder
构建 DateTimeFormatter
对象
赋予可选匹配项默认值(非常重要 )
使用 LocalDateTime.parse
进行解析
1 2 3 4 5 6 7 8 9 10 final DateTimeFormatter formatter = new DateTimeFormatterBuilder () .appendPattern("yyyy-MM-dd[['T'hh][:mm][:ss]]" ) .parseDefaulting(ChronoField.HOUR_OF_DAY, 0 ) .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0 ) .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0 ) .parseDefaulting(ChronoField.MILLI_OF_SECOND, 0 ) .toFormatter();final LocalDateTime localDateTime = LocalDateTime.parse("2018-12-11" , formatter); assertThat(localDateTime) .isNotNull();
最后一种方法满足了吾辈的需求,所以,也便是在这里记录一下啦