javascript to find leap year

假如想象 提交于 2019-11-26 18:49:52

It's safer to use Date objects for datetime stuff, e.g.

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:

> new Date(2015, 1, 29)
< Sun Mar 01 2015 00:00:00 GMT+0100 (CET)

On a leap year, the 1st + 28 = 29th Feb:

> 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.

Compared to using new Date() this is is around 100 times faster!

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.

ily = function(y) {return !(y & 3 || !(y % 25) && y & 15);};

http://jsperf.com/ily/15

It is slightly faster again than my previous version (below):

ily = function(yr) {return !((yr % 4) || (!(yr % 100) && (yr % 400)));};

http://jsperf.com/ily/7

It is also 5% faster, compared to the already fast conditional operator version by broc.seib

Speed Test results: 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
isLeap = !(new Date(year, 1, 29).getMonth()-1)

...subtraction by one should work even faster than compare on most CPU architectures.

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

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.

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).

isLeap = function(yr) {
  if (yr > 1752) return !((yr % 4) || (!(yr % 100) && (yr % 400)));
  if (yr >= 43) return !(yr % 4);
  return false;
};

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.

var year = 2012;
var isLeap = new Date(year,2,1,-1).getDate()==29;

You can easily make this to work calling .isLeapYear() from 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>

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

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!