0

我面临着非常奇怪的问题。这是生成一个新 Date 对象的代码:

Date result = DateUtils.setYears(new Date(), year);
result = DateUtils.setMonths(result, month);
return DateUtils.setDays(result, day);

如果我从 1 到 11 传递任何月份的值 - 一切正常,1 表示 1 月,2 - 2 月 ... 11 - 11 月。但是对于 12 它总是失败,但有java.lang.IllegalArgumentException: MONTH异常..

当我尝试传递基于 0 的值时,第一个 0 表示上一年的 12 月。有什么想法吗?

先感谢您

4

2 回答 2

2

该方法setMonths看起来像

 public static Date setMonths(Date date, int amount) {
        return set(date, Calendar.MONTH, amount);
    }

正如您所注意到的,它在内部使用 Java 中的 Calendar.MONTH。班级月份Calendar从 0 到 12 开始(12 值表示 UNDECIMBER,即一年中的第 13 个月,虽然 GregorianCalendar 不使用此值,但农历使用)。因此,当您传递时,0 表示一月,1 表示二月,... 11 表示十二月。对于无效的月份值日历类抛出

java.lang.IllegalArgumentException
于 2015-01-20T11:55:32.623 回答
0

让我们追踪它。

DateUtils 中的setMonths方法定义如下:

public static Date setMonths(Date date, int amount) {
   return set(date, Calendar.MONTH, amount);
}

我们来看看set方法。此方法抛出相同的异常类,但出于不同的原因。

private static Date set(Date date, int calendarField, int amount) {
    if (date == null) {
        throw new IllegalArgumentException("The date must not be null");
    }
    // getInstance() returns a new object, so this method is thread safe.
    Calendar c = Calendar.getInstance(); //returns an "empty" Calendar instance using default TimeZone and Local. Does not throw any exception
    c.setLenient(false); // Just set the leniency value of the Calendar.
    c.setTime(date); // set the time of the Calendar to the reference time by converting the date input into milliseconds
    c.set(calendarField, amount); // this one looks interesting, but not quite
    return c.getTime(); //returns the Date Object, possible source of the thrown Exception
}

getTimeCalendar.java 中的方法如下所示:

 public final Date getTime() {
     return new Date(getTimeInMillis());
 }

Calendar.java 中的方法getTimeInMillis定义如下:

public long getTimeInMillis() {
   if (!isTimeSet) {
       updateTime();
   }
   return time;
}

该方法中唯一看起来有趣的语句是updateTime它的定义如下:

 private void updateTime() {
     computeTime();
     // The areFieldsSet and areAllFieldsSet values are no longer
     // controlled here (as of 1.5).
     isTimeSet = true;
}

Calendar.java 中的computeTime方法是一个抽象方法,在这种情况下具体实现在 GregorianCalendar.java 中。因为整个方法很长,所以我只会在方法中显示可以抛出异常的语句。

    protected void computeTime() {
        // In non-lenient mode, perform brief checking of calendar
        // fields which have been set externally. Through this
        // checking, the field values are stored in originalFields[]
        // to see if any of them are normalized later.
        if (!isLenient()) {
            if (originalFields == null) {
                originalFields = new int[FIELD_COUNT];
            }
            for (int field = 0; field < FIELD_COUNT; field++) {
                int value = internalGet(field);
                if (isExternallySet(field)) {
                    // Quick validation for any out of range values
                    **This is the part of the code that has thrown that Exception**
                    if (value < getMinimum(field) || value > getMaximum(field)) {
                       throw new IllegalArgumentException(getFieldName(field));
                    }
            }
            originalFields[field] = value;
        }
    //After this part, code that computes the time in milliseconds follows
   .............................
   .............................
    }

如您所见,为特定字段提供的值与该字段的预定义最小值和最大值进行比较。对于 MONTH 字段,最小值为 0(一月),最大值为 11(十二月)。您可以从这里验证这些值。

现在关于你的另一个问题,你提供的信息仅限于我们提供具体的答案。通过 Calendar API 的实现,如果宽松模式设置为false,则月份的值 0 应对应于一月和 11 到十二月。0 月值对应于 12 月的唯一方法是,当您将宽大模式设置为true并且您有一个“环绕(翻转)”到 12 月的天值时,例如月 = 0 但天 = 369。

正如上面的评论之一中提到的,这里最好的猜测可能是您正在month以某种方式修改某处的值。

于 2015-01-20T13:22:11.387 回答