57

我最近迁移到 Java 8,希望能更轻松地处理本地和分区时间。

但是,在我看来,在解析简单日期时,我面临着一个简单的问题。

public static ZonedDateTime convertirAFecha(String fecha) throws Exception {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
            ConstantesFechas.FORMATO_DIA).withZone(
            obtenerZonaHorariaServidor());

    ZonedDateTime resultado = ZonedDateTime.parse(fecha, formatter);
    return resultado;
}

就我而言:

  • fecha 是 '15/06/2014'
  • ConstantesFechas.FORMATO_DIA 是 'dd/MM/yyyy'
  • obtenerZonaHorariaServidor 返回 ZoneId.systemDefault()

所以,这是一个简单的例子。但是,解析会引发此异常:

java.time.format.DateTimeParseException:无法解析文本“15/06/2014”:无法从 TemporalAccessor 获取 ZonedDateTime:{},ISO 解析为 java.time.format.Parsed 类型的 2014-06-15

有小费吗?我一直在尝试解析和使用 TemporalAccesor 的不同组合,但到目前为止没有任何运气。

4

5 回答 5

60

这不起作用,因为您的输入(和您的格式化程序)没有时区信息。一种简单的方法是将您的日期解析为LocalDate第一个(没有时间或时区信息),然后创建一个ZonedDateTime

public static ZonedDateTime convertirAFecha(String fecha) {
  DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
  LocalDate date = LocalDate.parse(fecha, formatter);

  ZonedDateTime resultado = date.atStartOfDay(ZoneId.systemDefault());
  return resultado;
}
于 2014-05-11T18:54:31.673 回答
16

这是一个错误,请参阅JDK-bug-log。根据该信息,Java 9 和 Java 8u20 的问题已解决。尝试下载最新的 Java 8 - 版本。2014 年 5月 12 日今天:有一个早期访问版本 8u20可用。

更新:

我个人认为,由于您只有并期望“dd/MM/yyyy”作为模式,您应该将LocalDate其用作@assylias 已经提出的主要类型。关于您的上下文,几乎可以肯定使用ZonedDateTime. 你想对这种类型的对象做什么?我只能将专门的时区计算视为用例。而且您甚至不能直接将这些ZonedDateTime对象存储在数据库中,因此这种类型远没有许多人认为的有用。

我所描述的你的用例问题确实是 Java-8 引入的一个新方面,与旧的GregorianCalendar-class (这是一个多合一类型)相比。用户必须开始考虑为他们的问题和用例选择合适的时间类型。

于 2014-05-12T09:43:14.337 回答
13

简而言之,这条线

ZonedDateTime.parse('2014-04-23', DateTimeFormatter.ISO_OFFSET_DATE_TIME)

抛出异常:

Text '2014-04-23' could not be parsed at index 10
java.time.format.DateTimeParseException: Text '2014-04-23' could not be parsed at index 10

对我来说它看起来像一个错误。

我使用了这个解决方法:

String dateAsStr = '2014-04-23';
if (dateAsStr.length() == 10) {
    dateAsStr += 'T00:00:00';
}
ZonedDateTime.parse(dateAsStr, DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneId.systemDefault()));
于 2014-12-04T03:36:00.963 回答
5

如果来自谷歌:

而不是这样做:

ZonedDateTime.from(new Date().toInstant());

尝试这个:

ZonedDateTime.ofInstant(new Date(), ZoneId.of("UTC")); 
于 2018-03-02T00:19:58.413 回答
2

只是一个示例转换,我相信有些人会得到下面的异常

(java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: 2014-10-24T18:22:09.800Z of type java.time.Instant)

如果他们尝试

LocalDateTime localDateTime = LocalDateTime.from(new Date().toInstant());

要解决此问题,请传入 Zone -

LocalDateTime localDateTime = LocalDateTime.from(new Date()
        .toInstant().atZone(ZoneId.of("UTC")));
于 2015-10-27T13:53:12.690 回答