闰年计算与 JavaScript Date 不匹配

3
尝试找出JavaScript中闰年计算和日期对象之间的关联(仅仅是因为我想知道为什么)。我不是要使用Date()对象来计算闰年 - 这不是重点。 执行以下代码:
new Date(43 * 365 * 24 * 60 * 60 * 1000).toUTCString()

生成如下结果:

"Fri, 21 Dec 2012 00:00:00 GMT"

这个日期偏差了11天(与闰年有关)。因此,我试图通过数学计算来解决:

1970 * 0.2425 = 477.72499999999997
2013 * 0.2425 = 488.1525
Difference: 10.427500000000009

我注意到时间相差43年,43 * 0.2425等于10.4275,但是即使四舍五入只会得到10,这意义还是正确的。为什么JavaScript Date()对象偏差11天?

还有一件事 - 我也试过这个:

function test(y) {
    return new Date((y * 365 + Math.round((y+1) * 0.2425)) * 24 * 60 * 60 * 1000).toUTCString();
}

这个方法看起来很有效,直到我遇到了2000年(test(30)),此时我得到的是"Sun, 02 Jan 2000 00:00:00 GMT"。我猜这是因为400年规则 - 但我认为这应该使用".2425"进行数学处理。我错过了什么,但不确定是什么。如果有帮助,请告诉我,谢谢。

更新:只是补充一下,我还在寻找一种数学计算(没有任何循环),可以告诉我传递给Date()对象所需的毫秒数(不使用Date对象本身!)。难道不能使用数学来计算给定年份的闰年,然后计算Date()所需的毫秒数吗?


2
这与日期对象或JavaScript一般没有任何关系,除了它是你用于计算的媒介。 - RobG
2
日期对象误差为11天,因为从1970年至今已经有11个闰年。 - JJJ
我知道有11天 - 但我不清楚。我想知道为什么我的数学是错误的。整个4-100-400规则的重点在于每年多出的0.2425天,理论上应该能够使用这个分数计算出跨越多年的4-100-400规则的结果。 - James Wilkins
1个回答

4
你的数学计算有误,因为你是从一个非闰年开始的。例如,如果只有一年,并且你这样做了(而且不是闰年),你将得到0.2425而不是正确答案0。按照你的方法进行计算,可以得出以下结果: 2010 * 0.2425 = 487.425 2011 * 0.2425 = 487.6675 计算差值:0.2425 闰年的正确天数:0 由于两者都不是闰年,因此不应分配任何额外的天数。另一个例子: 2012 * 0.2425 = 487.91 2013 * 0.2425 = 488.1525 计算差值:0.2425 闰年的正确天数:1 为了证明JavaScript的日期对象实际上是正确的,让我们看看从1970年开始的闰年:
1972
1976
1980
1984
1988
1992
1996
2000
2004
2008
2012

在 JavaScript 中,Date() 构造函数的实现实际上检查以下内容:


...

总共11天。
year % 4 === 0 && year % 100 !== 0 || year % 400 === 0

编辑:您可以使用类似以下的内容,看看是否符合您的需求:

function test(y)
{   var floor = Math.floor;
    // y -= 1970; // if you want it to be full years instead of years since 1970
    var value = (365 * y + floor((y + 1) / 4) + floor((y + 369) / 400) - floor((y + 69) / 100)) * 86400000;
    return new Date(value).toUTCString();
}

这种方法每四年增加一天,然后每100年减少一天,然后每400年再增加一天(以抵消每100年的减少)。

请注意,在一年开始时不会添加一天,例如1972年对于闰年没有增加任何天数,因为它是一年的开头,还没有到达二月底。


1
OP可以添加0.5的偏移量,以考虑自1968年以来累积的半天时间。但是,除非考虑到世纪规则,否则计算将在2100年失败。 - RobG
抱歉,我在帖子中没有表述清楚。我主要是在寻找一个数学计算公式(与循环无关),可以告诉我传递给 Date() 对象所需的毫秒数,以便于给定的年份。这是否可能而又不需要创建一个日期对象呢?我有我的理由。;) - James Wilkins
你很接近了。你忘记要减去1970年的时期年份了。 ;) 在“var floor...”后面加上“y = y - 1970”就好了。 - James Wilkins
哦,我明白了,你使用了我的示例,将年份之间的差作为参数,而不是年份本身;抱歉。 ;) - James Wilkins
1
啊,好的,我明白了。因为这个函数接受的是1970年和给定日期之间的差值,所以它会相应地进行调整,明白了,谢谢。 :) - James Wilkins
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,