我想知道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.out.println(cal.getTime());
产生以下输出:
Sun Mar 13 23:00:24 CDT 2016
Sun Mar 13 23:00:24 CDT 2016
2016年3月13日是凌晨2点(从CST到CDT)的夏令时更改.
Roll的Javadoc指出,Roll会“添加一个单一的时间单位”,此处未添加任何时间单位.
这是此方法的预期行为吗?
编辑:
我将其报告为错误.有关更多信息,这是相应的OpenJDK票证的链接:https://bugs.openjdk.java.net/browse/JDK-8152077
最佳答案
这似乎是roll方法中的实际错误.好发现!
一些注意事项:
>我必须使用SimpleDateFormat来获得您显示的确切结果,因为仅调用getTime会得到一个在本地时区打印的Date对象.
>使用America / Chicago而不是CST会更好,但这不是造成这种情况的原因.
>对于任何常规日期,滚动第23小时的日期应在同一天的小时0.如果您只想增加一个小时,请使用add代替roll.请参阅add vs roll.add方法似乎正常工作.
>在春季过渡的那天,一天只有23个小时.滚动方法似乎已考虑到这一点,即使它没有跨越实际的过渡(在该时区中接近2:00发生,此时时钟跳到3:00).如您所显示,它将小时设置为23,这比它应设置的0早了一个小时.
>在回退过渡的那天,一天有25个小时.同样,roll方法会尝试将这一点考虑在内,将小时设置为1而不是0,即使它没有越过实际的过渡时间(在该时区中,当时钟重新移至1时,它仍会在接近2:00时发生) :00).
我进行了快速搜索,以查看是否已经在任何地方报告了该报告,但没有发现太多.也许您应该report it.
我还要补充一点,您可能应该考虑对Java 7或更早版本使用Joda Time,对于Java 8或更早版本使用java.time
.