首页 > 解决方案 > 根据解析的 TemporalAccessor 有条件地创建 LocalDateTime、ZonedDateTime 或 OffsetDateTime

问题描述

给定一个DateTimeFormatter定义为:

public static final DateTimeFormatter DATE_TIME = new DateTimeFormatterBuilder()
        .parseCaseInsensitive()
        .append( ISO_LOCAL_DATE )
        .optionalStart().appendLiteral( ' ' ).optionalEnd()
        .optionalStart().appendLiteral( 'T' ).optionalEnd()
        .append( ISO_LOCAL_TIME )
        .optionalStart().appendLiteral( ' ' ).optionalEnd()
        .optionalStart().appendZoneOrOffsetId().optionalEnd()
        .toFormatter();

我想有条件地创建一个LocalDateTimeZonedDateTimeOffsetDateTime基于解析是否包含区域ID、偏移量或两者都不包含。

到目前为止,我有:

    DATE_TIME.parse(
            text,
            (temporal) -> {
                // see if there is an offset
                final ZoneOffset offset = temporal.query( TemporalQueries.offset() );
                if ( offset != null ) {
                    return OffsetDateTime.from( temporal );
                }

                // see if there is a tz
                final ZoneId zoneId = temporal.query( TemporalQueries.zoneId() );
                if ( zoneId != null ) {
                    return ZonedDateTime.from( temporal );
                }

                // otherwise its a LocalDateTime
                return LocalDateTime.from( temporal );
            }
    );

但我发现,区域偏移量永远不会被“识别”——即使文本包含偏移量,它也总是被报告为区域 ID。例如,鉴于"1999-12-31 12:59:59 +02:00"我期望一个OffsetDateTime. 但是,"+02:00"始终将其解析为区域 ID。最终,考虑到分区和偏移之间的互惠,它可以工作。但作为(可能超出顶部)正确性的问题,我想将这些视为OffsetDateTime.

我是否缺少能够做出这种区分的东西?

谢谢!

标签: javadatetime

解决方案


看起来这实际上是 Java 8 中的一个错误。如果将 的值存储DateTimeFormatter#parseTemporal变量中并打印其getClass(),则在使用 Java 8 编译和运行时会收到以下信息:

class java.time.ZonedDateTime

但是,当使用 Java 11 编译和运行时,输出是您所期望的:

class java.time.OffsetDateTime

如果我设法找到它,我将四处搜索特定的错误报告并编辑此答案。这样,我们就可以确定错误的原因以及修复它的 Java 版本。


推荐阅读