无法使用Java 8中的DateTimeFormatter和ZonedDateTime从TemporalAccessor获取ZonedDateTime

我最近转向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()

所以,这是一个简单的例子。 但是,解析会抛出此exception:

 java.time.format.DateTimeParseException: Text '15/06/2014' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {},ISO resolved to 2014-06-15 of type java.time.format.Parsed 

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

最好的祝福

我不确定为什么它不起作用(可能是因为您的输入没有时间/时区信息)。 一种简单的方法是首先将您的日期解析为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; } 

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

更新:

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

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

简单来说就行了

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

抛出exception:

 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())); 

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

 (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()); 

要解决问题,请通过区域 –

 LocalDateTime localDateTime = LocalDateTime.from(new Date() .toInstant().atZone(ZoneId.of("UTC"))); 

如果来自Google:

而不是做:

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

尝试这个:

 ZonedDateTime.ofInstant(new Date(), ZoneId.of("UTC"));