Donkha's coding blog

How to calculate leap years

In the Gregorian calendar, common years have 365 days and leap years 366 with february extended to 29 instead of 28. This happens roughly every 4 years but there are some exceptions. So when you're dealing with dates or calendars, you want an accurate answer.

This article is mainly written for JavaScript, but aside the first and last example that are very specific to it, you can easily port the code to whatever you want to.
Just note that the function's argument is expected to be an integer.

In JavaScript the lazy way is to create a Date object initialized to february 29 for a simple check:

function isLeapYear(_year) {
   return new Date(_year, 1, 29).getMonth() == 1; // month 0=jan 1=feb etc
}
// or
function isLeapYear(_year) {
   return new Date(_year, 1, 29).getDate() == 29;
}

If this is a common year with february ending by 28, the date will auto-shift to the first march (month2 day1) then the function returns false.

So what is the actual rule?

According to the Gregorian calendar, which is the civil calendar in use today, years evenly divisible by 4 are leap years, with the exception of centurial years that are not evenly divisible by 400. Therefore, the years 1700, 1800, 1900 and 2100 are not leap years, but 1600, 2000, and 2400 are leap years.

My initial human-readable interpretation was:

function isLeapYear(_year) {
   if (_year % 4 == 0) {
       if (_year % 100 == 0) {
           return _year % 400 == 0;
       }
       return true;
   }
   return false;
}

Now let's take a look at this pseudocode:

if (year is not divisible by 4) then (it is a common year)
else if (year is not divisible by 100) then (it is a leap year)
else if (year is not divisible by 400) then (it is a common year)
else (it is a leap year)

Basically:

function isLeapYear(_year) {
   if (_year % 4 != 0)
       return false;
   if (_year % 100 != 0)
       return true;
   return _year % 400 == 0;
}

If you plan to do intensive calls (which I highly doubt) the 2 previous versions may be the most optimal, otherwise it's probably better to shorten like this:

function isLeapYear(_year) {
   return (_year % 4 == 0 && _year % 100 != 0) || _year % 400 == 0;
}

In JavaScript a single line function is a nice candidate for the shorter ES6 arrow function, which let you omit parentheses for single argument, brackets and return keyword for single line statement:

const isLeapYear = _year => (_year % 4 == 0 && _year % 100 != 0) || _year % 400 == 0;
Thoughts? Leave a comment