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

吾辈知道使用 LocalDate 可以解析,难道 LocalDateTime 就不能转换 yyyy-MM-dd 这种格式的字符串么?

阅读 37.7k
2 个回答

吾辈已经找到了解决方法,同时也把这个问题整理成了一篇 记录,同时欢迎来吾辈的博客玩 https://blog.rxliuli.com/
下面是这个问题找到的解决方法,以及吾辈最后的选择

解决

先转换为 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();

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

LocalDateTime 其实是 LocalDate + LocalTime 两部分都得有

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏