2 月 java.util.Calendar 的一个奇怪行为

A strange behavior from java.util.Calendar on February(2 月 java.util.Calendar 的一个奇怪行为)
本文介绍了2 月 java.util.Calendar 的一个奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

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

I faced with a strange behavior from 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;
    }
}

我想知道为什么会这样?

I want to know why exactly this is happening?

推荐答案

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

The problem is that you're starting off with a calendar on January 30th 2013.

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

You're then setting the year to 2013 - that's not a problem.

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

You're then setting the month to 1 (i.e. February). What do you expect to happen here? What actually happens is that it will remember that it needs to set the month to 1, but not recompute the actual time value. The time value will be recomputed on your call to get though, as per the documentation (emphsis mine):

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

set(f, value) changes calendar field f to value. In addition, it sets an internal member variable to indicate that calendar field f has been changed. Although calendar field f is changed immediately, the calendar's time value in milliseconds is not recomputed until the next call to get(), getTime(), getTimeInMillis(), add(), or roll() is made. Thus, multiple calls to set() do not trigger multiple, unnecessary computations. As a result of changing a calendar field using set(), other calendar fields may also change, depending on the calendar field, the calendar field value, and the calendar system. In addition, get(f) will not necessarily return value set by the call to the set method after the calendar fields have been recomputed. The specifics are determined by the concrete calendar class.

当您尝试将1 月 30 日"更改为2 月 30 日"并强制进行计算时,实际上会发生的是您在 3 月 2 日结束了我的盒子 - 但您的可能会有所不同实施.

When you try to change "January 30th" to "February 30th" and force a computation, what actually happens is that you end up on March 2nd on my box - but it may differ on your implementation.

最好的修复方法是:

  • 使用 Calendar.set(year, month, date) 来避免这个排序问题
  • 首先使用 Joda Time 作为更合理的 API.
  • Use Calendar.set(year, month, date) instead to avoid this ordering issue
  • Use Joda Time as a more sensible API in the first place.

这篇关于2 月 java.util.Calendar 的一个奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

Month is not printed from a date - Java DateFormat(月份不是从日期打印的 - Java DateFormat)
java get week of year for given a date(java获取给定日期的一年中的一周)
Get the number of days, weeks, and months, since Epoch in Java(获取自 Java 中的 Epoch 以来的天数、周数和月数)
Is there a good way to get the date of the coming Wednesday?(有什么好方法可以得到即将到来的星期三的日期吗?)
Calendar view for Android GingerBread and before (APIlt;11)(Android GingerBread 及之前的日历视图 (API11))
How to save and retrieve Date in SharedPreferences(如何在 SharedPreferences 中保存和检索日期)