Javascript 为什么moment.js year diff year不完全匹配1?

Javascript 为什么moment.js year diff year不完全匹配1?,javascript,datetime,momentjs,Javascript,Datetime,Momentjs,我已经执行了这些简单的JS代码行 moment.duration(moment(new Date(2013,1,1)).diff(moment(new Date(2012,1,1)))).asYears() moment.duration(moment(new Date(2012,1,1)).diff(moment(new Date(2011,1,1)))).asYears() moment.duration(moment(new Date(2011,1,1)).diff(moment(new

我已经执行了这些简单的JS代码行

moment.duration(moment(new Date(2013,1,1)).diff(moment(new Date(2012,1,1)))).asYears()
moment.duration(moment(new Date(2012,1,1)).diff(moment(new Date(2011,1,1)))).asYears()
moment.duration(moment(new Date(2011,1,1)).diff(moment(new Date(2010,1,1)))).asYears()
moment.duration(moment(new Date(2010,1,1)).diff(moment(new Date(2009,1,1)))).asYears()
输出

1.0020739645577939
0.9993360575508053
0.9993360575508053
0.9993360575508053
肯定是出了什么事

或者这种反常现象与闰年有关?2012年是闰年

所以我尝试了下一个闰年2016

moment.duration(moment(new Date(2016,1,1)).diff(moment(new Date(2015,1,1)))).asYears()
它的输出和以前的非闰年相同,所以可能与之无关

0.9993360575508053
有人知道发生了什么吗?

首先,请注意,新年1,1指的是2月1日,而不是1月。Javascript遵循UNIX time_t约定,以0开始计算月数,其思想是使用月数索引到月名数组中,而不是直接使用它。因此,要构造一个引用一月一日的日期对象,您应该调用new Dateyear,0,1

第二,取一个天数的差,再换算成年,永远不会得到一个整数。首先,你应该让Moment给出以年为单位的差异:

> moment(new Date(2013,0,1)).diff(moment(new Date(2012,0,1)),'year');
1
如果您希望结果包括一年的分数,而不是被截断为整数,请在diff中添加truthy第三个参数。这里我们从7月到1月进行计算:

> moment(new Date(2013,0,1)).diff(moment(new Date(2012,6,1)),'year',true)
0.5
您的方法不起作用,因为日历年不是固定的秒数;要么是365天,即31536000秒,要么是366天,即31622400秒。由于闰年通常每四年发生一次,因此平均日历年为365.25天,即31557600秒;事实上,一光年的定义是光以精确的秒数传播的距离

但在现代公历中,闰世纪规则意味着一年的平均长度(你需要400多年才能得到一个完整的周期)实际上要短一点:365.2425天或31556952秒。这是矩使用的值,但它仅作为平均值起作用;任何不是400年的精确倍数的周年纪念都不会给你一个整数结果。相反,正如您所发现的,一个普通年份将计为31536000/31556952=0.99933605755085028689843。。。而闰年将计算为31622400/31556952=1.0020739645779379453376886。。。年

在上一个示例中,您得到了普通年份值,因为您要求的是2015年至2016年的年份长度,即2015年的长度。如果从2016年到2017年进行计算,则得到预期闰年值:

> moment.duration(moment(new Date(2017,0,1)).diff(moment(new Date(2016,0,1)))).asYears()
1.0020739645577939
更具体地说,只要间隔包括2月29日,你就会得到闰年长度。因此,如果你测量连续几年中同一日期之间的差值,如果你从闰年前一年的3月1日到闰年本身的2月28日之间的任何日期开始,你将得到366天。如果你从2月29日开始计算,那么下一年当然没有2月29日;如果计算到2月28日,你将获得365天;如果计算到3月1日,你将获得366天。从闰年的3月1日开始,同一日期的重现时间回到365天:

> moment.duration(moment(new Date(2016,1,28)).diff(moment(new Date(2015,1,28)))).asYears()
0.9993360575508053
> moment.duration(moment(new Date(2016,2,1)).diff(moment(new Date(2015,2,1)))).asYears()
1.0020739645577939
> moment.duration(moment(new Date(2017,1,28)).diff(moment(new Date(2016,1,28)))).asYears()
1.0020739645577939
> moment.duration(moment(new Date(2017,2,1)).diff(moment(new Date(2016,2,1)))).asYears()
0.9993360575508053
首先,请注意,new Dateyear,1,1指的是2月1日,而不是1月。Javascript遵循UNIX time_t约定,以0开始计算月数,其思想是使用月数索引到月名数组中,而不是直接使用它。因此,要构造一个引用一月一日的日期对象,您应该调用new Dateyear,0,1

第二,取一个天数的差,再换算成年,永远不会得到一个整数。首先,你应该让Moment给出以年为单位的差异:

> moment(new Date(2013,0,1)).diff(moment(new Date(2012,0,1)),'year');
1
如果您希望结果包括一年的分数,而不是被截断为整数,请在diff中添加truthy第三个参数。这里我们从7月到1月进行计算:

> moment(new Date(2013,0,1)).diff(moment(new Date(2012,6,1)),'year',true)
0.5
您的方法不起作用,因为日历年不是固定的秒数;要么是365天,即31536000秒,要么是366天,即31622400秒。由于闰年通常每四年发生一次,因此平均日历年为365.25天,即31557600秒;事实上,一光年的定义是光以精确的秒数传播的距离

但在现代公历中,闰世纪规则意味着一年的平均长度(你需要400多年才能得到一个完整的周期)实际上要短一点:365.2425天或31556952秒。这是矩使用的值,但它仅作为平均值起作用;任何不是400年的精确倍数的周年纪念都不会给你一个整数结果。相反,正如您所发现的,一个普通年份将计为31536000/31556952=0.99933605755085028689843。。。而闰年将计算为31622400/31556952=1.0020739645779379453376886。。。年

在上一个示例中,您得到了普通年份值,因为您要求的是从2015年到2016年的年份长度,即长度 2015年第十季度。如果从2016年到2017年进行计算,则得到预期闰年值:

> moment.duration(moment(new Date(2017,0,1)).diff(moment(new Date(2016,0,1)))).asYears()
1.0020739645577939
更具体地说,只要间隔包括2月29日,你就会得到闰年长度。因此,如果你测量连续几年中同一日期之间的差值,如果你从闰年前一年的3月1日到闰年本身的2月28日之间的任何日期开始,你将得到366天。如果你从2月29日开始计算,那么下一年当然没有2月29日;如果计算到2月28日,你将获得365天;如果计算到3月1日,你将获得366天。从闰年的3月1日开始,同一日期的重现时间回到365天:

> moment.duration(moment(new Date(2016,1,28)).diff(moment(new Date(2015,1,28)))).asYears()
0.9993360575508053
> moment.duration(moment(new Date(2016,2,1)).diff(moment(new Date(2015,2,1)))).asYears()
1.0020739645577939
> moment.duration(moment(new Date(2017,1,28)).diff(moment(new Date(2016,1,28)))).asYears()
1.0020739645577939
> moment.duration(moment(new Date(2017,2,1)).diff(moment(new Date(2016,2,1)))).asYears()
0.9993360575508053
尝试使用:

moment(new Date(2013,1,1)).diff(moment(new Date(2012,1,1)),'year');
尝试使用:

moment(new Date(2013,1,1)).diff(moment(new Date(2012,1,1)),'year');

回答得很好。这很有效。然而,我期待的是像momentnew Date2013,1,1.diffmomentnew Date2012,6,1,'year';返回0.5,但它返回0。我算出了。“我只需要在‘year’之后加上一个true作为额外参数,谢谢你,@Daniel;我已经把它加入到答案中了。很好的答案。这很有效。然而,我期待的是像momentnew Date2013,1,1.diffmomentnew Date2012,6,1,'year';返回0.5,但它返回0。我算出了。“我只需要在‘year’之后加上一个true作为额外参数,谢谢你,@Daniel;我已经把它纳入了答案中。