apache.commons.lang3.DateUtils.setMonths 与 12 月
apache.commons.lang3.DateUtils.setMonths with December
我遇到了一个很奇怪的问题..
这是生成新日期对象的代码:
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 月..
有什么想法吗?
提前致谢
方法 setMonths
看起来像
public static Date setMonths(Date date, int amount) {
return set(date, Calendar.MONTH, amount);
}
正如您所注意到的,它在内部使用了 java 中的 Calendar.MONTH。 Calendar
class 中的月份从 0 开始到 12(12 值表示 UNDECIMBER,即一年中的第 13 个月 虽然 GregorianCalendar 不使用此值,但农历使用)。所以当你传递 0 时,它表示一月,1 表示二月,......而 11 表示十二月。对于无效的月份值日历 class 抛出
java.lang.IllegalArgumentException
我们来追踪一下。
DateUtils中的setMonths
方法定义如下:
public static Date setMonths(Date date, int amount) {
return set(date, Calendar.MONTH, amount);
}
我们来看看 set
方法。此方法抛出相同的异常 class 但出于不同的原因。
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
}
Calendar.java 中的 getTime
方法如下所示:
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(十二月)。您可以从 here.
验证这些值
那么关于你的另一个问题,你提供的信息有限,我们无法给出具体的回答。通过日历 API 的实现,如果宽大模式设置为 false
,则月份的值 0 应对应于 1 月,11 对应于 12 月。 0 个月值对应于 12 月的唯一方法是当您将宽大模式设置为 true
并且您有一个天值 "wraps around (roll over)" 到 12 月,例如月 = 0 但日 = 369。
如上面的评论之一所述,这里的最佳猜测可能是您正在某处以某种方式修改 month
的值。
我遇到了一个很奇怪的问题.. 这是生成新日期对象的代码:
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 月.. 有什么想法吗?
提前致谢
方法 setMonths
看起来像
public static Date setMonths(Date date, int amount) {
return set(date, Calendar.MONTH, amount);
}
正如您所注意到的,它在内部使用了 java 中的 Calendar.MONTH。 Calendar
class 中的月份从 0 开始到 12(12 值表示 UNDECIMBER,即一年中的第 13 个月 虽然 GregorianCalendar 不使用此值,但农历使用)。所以当你传递 0 时,它表示一月,1 表示二月,......而 11 表示十二月。对于无效的月份值日历 class 抛出
java.lang.IllegalArgumentException
我们来追踪一下。
DateUtils中的setMonths
方法定义如下:
public static Date setMonths(Date date, int amount) {
return set(date, Calendar.MONTH, amount);
}
我们来看看 set
方法。此方法抛出相同的异常 class 但出于不同的原因。
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
}
Calendar.java 中的 getTime
方法如下所示:
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(十二月)。您可以从 here.
验证这些值那么关于你的另一个问题,你提供的信息有限,我们无法给出具体的回答。通过日历 API 的实现,如果宽大模式设置为 false
,则月份的值 0 应对应于 1 月,11 对应于 12 月。 0 个月值对应于 12 月的唯一方法是当您将宽大模式设置为 true
并且您有一个天值 "wraps around (roll over)" 到 12 月,例如月 = 0 但日 = 369。
如上面的评论之一所述,这里的最佳猜测可能是您正在某处以某种方式修改 month
的值。