Java日期转换异常:Europe/Vienna时区1980-04-06无00:00时刻
日期转换小时偏移问题:00:00变01:00/23:00的原因解析
问题现象
两段日期转换代码均出现时间偏移:
- 使用
SimpleDateFormat的示例:
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", java.util.Locale.GERMAN); String dateInString = "06-04-1980"; Date date = formatter.parse(dateInString);
- 预期结果:
Sun Apr 06 00:00:00 CEST 1980 - 实际结果:
Sun Apr 06 01:00:00 CEST 1980
- 使用Java 8+日期API的示例:
Date date = Date.from(LocalDate.of(1980, 4, 6).atStartOfDay(ZoneId.systemDefault()).toInstant());
同样出现00:00偏移为01:00的问题。
根因分析
最初怀疑是Java 11升级到Java 17导致,但实际核心原因是时区从Europe/Berlin切换为Europe/Vienna:
- 1980年4月6日,奥地利(
Europe/Vienna时区)启用夏令时,切换时刻为00:00——该时区当天不存在00:00这个时间点,Java会自动将时间调整到下一个有效时刻(01:00)。 - 1893年3月31日之前的日期,
Europe/Vienna时区的本地“当日起始时间”对应UTC的前一天23:00,因此转换后Calendar.HOUR_OF_DAY显示为23;而Europe/Berlin时区无此偏移,始终显示为00。
可复现验证代码
以下代码可遍历并输出所有Europe/Vienna时区中存在时间偏移的日期:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); for (LocalDate date = LocalDate.of(1500, 4, 1); 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");
内容的提问来源于stack exchange,提问作者anm
相关产品推荐
相关产品推荐

