为什么 moment.js year diff year 不完全匹配 1?
Why doesn't moment.js year diff year not match exactly 1?
我已经执行了这些简单的 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
有人知道发生了什么事吗?
首先,请注意 new Date(year,1,1)
指的是 二月 1 日,而不是一月。 Javascript,遵循 UNIX time_t 约定,月份数字从 0 开始,其想法是您将使用月份编号索引到月份名称数组中,而不是直接使用它。因此,要构造一个引用 1 月 1 日的 Date 对象,您应该调用 new Date(year,0,1)
.
其次,取整数天数的差值并转换为年数永远不会得到整数。您应该首先要求 Moment 给出年份的差异:
> moment(new Date(2013,0,1)).diff(moment(new Date(2012,0,1)),'year');
1
如果您希望结果包含一年的小数部分而不是被截断为整数,请向 diff
添加一个真实的第三个参数。这里我们从 7 月算到 1 月:
> moment(new Date(2013,0,1)).diff(moment(new Date(2012,6,1)),'year',true)
0.5
您的方法不可行,因为日历年不是固定的秒数;它要么是 365 天,即 31,536,000 秒,要么是 366 天,即 31,622,400 秒。由于闰年通常每四年发生一次,平均 日历年为 365.25 天,或 31,557,600 秒;事实上,一光年被定义为光在该精确秒数内传播的距离。
但在现代公历中,闰世纪规则意味着一年的平均长度(需要 400 多年才能获得一个完整的周期)确实要短一些:365.2425 天或 31,556,952秒。这是 Moment 使用的值,但它仅作为平均值使用;任何不是 400 年的精确倍数的周年纪念日永远不会给你一个整数结果。相反,正如您发现的那样,平年将计算为 31,536,000 / 31,556,952 = 0.99933605755085028689843... 一年,而闰年将计算为 31,622,400 / 31,556,952 = 1.002073964555779379453...3768[年]
在你的最后一个例子中你得到了共同的年份值,因为你要求的是从 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');
我已经执行了这些简单的 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
有人知道发生了什么事吗?
首先,请注意 new Date(year,1,1)
指的是 二月 1 日,而不是一月。 Javascript,遵循 UNIX time_t 约定,月份数字从 0 开始,其想法是您将使用月份编号索引到月份名称数组中,而不是直接使用它。因此,要构造一个引用 1 月 1 日的 Date 对象,您应该调用 new Date(year,0,1)
.
其次,取整数天数的差值并转换为年数永远不会得到整数。您应该首先要求 Moment 给出年份的差异:
> moment(new Date(2013,0,1)).diff(moment(new Date(2012,0,1)),'year');
1
如果您希望结果包含一年的小数部分而不是被截断为整数,请向 diff
添加一个真实的第三个参数。这里我们从 7 月算到 1 月:
> moment(new Date(2013,0,1)).diff(moment(new Date(2012,6,1)),'year',true)
0.5
您的方法不可行,因为日历年不是固定的秒数;它要么是 365 天,即 31,536,000 秒,要么是 366 天,即 31,622,400 秒。由于闰年通常每四年发生一次,平均 日历年为 365.25 天,或 31,557,600 秒;事实上,一光年被定义为光在该精确秒数内传播的距离。
但在现代公历中,闰世纪规则意味着一年的平均长度(需要 400 多年才能获得一个完整的周期)确实要短一些:365.2425 天或 31,556,952秒。这是 Moment 使用的值,但它仅作为平均值使用;任何不是 400 年的精确倍数的周年纪念日永远不会给你一个整数结果。相反,正如您发现的那样,平年将计算为 31,536,000 / 31,556,952 = 0.99933605755085028689843... 一年,而闰年将计算为 31,622,400 / 31,556,952 = 1.002073964555779379453...3768[年]
在你的最后一个例子中你得到了共同的年份值,因为你要求的是从 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');