java.util.Date特殊日期1980-04-06:错误的时间



我们面临以下问题:

SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", java.util.Locale.GERMAN);
String dateInString = "06-04-1980";
Date date = formatter.parse(dateInString);

之前:1980年欧洲中部时间4月6日星期日00:00:00

之后:1980年欧洲中部时间4月6日星期日01:00:00

另一个例子:

Date date = Date.from(LocalDate.of(1980, 4, 6).atStartOfDay(ZoneId.systemDefault()).toInstant());

面对同样的问题。

我们认为将java11更改为java17是问题所在,但事实并非如此。这是时区从欧洲/柏林更改为欧洲-维也纳。1980-04-06年,奥地利实行夏令时,时间改为00:00。所以这一天没有00:00。

可再现示例-将时区更改为"0";欧洲/柏林";结果在0小时内。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
for (LocalDate date = LocalDate.of(1500, 04, 01); date.isBefore(LocalDate.of(9999, 1, 1)); date = date.plusDays(1)) {
Date out = Date.from(date.atStartOfDay(ZoneId.of("Europe/Vienna")).toInstant());
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone(ZoneId.of("Europe/Vienna")));
cal.setTime(out);
if (cal.get(Calendar.HOUR_OF_DAY) > 0) {
System.out.println(date.format(formatter) + " > " + cal.get(Calendar.HOUR_OF_DAY));
}
}
System.out.println("done");

1893-03-31年之前的所有日期都有23小时的时区";欧洲/维也纳";,在";欧洲/柏林";也是0。

这不是一个真正的问题,这是时区的一个特殊之处"欧洲/维也纳";这在我们的系统中发生了变化。如果你遇到这个问题,请检查你的时区,也许它被其他属性更改了。

虽然德国的夏令时间(夏令时(从当天的02:00开始,但奥地利(欧洲/维也纳时区(已经在午夜开始,所以00:00时间并不存在,这就是为什么我们突然得到01:00的原因。这两个时区都打印为中欧夏令时间,因此缩写不允许我们区分。

我在以色列,所以为了模拟中欧的时区(使用Java 17(,我使用Java命令的-D选项将[System]属性user.timezone设置为CET。然后我运行了以下代码:

/*
* import java.time.ZoneId;
* import java.time.ZonedDateTime;
* import java.util.Date;
*/
ZonedDateTime zdt = ZonedDateTime.of(1980, 4, 6, 0, 0, 0, 0, ZoneId.systemDefault());
System.out.println(Date.from(zdt.toInstant()));

我得到的结果是:

Sun Apr 06 00:00:00 CET 1980

这就是你想要的结果,对吗?

最新更新