JavaScript - 添加年份
影响类别 2
有缺陷的代码
var dt = new Date();
dt.setFullYear(dt.getFullYear() + 1);
这段代码在dt
变成2月29日(例如在2020-02-29
)之前可以正常工作。然后它将尝试将年份设置为2021年。由于2021-02-29
不存在,Date
对象将向前滚动到下一个有效日期,即2020-03-01
。
在某些情况下,这可能是预期的行为。在其他情况下,相差一天可能没有什么影响(例如过期日期)。
然而,在许多情况下,提前一年的意图是保持大致相同的月份和日期位置。换句话说,如果您从二月底开始(2020-02-29
),并提前一年,您可能希望结果也是在二月底(2021-02-28
),而不是三月初(2021-03-01
)。
更正后的代码
要在JavaScript中添加年份并保留2月底的行为,请使用以下函数。
function addYears(dt, n) {
var m = dt.getMonth();
dt.setFullYear(dt.getFullYear() + n);
if (dt.getMonth() !== m)
dt.setDate(dt.getDate() - 1);
}
addYears(dt, 1);
常见变体 - 不可变形式
有时候我们会有一些不会改变原始对象的代码,例如下面这段:
有缺陷的代码
var dt = new Date();
var result = new Date(dt.getFullYear() + 1, dt.getMonth(), dt.getDate());
保持二月末行为不变的不可变形式如下:
更正后的代码
function addYears(dt, n) {
var result = new Date(dt);
result.setFullYear(result.getFullYear() + n);
if (result.getMonth() !== dt.getMonth())
result.setDate(result.getDate() - 1);
return result;
}
var result = addYears(dt, 1);
库
JavaScript有许多日期/时间库,例如Luxon, Date-Fns, Moment和js-Joda。所有这些库已经为它们的add-years函数使用了二月底的行为。除非您想要三月初的行为,否则不需要进行任何额外的调整。
Z
创建它。由于toISOString
也输出UTC,因此被掩盖了。如果您省略了Z
,或者使用format
进行输出(或两者都使用),则行为将更清晰。(它实际上并没有向前跳跃。) - Matt Johnson-Pint