【问题标题】:A strange behavior from java.util.Calendar on February2 月 java.util.Calendar 的一个奇怪行为
【发布时间】:2013-01-14 08:22:24
【问题描述】:

我遇到了来自 java.util.Calendar 的奇怪行为:

import static org.junit.Assert.*;
import org.junit.Test;

import java.util.Calendar;

public class Tester1 {
    @Test
    public void test_monthOfDate() {
        assertEquals(1, monthOfDate(2013, 1, 30)); // OK
        assertEquals(1, monthOfDate(2013, 1, 31)); // OK

        // Start of February
        assertEquals(2, monthOfDate(2013, 2, 1));  // FAIL
        assertEquals(2, monthOfDate(2013, 2, 28)); // FAIL
        // to the end of it

        // and after that it is okay also
        assertEquals(3, monthOfDate(2013, 3, 1));  // OK
    }

    public int monthOfDate(int year, int month, int day) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month - 1);

        // just a simple get! but seems it is very important
        cal.get(Calendar.MONTH);
        //

        cal.set(Calendar.DAY_OF_MONTH, day);

        return cal.get(Calendar.MONTH) + 1;
    }
}

我想知道为什么会这样?

【问题讨论】:

    标签: java calendar


    【解决方案1】:

    问题是您从 2013 年 1 月 30 日开始的日历。

    然后您将年份设置为 2013 年 - 这不是问题。

    然后您将月份设置为 1(即二月)。你期望在这里发生什么?实际发生的是它会记住它需要将月份设置为 1,但 不会 重新计算实际时间值。根据documentation(强调我的),时间值在您致电get 时重新计算:

    set(f, value) 将日历字段 f 更改为 value。此外,它设置一个内部成员变量来指示日历字段 f 已更改。尽管日历字段 f 立即更改,但在下一次调用 get()、getTime()、getTimeInMillis()、add() 或 roll() 之前,不会重新计算日历的时间值(以毫秒为单位)。因此,多次调用 set() 不会触发多次不必要的计算。作为使用 set() 更改日历字段的结果,其他日历字段也可能更改,具体取决于日历字段、日历字段值和日历系统。 另外,get(f)在日历字段重新计算后,不一定会返回调用set方法设置的值。具体由具体的日历类决定。

    当您尝试将“1 月 30 日”更改为“2 月 30 日”并强制进行计算时,实际上会发生的是,您最终会在 3 月 2 日出现在我的盒子上 - 但您的可能会有所不同实施。

    最好的修复方法是:

    【讨论】:

      猜你喜欢
      • 2013-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-03
      • 2011-03-05
      • 2011-10-01
      • 1970-01-01
      相关资源
      最近更新 更多