特征; 不是错误。
ZonedDateTime#parse
给予ZoneId
比更高的优先级ZoneOffset
。文档清楚地提到了它:
在设计方面,这个类应该主要被视为 aLocalDateTime
和 a的组合ZoneId
。这ZoneOffset
是一条重要但次要的信息,用于确保类代表一个瞬间,尤其是在夏令时重叠期间。
通过查看反编译的源代码可以进一步理解:
类 ZonedDateTime
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);
}
}
类 ZoneId
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;
}
类 TemporalQuery
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";
}
};
此外,整个要点ZonedDateTime
是您将其包含ZoneId
在其中,以便考虑到夏令时/夏令时,它可以自动为您提供正确的日期时间,例如在没有ZoneId
信息的情况下,以下代码将为您提供相同的打印输出声明:
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
String dateTimeString = "2016-05-04T12:58:22+01:00";
ZonedDateTime dateTime = ZonedDateTime.parse(dateTimeString);
System.out.println(dateTimeString);
System.out.println(dateTime.toString());
}
}
输出:
2016-05-04T12:58:22+01:00
2016-05-04T12:58:22+01:00
同样,这是一个功能。不是错误,因为您要求系统使用固定 ZoneOffset
信息解析日期时间字符串。做一个简单的类比,你可以认为是ZoneOffset
按字面意思求值,而ZoneId
要变量求值。
有几件事可能对您和未来的访客有用:
- 日期时间字符串
2016-05-04T12:58:22+01:00[Europe/Paris]
已采用默认格式ZonedDateTime#parse
,因此您无需将 aDateTimeFormatter
作为参数传递给它。
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);
}
}