Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ZoneDateTime解析成功,但输出字符串不同_Java_Java 8_Zoneddatetime - Fatal编程技术网

Java ZoneDateTime解析成功,但输出字符串不同

Java ZoneDateTime解析成功,但输出字符串不同,java,java-8,zoneddatetime,Java,Java 8,Zoneddatetime,我正在使用zoneDateTime根据时区解析并获取当前时间 当我解析以下字符串时,解析成功,但输出的字符串不同。为什么呢 String dateTimeString = "2016-05-04T12:58:22+01:00[Europe/Paris]"; ZonedDateTime dateTime = ZonedDateTime.parse(dateTimeString, ISO_ZONED_DATE_TIME); System.out.println(dateTimeString); Sy

我正在使用
zoneDateTime
根据时区解析并获取当前时间

当我解析以下
字符串
时,解析成功,但输出的
字符串
不同。为什么呢

String dateTimeString = "2016-05-04T12:58:22+01:00[Europe/Paris]";
ZonedDateTime dateTime = ZonedDateTime.parse(dateTimeString, ISO_ZONED_DATE_TIME);
System.out.println(dateTimeString);
System.out.println(dateTime.toString());
输出

2016-05-04T12:58:22+01:00[Europe/Paris]
2016-05-04T12:58:22+02:00[Europe/Paris]
它在什么时候决定将
+1
更改为
+2
,为什么没有引发异常

我知道括号
[Europe/Paris]
中的参数是可选的,但在这里它优先于偏移量

另一方面,下面的代码

String dateTimeString = "2016-05-04T12:58:22+01:00";
ZonedDateTime dateTime = ZonedDateTime.parse(dateTimeString, ISO_ZONED_DATE_TIME);
System.out.println(dateTimeString);
System.out.println(dateTime.toString());
产出

2016-05-04T12:58:22+01:00
2016-05-04T12:58:22+01:00

问题是,
2016-05-04T12:58:22+01:00[欧洲/巴黎]
不是正确的时间,因为我们在5月份有CEST(中欧夏令时,夏令时),从3月份的最后一个星期日开始。与UTC相比为+2h。所以实际上,
2016-05-04T12:58:22+02:00[欧洲/巴黎]
是正确的

正如你所说,
[欧洲/巴黎]
似乎受到重视。不确定是否应该有一个关于规范的例外,但我怀疑它

换言之,
2016-05-04T12:58:22+01:00
不能在时区
Europe/Paris
功能中;不是虫子。
zoneDateTime#parse
赋予
ZoneId
的优先级高于
ZoneOffset
。报告明确提到:

就设计而言,此类课程应主要视为
LocalDateTime
ZoneId
的组合。
ZoneOffset
是一个 重要但次要的信息,用于确保 类表示一个瞬间,特别是在夏令时 重叠

通过查看反编译的源代码可以进一步理解:

班级分区日期时间

public static ZonedDateTime parse(CharSequence text) {
    return parse(text, DateTimeFormatter.ISO_ZONED_DATE_TIME);
}

public static ZonedDateTime parse(CharSequence text, DateTimeFormatter formatter) {
    Objects.requireNonNull(formatter, "formatter");
    return formatter.parse(text, ZonedDateTime::from);
}

public static ZonedDateTime from(TemporalAccessor temporal) {
    if (temporal instanceof ZonedDateTime) {
        return (ZonedDateTime) temporal;
    }
    try {
        ZoneId zone = ZoneId.from(temporal);
        if (temporal.isSupported(INSTANT_SECONDS)) {
            long epochSecond = temporal.getLong(INSTANT_SECONDS);
            int nanoOfSecond = temporal.get(NANO_OF_SECOND);
            return create(epochSecond, nanoOfSecond, zone);
        } else {
            LocalDate date = LocalDate.from(temporal);
            LocalTime time = LocalTime.from(temporal);
            return of(date, time, zone);
        }
    } catch (DateTimeException ex) {
        throw new DateTimeException("Unable to obtain ZonedDateTime from TemporalAccessor: " +
                temporal + " of type " + temporal.getClass().getName(), ex);
    }
}
类分区ID

public static ZoneId from(TemporalAccessor temporal) {
    ZoneId obj = temporal.query(TemporalQueries.zone());
    if (obj == null) {
        throw new DateTimeException("Unable to obtain ZoneId from TemporalAccessor: " +
                temporal + " of type " + temporal.getClass().getName());
    }
    return obj;
}
类临时查询

public static TemporalQuery<ZoneId> zone() {
    return TemporalQueries.ZONE;
}

static final TemporalQuery<ZoneId> ZONE = new TemporalQuery<>() {
    @Override
    public ZoneId queryFrom(TemporalAccessor temporal) {
        ZoneId zone = temporal.query(ZONE_ID);
        return (zone != null ? zone : temporal.query(OFFSET));// <----- Look at this line
    }

    @Override
    public String toString() {
        return "Zone";
    }
};
输出:

2016-05-04T12:58:22+01:00
2016-05-04T12:58:22+01:00
再一次,这是一个特征;这不是一个错误,因为您要求系统使用固定的
区域偏移
信息解析日期时间字符串。作为一个简单的类比,您可以将
ZoneOffset
看作是逐字计算的,而
ZoneId
则是可变计算的

以下几点可能对您和未来的访客有用:

2016-05-04T12:58:22+01:00
2016-05-04T12:58:22+01:00
  • 日期-时间字符串,
    2016-05-04T12:58:22+01:00[欧洲/巴黎]
    已采用的默认格式,因此,您无需将
    DateTimeFormatter
    作为参数传递给它
  • System.out.println
    自动打印参数对象的
    toString
    方法返回的字符串,因此不需要显式调用
    toString
  • 所以你的代码

    import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME;
    
    import java.time.ZonedDateTime;
    
    public class Main {
        public static void main(String[] args) {
            String dateTimeString = "2016-05-04T12:58:22+01:00[Europe/Paris]";
            ZonedDateTime dateTime = ZonedDateTime.parse(dateTimeString, ISO_ZONED_DATE_TIME);
            System.out.println(dateTime.toString());
        }
    }
    
    可以简单地写为

    import java.time.ZonedDateTime;
    
    public class Main {
        public static void main(String[] args) {
            String dateTimeString = "2016-05-04T12:58:22+01:00[Europe/Paris]";
            ZonedDateTime dateTime = ZonedDateTime.parse(dateTimeString);
            System.out.println(dateTime);
        }
    }
    

    谢谢你的回复。我知道这是一个错误的日期,为什么它能成功解析?这是一个设计缺陷。我猜规范中有定义的优先级。但我没有检查。