Calendar的奇怪行为

Cod*_*roc 6 java calendar date

我正面临一种奇怪的行为java.util.Calendar.

问题是当我Calendar#getTime()在中间添加一个方法调用时,我得到的结果是正确的,但是当我直接得到Dates一周而没有调用Calendar#getTime()它时,它指的是下周而不是当前周.

请考虑以下代码段:

public class GetDatesOfWeek {

    public static void main(String[] args) {

        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");

        Calendar cal = Calendar.getInstance();
        cal.set(1991, Calendar.DECEMBER, 11);

        //System.out.println(cal.getTime());//LINE NO : 14

        for(int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) {
            cal.set(Calendar.DAY_OF_WEEK, i);
            Date date = cal.getTime();
            System.out.println(sdf.format(date));
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

当我取消注释该行时,14我得到以下输出:

Wed Dec 11 07:38:06 IST 1991
08-12-1991
09-12-1991
10-12-1991
11-12-1991
12-12-1991
13-12-1991
14-12-1991
Run Code Online (Sandbox Code Playgroud)

但是当我评论该行并执行代码时,我得到了输出.

15-12-1991
16-12-1991
17-12-1991
18-12-1991
19-12-1991
20-12-1991
21-12-1991
Run Code Online (Sandbox Code Playgroud)

请注意,在两种情况下,月份和年份字段都是正确的,但开始日期从更改08-12-199115-12-1991对我来说08-12-1991正确的.

我的问题 :

  • 为什么我在上述两个案例中得到了一周的不同日期?
  • 为什么Java中提供了这种功能?

Jas*_*son 5

如果您在调试器中单步执行代码,您将看到cal对象的内部变量发生了有趣的事情.

日历对象分别存储它所代表的时间和调整字段.在执行第12行之后,使用当前时间和没有调整字段构造cal对象,并将其内部变量isTimeSet设置为true.这意味着存储的内部时间是正确的.

执行第13行清除isTimeSet为假,因为现在需要通过调整字段调整内部时间,然后才能再次准确.这不会立即发生,而是等待一个呼叫getTime()get(...),getTimeInMillis(),add(...)roll(...).

第14行(如果未注释)强制使用调整字段重新计算内部时间,并isTimeSet再次将该变量设置为true.

然后,第17行设置另一个调整字段,并isTimeSet再次取消设置该变量.

第18行根据第17行中设置的调整字段再次重新计算正确的时间.

解决方案:

将日期设置与星期几组合时会出现此问题.设置星期几时,将忽略日期设置,并将对象中的当前日期cal用作起点.你恰好在15日开始一周,因为今天的日期是1991年12月12日和15日,是最接近1991年12月12日的星期日.

注意:如果您在一周的时间内再次运行测试,您将得到不同的结果.

解决方案是在设置星期几调整之前调用getTimeInMillis()getTime()强制重新计算时间.

测试:

如果您不想再等一周再次测试,请尝试以下操作:

public class GetDatesOfWeek {

    public static void main(String[] args) {

        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");

        Calendar cal = Calendar.getInstance();
        cal.set(2015, Calendar.AUGUST, 1); // adjust this date and see what happens
        cal.getTime();

        cal.set(1991, Calendar.DECEMBER, 11);
        //System.out.println(cal.getTime());//LINE NO : 14

        for(int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) {
            cal.set(Calendar.DAY_OF_WEEK, i);
            Date date = cal.getTime();
            System.out.println(sdf.format(date));
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 这也记录在Java doc**中.日历字段值可以通过调用set方法来设置.在需要计算其时间值(距Epoch的毫秒数)或日历字段的值之前,不会解释日历中设置的任何字段值.调用get,getTimeInMillis,getTime,add和roll涉及这样的计算.** (3认同)