添加年份的Java日历问题
我试图增加一年的日期,但这是给不同的输入相同的日期。输入日期为2020年2月28日和2020年2月29日,输出日期与2021年2月28日相同。请帮我找出这里出了什么问题 更新: 我预计产量为2021年2月28日和2021年3月1日添加年份的Java日历问题,java,date,calendar,Java,Date,Calendar,我试图增加一年的日期,但这是给不同的输入相同的日期。输入日期为2020年2月28日和2020年2月29日,输出日期与2021年2月28日相同。请帮我找出这里出了什么问题 更新: 我预计产量为2021年2月28日和2021年3月1日 public static Date dateAdd(Date newDate, int field, int amount) { Calendar aCalendar = Calendar.getInstance(); aCalend
public static Date dateAdd(Date newDate, int field, int amount) {
Calendar aCalendar = Calendar.getInstance();
aCalendar.setTime(newDate);
aCalendar.add(field, amount);
return aCalendar.getTime();
}
public static void main(String[] args) throws Exception {
System.out.println(dateAdd(new SimpleDateFormat("dd/MM/yyyy").parse("28/02/2020"),Calendar.YEAR,1));
System.out.println(dateAdd(new SimpleDateFormat("dd/MM/yyyy").parse("29/02/2020"),Calendar.YEAR,1));
// Console output below
//Sun Feb 28 00:00:00 IST 2021
//Sun Feb 28 00:00:00 IST 2021
}
使用:
使用:
您可以先添加一年,然后再添加一天:
Date d = dateAdd(new SimpleDateFormat("dd/MM/yyyy").parse("28/02/2020"),Calendar.YEAR,1); // add a year
System.out.println(d);
d = dateAdd(d, Calendar.DATE, 1); // add a day
System.out.println(d);
您可以先添加一年,然后再添加一天:
Date d = dateAdd(new SimpleDateFormat("dd/MM/yyyy").parse("28/02/2020"),Calendar.YEAR,1); // add a year
System.out.println(d);
d = dateAdd(d, Calendar.DATE, 1); // add a day
System.out.println(d);
没有理由期待2021年3月1日的结果。事实上,有些人会质疑,为什么在2020年2月29日和2020年3月1日这两个日期上加上一年会产生与2021年3月1日相同的结果 相反,Java遵循一条清晰、一致且简单的规则:如果日期算术的结果(如添加月份或年份)导致无效日期,则返回的答案将是该结果月份的最后一天 例如,来自:
例如,2007-03-31加上一个月将导致无效日期2007-04-31。而不是返回无效结果,而是选择当月的最后一个有效日期2007-04-30。没有理由期望结果为2021年3月1日。事实上,有些人会质疑,为什么在2020年2月29日和2020年3月1日这两个日期上加上一年会产生与2021年3月1日相同的结果 相反,Java遵循一条清晰、一致且简单的规则:如果日期算术的结果(如添加月份或年份)导致无效日期,则返回的答案将是该结果月份的最后一天 例如,来自:
例如,2007-03-31加上一个月将导致无效日期2007-04-31。不是返回无效结果,而是选择月份的最后一个有效日期2007-04-30。没有问题,这取决于“添加一年”的解释,对于
java.util.Calendar#add
,它是:
添加(f,delta)将delta
添加到字段f
。这相当于调用set(f,get(f)+delta)
进行两次调整:
添加规则1。调用后字段f的值减去调用前字段f的值为增量,以字段f中发生的任何溢出为模。当一个字段值超出其范围时会发生溢出,结果是下一个较大的字段会递增或递减,并且字段值会调整回其范围
添加规则2。如果一个较小的字段预期是不变的,但由于字段f更改后其最小值或最大值的变化或其他约束(如时区偏移量更改)而不可能等于其先前的值,则其值将调整为尽可能接近其预期值。较小的字段表示较小的时间单位。小时是一个比月中的天小的字段。不会对预计不会保持不变的较小字段进行调整。日历系统确定哪些字段应保持不变
此外,与set()不同,add()强制立即重新计算日历的毫秒数和所有字段
例如:考虑GregorianCalendar最初设定为1999年8月31日。调用add(Calendar.MONTH,13)将日历设置为2000年9月30日。添加规则1将月份字段设置为9月,因为将13个月添加到8月会得到下一年的9月。由于公历月份中的日期不能是9月31日,因此添加规则2会将月份中的日期设置为30,这是最接近的可能值。虽然它是一个较小的字段,但“周中的天”不受规则2的调整,因为当月份在GregoriaCalendar中发生变化时,它会发生变化
资料来源:
这听起来与描述的行为一致,你期望什么&为什么?也许有更好/更专业的解决方案。没有错,这取决于“增加一年”的解释,对于
java.util.Calendar#add
,它是:
添加(f,delta)将delta
添加到字段f
。这相当于调用set(f,get(f)+delta)
进行两次调整:
添加规则1。调用后字段f的值减去调用前字段f的值为增量,以字段f中发生的任何溢出为模。当一个字段值超出其范围时会发生溢出,结果是下一个较大的字段会递增或递减,并且字段值会调整回其范围
添加规则2。如果一个较小的字段预期是不变的,但由于字段f更改后其最小值或最大值的变化或其他约束(如时区偏移量更改)而不可能等于其先前的值,则其值将调整为尽可能接近其预期值。较小的字段表示较小的时间单位。小时是一个比月中的天小的字段。不会对预计不会保持不变的较小字段进行调整。日历系统确定哪些字段应保持不变
此外,与set()不同,add()强制立即重新计算日历的毫秒数和所有字段
例如:考虑GregorianCalendar最初设定为1999年8月31日。调用add(Calendar.MONTH,13)将日历设置为2000年9月30日。添加规则1将月份字段设置为9月,因为将13个月添加到8月会得到下一年的9月。由于公历月份的日期不能是9月31日,因此添加规则2将月份的日期设置为30,即结束日期
aCalendar.roll(field, amount);