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

Fal*_*orn 36 java timezone datetime-format java-8 java-time

我最近搬到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;
}
Run Code Online (Sandbox Code Playgroud)

就我而言:

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

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

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
Run Code Online (Sandbox Code Playgroud)

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

最好的祝福

ass*_*ias 34

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

  • 顺便说一句,除了使用 LocalDate 之外,另一个解决方案是使用 DateTimeFormatter.withZone(x) 为 Formatter 设置默认时区。然后你可以使用ZonedDateTime,它总是有时区x。 (3认同)
  • 是的,出现问题是因为格式化程序不提供时区。我编辑了你的答案来强调这一点。你是对的 :-)。 (2认同)

Men*_*ild 15

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

更新:

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

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

  • 更好的错误报告链接是https://bugs.openjdk.java.net/browse/JDK-8033662 (3认同)
  • 不错的收获 - 尽管我相信 op 仍然需要提供时间才能将输入解析为 ZonedDateTime。 (2认同)

ano*_*932 8

如果来自 Google:

而不是这样做:

ZonedDateTime.from(new Date().toInstant());
Run Code Online (Sandbox Code Playgroud)

尝试这个:

ZonedDateTime.ofInstant(new Date(), ZoneId.of("UTC")); 
Run Code Online (Sandbox Code Playgroud)


sto*_*ito 5

简单来说就行了

ZonedDateTime.parse('2014-04-23', DateTimeFormatter.ISO_OFFSET_DATE_TIME)
Run Code Online (Sandbox Code Playgroud)

抛出异常:

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
Run Code Online (Sandbox Code Playgroud)

对我来说这看起来像个错误.

我使用了这个解决方法:

String dateAsStr = '2014-04-23';
if (dateAsStr.length() == 10) {
    dateAsStr += 'T00:00:00';
}
ZonedDateTime.parse(dateAsStr, DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneId.systemDefault()));
Run Code Online (Sandbox Code Playgroud)

  • 这是一个dateTIME,所以没有时间部分的字符串不是有效的日期时间...... (2认同)