夏时制更改期间的Java Calendar.roll和CST
我想知道Calendar.roll是否遵守其javadoc合同: 运行以下代码段夏时制更改期间的Java Calendar.roll和CST,java,datetime,timezone,dst,Java,Datetime,Timezone,Dst,我想知道Calendar.roll是否遵守其javadoc合同: 运行以下代码段 final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("CST")); cal.setTimeInMillis(1457928024812l); System.out.println(cal.getTime()); cal.roll(Calendar.HOUR_OF_DAY, true); System
final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("CST"));
cal.setTimeInMillis(1457928024812l);
System.out.println(cal.getTime());
cal.roll(Calendar.HOUR_OF_DAY, true);
System.out.println(cal.getTime());
yiels输出如下:
Sun Mar 13 23:00:24 CDT 2016
Sun Mar 13 23:00:24 CDT 2016
2016年3月13日是凌晨2点(从CST改为CDT)的夏令时。
滚动的javadoc声明滚动“添加了一个时间单位”,这里没有添加时间单位。
这是该方法的预期行为吗
编辑:
我报告这是一个错误。有关更多信息,请参阅相应OpenJDK票证的链接:这似乎是
roll
方法中的实际错误。好发现
几点注意:
- 我必须使用一个
来获得您显示的确切结果,因为只要调用SimpleDateFormat
就会得到一个getTime
对象,该对象在本地时区打印Date
- 最好使用
而不是America/Chicago
,但这不是原因CST
- 对于任何常规日期,第23小时应在同一天变为第0小时。如果您只想增加一小时,那么使用
而不是add
。看见roll
方法似乎工作正常add
- 在春季提前过渡的那天,一天只有23个小时。
方法似乎考虑到了这一点,即使它没有跨越实际的转换(在这个时区,当时钟跳到3:00时,转换发生在接近2:00时)。如您所示,它将小时设置为roll
,这比它应该设置的23
早一个小时0
- 在后退过渡的那天,一天有25个小时。同样,
方法尝试考虑到这一点,将小时设置为roll
,而不是1
,即使它没有穿过实际的转换(当时钟移回1:00时,在该时区接近2:00时再次发生)0
- 在
格式中使用a。避免使用既不独特也不标准的3-4字母代码大陆/地区
- 使用Java 8及更高版本中内置的框架。看见避免使用旧的日期时间类java.util.date/.Calendar
System.out.println ( "input: " + input + " | instant: " + instant + " | zoneId: " + zoneId + " | zdt: " + zdt + " | zdtHourLater: " + zdtHourLater );
System.out.println ( "zdtBeforeTwoAm: " + zdtBeforeTwoAm + " | zdtBeforeTwoAmPlus: " + zdtBeforeTwoAmPlus );
System.out.println ("zdtTwoAm: " + zdtTwoAm );
输入:1457928024812 |即时:2016-03-14T04:00:24.812Z |地区ID:美国/芝加哥| zdt:2016-03-13T23:00:24.812-05:00[美国/芝加哥]| zdtHourLater:2016-03-14T00:00:24.812-05:00[美国/芝加哥]
因此,java.time中没有这样的问题。加上一个小时,从13日晚上11点到14日午夜刚过,就像预期的那样在午夜移动
夏时制(DST)
DST处理得当
跨越DST转换
如预期的那样,从凌晨1:59增加一个小时,时钟上的两个小时将跳到凌晨3:59
ZonedDateTime zdtBeforeTwoAm = ZonedDateTime.of ( 2016, Month.MARCH.getValue ( ), 13, 1, 59, 0, 0, zoneId );
ZonedDateTime zdtBeforeTwoAmPlus = zdtBeforeTwoAm.plusHours ( 1 );
转储到控制台
System.out.println ( "input: " + input + " | instant: " + instant + " | zoneId: " + zoneId + " | zdt: " + zdt + " | zdtHourLater: " + zdtHourLater );
System.out.println ( "zdtBeforeTwoAm: " + zdtBeforeTwoAm + " | zdtBeforeTwoAmPlus: " + zdtBeforeTwoAmPlus );
System.out.println ("zdtTwoAm: " + zdtTwoAm );
Zdtbefortwoam:2016-03-13T01:59-06:00[美国/芝加哥]| Zdtbefortwoamplus:2016-03-13T03:59-05:00[美国/芝加哥]
要求凌晨2点
要求凌晨2点是无效的(没有这样的时间)。因此java.time会自动移动到一个有效的等效值,即凌晨3点
ZonedDateTime zdtTwoAm = ZonedDateTime.of ( 2016, Month.MARCH.getValue ( ), 13, 2, 0, 0, 0, zoneId );
转储到控制台
System.out.println ( "input: " + input + " | instant: " + instant + " | zoneId: " + zoneId + " | zdt: " + zdt + " | zdtHourLater: " + zdtHourLater );
System.out.println ( "zdtBeforeTwoAm: " + zdtBeforeTwoAm + " | zdtBeforeTwoAmPlus: " + zdtBeforeTwoAmPlus );
System.out.println ("zdtTwoAm: " + zdtTwoAm );
ZDTWOAM:2016-03-13T03:00-05:00[美国/芝加哥]
谢谢你,马特。关于
America/Chicago
事件,我用CST
简单地重现了这个问题。它发生在具有默认时区的服务器上,使用一个简单的Calendar.getInstance()
。