javascript 查找闰年
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8175521/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
javascript to find leap year
提问by Juan Almonte
How can I get the code below to work when I have a month of february? Currently it is getting to the day and then stopping before getting to the if to determine whether it is a leap year.
当我有一个月的二月时,我怎样才能让下面的代码工作?目前它正在进入这一天,然后在进入 if 之前停止以确定它是否是闰年。
if (month == 2) {
if (day == 29) {
if (year % 4 != 0 || year % 100 == 0 && year % 400 != 0) {
field.focus();
field.value = month +'/' + '';
}
}
else if (day > 28) {
field.focus();
field.value = month +'/' + '';
}
}
回答by georg
It's safer to use Date objectsfor datetime stuff, e.g.
将Date 对象用于日期时间内容更安全,例如
isLeap = new Date(year, 1, 29).getMonth() == 1
Since people keep asking about how exactly this works, it has to do with how JS calculates the date value from year-month-day (details here). Basically, it first calculates the first of the month and then adds N -1 days to it. So when we're asking for the 29th Feb on a non-leap year, the result will be the 1st Feb + 28 days = 1st March:
由于人们一直在问这到底是如何工作的,这与 JS 如何从年-月-日计算日期值有关(详情请点击此处)。基本上,它首先计算当月的第一天,然后添加 N -1 天。因此,当我们要求非闰年的 2 月 29 日时,结果将是 2 月 1 日 + 28 天 = 3 月 1 日:
> new Date(2015, 1, 29)
< Sun Mar 01 2015 00:00:00 GMT+0100 (CET)
On a leap year, the 1st + 28 = 29th Feb:
在闰年,1 日 + 28 = 2 月 29 日:
> new Date(2016, 1, 29)
< Mon Feb 29 2016 00:00:00 GMT+0100 (CET)
In the code above, I set the date to 29th Feb and look if a roll-over took place. If not (the month is still 1, i.e. February), this is a leap year, otherwise a non-leap one.
在上面的代码中,我将日期设置为 2 月 29 日,然后查看是否发生了翻转。如果不是(月份仍为1,即二月),则这是闰年,否则为非闰年。
回答by Gone Coding
Compared to using new Date()
this is is around 100 times faster!
与使用new Date()
它相比,它快了大约 100 倍!
Update:
更新:
This latest version uses a bit test of the bottom 3 bits (is it a multiple of 4), as well as a check for the year being a multiple of 16 (bottom 4 bits in binary is 15) and being a multiple of 25.
这个最新版本使用了底部 3 位的位测试(它是 4 的倍数),以及检查年份是 16 的倍数(二进制的底部 4 位是 15)和 25 的倍数。
ily = function(y) {return !(y & 3 || !(y % 25) && y & 15);};
It is slightly faster again than my previous version (below):
它再次比我以前的版本(如下)略快:
ily = function(yr) {return !((yr % 4) || (!(yr % 100) && (yr % 400)));};
It is also 5% faster, compared to the already fast conditional operator version by broc.seib
与 broc.seib 已经很快的条件运算符版本相比,它也快了 5%
Speed Test results: http://jsperf.com/ily/6
速度测试结果:http: //jsperf.com/ily/6
Expected logic test results:
预期的逻辑测试结果:
alert(ily(1900)); // false
alert(ily(2000)); // true
alert(ily(2001)); // false
alert(ily(2002)); // false
alert(ily(2003)); // false
alert(ily(2004)); // true
alert(ily(2100)); // false
alert(ily(2400)); // true
回答by bofs
isLeap = !(new Date(year, 1, 29).getMonth()-1)
...subtraction by one should work even faster than compare on most CPU architectures.
...减一应该比在大多数 CPU 架构上的比较还要快。
回答by broc.seib
Correct and Fast:
正确和快速:
ily = function(yr) { return (yr%400)?((yr%100)?((yr%4)?false:true):false):true; }
If you are in a loop or counting the nanoseconds, this is two magnitudes faster than running your year through a new Date() object. Compare the performance here: http://jsperf.com/ily
如果您在循环中或计算纳秒,这比通过新的 Date() 对象运行您的一年快两个数量级。在这里比较性能:http: //jsperf.com/ily
回答by spirographer
Better historical computation of leap years.
更好的闰年历史计算。
The code below takes into account that leap years were introduced in 45BC with the Julian calendar, and that the majority of the Western world adopted the Gregorian calendar in 1582CE, and that 0CE = 1BC.
下面的代码考虑到闰年是在公元前 45 年引入儒略历的,而西方世界的大部分地区在公元 1582 年采用公历,0CE = 1BC。
isLeap = function(yr) {
if (yr > 1582) return !((yr % 4) || (!(yr % 100) && (yr % 400)));
if (yr >= 0) return !(yr % 4);
if (yr >= -45) return !((yr + 1) % 4);
return false;
};
Britain and its colonies adopted the Gregorian calendar in 1752, so if you are more Anglo centric this version is better (We'll assume Britain adopted the Julian calendar with Roman conquest starting in 43CE).
英国及其殖民地在 1752 年采用了格里高利历,所以如果你更以盎格鲁为中心,这个版本会更好(我们假设英国从公元 43 年开始采用罗马征服的儒略历)。
isLeap = function(yr) {
if (yr > 1752) return !((yr % 4) || (!(yr % 100) && (yr % 400)));
if (yr >= 43) return !(yr % 4);
return false;
};
回答by guijob
You can easily make this to work calling .isLeapYear()
from momentjs
:
您可以轻松地使其工作.isLeapYear()
从momentjs
以下调用:
var notLeapYear = moment('2018-02-29')
console.log(notLeapYear.isLeapYear()); // false
var leapYear = moment('2020-02-29')
console.log(leapYear.isLeapYear()); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.21.0/moment.min.js"></script>
回答by Adam
I use this because I hate having to keep referring to January as 0 and February as 1. To me and PHP and readable dates, February=2. I know it doesn't really matter as the number never changes but it just keeps my brain thinking the same across different code.
我使用它是因为我讨厌不得不将一月称为 0,将二月称为 1。对我和 PHP 以及可读日期来说,二月 = 2。我知道这并不重要,因为数字永远不会改变,但它只是让我的大脑在不同的代码中保持相同的想法。
var year = 2012;
var isLeap = new Date(year,2,1,-1).getDate()==29;
回答by Daut
Pseudo code
伪代码
if year is not divisible by 4 then not leap year
else if year is not divisible by 100 then leap year
else if year is divisible by 400 then leap year
else not leap year
JavaScript
JavaScript
function isLeapYear (year) {
return year % 4 == 0 && ( year % 100 != 0 || year % 400 == 0 )
}
Using the above code insures you do only one check per year
if the year
is not divisible by 4
Just by adding the brackets you save 2 checks per year
that is not divisible by 4
year
如果year
不能被 4 整除,则使用上面的代码确保您只进行一次检查只需添加括号,您就可以保存 2 次year
不能被 4 整除的检查
回答by Robert Todar
Another alternative is to see if that year has the date of February 29th. If it does have this date, then you know it is a leap year.
另一种选择是查看该年份是否为2 月 29 日。如果它确实有这个日期,那么你就知道这是一个闰年。
ES6
ES6
// Months are zero-based integers between 0 and 11, where Febuary = 1
const isLeapYear = year => new Date(year, 1, 29).getDate() === 29;
Tests
测试
> isLeapYear(2016);
< true
> isLeapYear(2019);
< false