我在Java时区有一个棘手的问题(至少对我来说(。我将从一个按预期工作的示例开始:
TimeZone tz = TimeZone.getDefault();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
simpleDateFormat.setTimeZone(tz);
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(tz);
calendar.set(Calendar.HOUR_OF_DAY, 0);
System.out.println("0: " + simpleDateFormat.format(calendar.getTime()));
calendar.set(Calendar.HOUR_OF_DAY, 1);
System.out.println("1: " + simpleDateFormat.format(calendar.getTime()));
calendar.set(Calendar.HOUR_OF_DAY, 2);
System.out.println("2: " + simpleDateFormat.format(calendar.getTime()));
输出:
0 4/28/17 12:27 AM
1: 4/28/17 1:27 AM
2: 4/28/17 2:27 AM
现在有些魔术:
TimeZone tz = TimeZone.getTimeZone("Africa/Cairo");
SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
simpleDateFormat.setTimeZone(tz);
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(tz);
calendar.set(Calendar.HOUR_OF_DAY, 0);
System.out.println("0: " + simpleDateFormat.format(calendar.getTime()));
calendar.set(Calendar.HOUR_OF_DAY, 1);
System.out.println("1: " + simpleDateFormat.format(calendar.getTime()));
calendar.set(Calendar.HOUR_OF_DAY, 2);
System.out.println("2: " + simpleDateFormat.format(calendar.getTime()));
输出:
0: 4/28/17 1:31 AM
1: 4/28/17 1:31 AM
2: 4/28/17 2:31 AM
有人可以向我解释为什么hour_of_day for值0和1设定的小时在特定时区的相同值?
您的机器具有旧版本的时区数据,其中埃及本来会在2017年4月28日开始时将时钟推向午夜的当地时间。因此,上午12:31 AM不会已经存在了,Java跳过一个小时,而是 1 。
2016年7月5日,IANA时区数据2016F随着非洲/开罗时区的变化而发布,从那时起就不观察DST。(这是很晚的公告,因为下一个更改将是2016年7月8日。(
您可以在http://nodatime.github.io/tzvalidate/上看到每个IANA时区的所有iANA时区的所有过渡。(免责声明:我构建该页面。我启动了Tzvalidate项目,以验证不同的日期/时间库以相同的方式了解时区数据。(
1 我会争辩说,API应该强迫您在这种情况下陈述您想发生的事情,但是我不会进入 everything java.util.Calendar
是错误的这里...
几年前,该时区计划在2017年4月28日晚上进行DST过渡:在00:00 AM,时钟会升起一个小时。因此,由于过渡,午夜至凌晨1点之间的时间将是无效的。
但是,由于取消了过渡(埃及似乎已经取消并恢复了DST几次(。
(。总而言之,您可能正在使用具有过时的时区数据库的旧版本的Java。
你是对的。问题是在28日的时间过渡。今天一切正常:(