无法使用 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 return ZoneId.systemDefault()

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

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

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


答案 1

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

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;
}

答案 2

这是一个错误,请参阅 JDK-bug-log。根据这些信息,Java 9和Java 8u20的问题得到了解决。尝试下载最新的 Java 8 版本。今天是 2014-05-12:有一个抢先体验版本 8u20 可用。

更新:

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

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