首页 > 解决方案 > 将非 ISO 8601 解析为 ISO_INSTANT

问题描述

我正在尝试将这个字符串2020-05-20 14:27:00.943000000 +00:00和这个解析Wed May 20 14:27:00 CEST 2020为一个 ISO_INSTANT,但总是返回这个异常

java.time.format.DateTimeParseException: Text '2020-05-20 14:27:00.943000000 +00:00' could not be parsed at index 10

我的代码是:

protected Instant parseDateTime(String fechaHora) {

        DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
        TemporalAccessor temporalAccessor = formatter.parse(fechaHora);
        LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor);
        ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());
        Instant result = Instant.from(zonedDateTime);
        return result; }

我怎样才能转换这种类型?

标签: javadateparsingtimeinstant

解决方案


tl;博士

OffsetDateTime.parse( 
    "2020-05-20 14:27:00.943000000 +00:00" , 
    DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss.SSSSSSSSS xxx" )
)
.toInstant()

修复你的代码

您的代码在几个方面存在缺陷。

这里的使用TemporalAccessor是不必要和不恰当的。引用它的 Javadoc

该接口是框架级接口,不应在应用程序代码中广泛使用。相反,应用程序应该创建和传递具体类型的实例

LocalDateTime在这里不合适,因为它会删除重要信息、时区或与 UTC 的偏移量。

您指定了一个格式化程序,其格式化模式与您的输入不匹配。

解决方案

处理您的输入字符串以符合标准ISO 8601格式。用 替换日期和时间之间的空格T。删除时间和偏移量之间的空间。

String input = "2020-05-20 14:27:00.943000000 +00:00" ;
String[] strings = input.split( " " ) ;
String modifiedInput = strings[0] + "T" + strings[1] + strings[2] ;

在从 UTC 偏移的上下文中解析为一个OffsetDateTime带有时间的日期。

OffsetDateTime odt = OffsetDateTime.parse( modifiedInput ) ;

或者,定义格式模式以匹配您的输入字符串。使用DateTimeFormatter类。这已在 Stack Overflow 上多次介绍过,因此请搜索以了解更多信息。

您尝试使用的预定义格式化程序DateTimeFormatter.ISO_INSTANT与您的输入不匹配。您的输入不符合该格式化程序使用的 ISO 8601 标准。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss.SSSSSSSSS xxx" ) ;
String input = "2020-05-20 14:27:00.943000000 +00:00" ;
OffsetDateTime odt = OffsetDateTime.parse( input , f ) ;

请参阅在 IdeOne.com 上实时运行的代码

odt.toString(): 2020-05-20T14:27:00.943Z

如果你需要返回一个Instant,调用toInstant

Instant instant = odt.toInstant() ;

要在时区的上下文中查看同一时刻,请应用 aZoneId来获取ZonedDateTime对象。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

和对象代表同一时刻,时间轴上的同一点OffsetDateTimeZonedDateTime


推荐阅读