Java Calendar.add给出不一致的结果

时间:2012-05-04 12:14:39

标签: java

我有以下代码

    Calendar calendar = Calendar.getInstance();

    calendar.set(2011, 7, 29);      //case 1    
   // calendar.set(2011, 7, 30);      //case 2
   // calendar.set(2011, 7, 31);    //case 3

    System.out.println("===After seting the date== "+calendar.getTime());

    System.out.println("=================================================================");

    calendar.add(Calendar.MONTH, 6);


    System.out.println("===result after adding 6 months==  "+calendar.getTime());

对于案例2和案例3,我也得到了相同的结果。它应该溢出到下个月并显示新的日期。但它没有发生。

2 个答案:

答案 0 :(得分:4)

目前尚不清楚你是否正在使用“应该”来表示“这就是我想要它做的事情”,或者意味着“这就是我相信它所记录的事情”。 documentation实际上支持给出的行为:

  

add(f,delta)将delta添加到字段f。这相当于通过两次调整来调用set(f,get(f)+ delta):

     

添加规则1 。调用之后的字段f的值减去调用之前的字段f的值是delta,以模拟字段f中发生的任何溢出为模。当字段值超出其范围时发生溢出,结果,下一个更大的字段递增或递减,字段值调整回其范围。

     

添加规则2 。如果预期较小的字段是不变的,但由于字段f改变或其他约束(例如时区偏移改变)后其最小值或最大值发生变化,它不可能等于其先前值,则其值被调整为尽可能接近其预期值。较小的字段表示较小的时间单位。 HOUR是一个比DAY_OF_MONTH小的字段。不对不希望不变的较小字段进行调整。日历系统确定预期哪些字段不变。

     

此外,与set()不同,add()强制立即重新计算日历的毫秒数和所有字段。

     

示例:考虑最初设置为1999年8月31日的GregorianCalendar。调用add(Calendar.MONTH,13)将日历设置为2000年9月30日。添加规则1将MONTH字段设置为9月,因为将8月添加到8月给了明年九月。由于在GregorianCalendar中DAY_OF_MONTH在9月不能是31,因此添加规则2将DAY_OF_MONTH设置为30,即最接近的可能值。虽然它是一个较小的字段,但DAY_OF_WEEK不会被规则2调整,因为当GregorianCalendar中月份发生变化时,它会发生变化。

示例的第二部分正是您所面临的情况:DAY_OF_MONTH预计是不变的,但必须更改才能保持在正确的月份内,因此将其调整为最接近的可能值(29 in你的情况)。

所以看起来行为 对我来说是一致的 - 你认为它与你的不一致有哪些?

答案 1 :(得分:0)

我发现以下是使用格里高利日历实现的最简单的方法。 将月中的日期设置为下个月的最后一天,以防止它成为下个月的第一天。

尝试以下操作。

cal.set(Calendar.DAY_OF_MONTH,Math.min(Calendar.DAY_OF_MONTH,cal.getActualMaximum(Calendar.DAY_OF_MONTH)));