Java 中 String 转 LocalDateTime 出现错误


Java 中 String 转 LocalDateTime 出现错误

场景

在 Java 中使用 LocalDateTime 解析 String 失败

代码如下

final LocalDateTime result = LocalDateTime.parse("2000-01-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
log.info("result: {}", result);

抛出异常

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 再二次转换

吾辈首先找到了一种笨方法

  1. 先解析为 LocalDate
  2. LocalDate 转换为 LocalDateTime
final LocalDateTime localDateTime = LocalDate.parse("2018-12-11", DateTimeFormatter.ISO_DATE).atStartOfDay();
assertThat(localDateTime)
    .isNotNull();

使用 DateTimeFormatter 先解析,然后转换为 LocalDateTime

  1. 使用 DateTimeFormatter.ISO_DATE 解析文本并得到 TemporalAccessor 对象
  2. 使用 temporalAccessor.get 方法获取指定属性
  3. 使用 LocalDateTime.of 构造一个 LocalDateTime 对象
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 是吾辈自定义的一个工具方法,具体看下面的代码

/**
  * 安全获取时间的某个属性
  *
  * @param temporalAccessor 需要获取的时间对象
  * @param chronoField      需要获取的属性
  * @return 时间的值,如果无法获取则默认为 0
  */
private static int secureGet(TemporalAccessor temporalAccessor, ChronoField chronoField) {
    if (temporalAccessor.isSupported(chronoField)) {
        return temporalAccessor.get(chronoField);
    }
    return 0;
}

使用 DateTimeFormatterBuilder 构建器

吾辈在 StackOverflow 找到了一个好的方法

  1. 使用 DateTimeFormatterBuilder 构建 DateTimeFormatter 对象
  2. 赋予可选匹配项默认值(非常重要
  3. 使用 LocalDateTime.parse 进行解析
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();

最后一种方法满足了吾辈的需求,所以,也便是在这里记录一下啦


文章作者: rxliuli
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 rxliuli !
 上一篇
2016 年里做前端是怎样一种体验 2016 年里做前端是怎样一种体验
2016 年里做前端是怎样一种体验 本文转载自 SegmentFault,英文原文在 How it feels to learn JavaScript in 2016吾辈觉得颇为有趣,便转载了一下(也算是前端开发的悲哀之处了吧)附:吾辈觉得
2019-03-16 rxliuli
下一篇 
Git 错误 Reset 恢复 Git 错误 Reset 恢复
Git 错误 Reset 恢复场景今天在帮同事操作 Git 的时候,因为没有清楚理解意思,吾辈错误撤回了一些提交。 具体使用的命令是 git reset dd256c7d66ad2e9671cbd47650ffddc4267ca7d5 感觉
2019-03-12 rxliuli
  目录