How to know if it’s a leap year

It always happens : you have some calculation to do with a date and you forget to calculate those friggin’ leap years. Here’s how to do it cleanly.

The first way

Almost every one use this simple rule : if it’s divisible by 4, it’s a leap year. So the code is

  1. var isLeap = theYear % 4 == 0

Wait a minute, I forgot something! If it’s not divisible by 100 but by 400 it is not a leap year… or maybe divisble by 100 and not by 400…

I can’t remember that! Let’s do it another way.

The one and only way

  1. var isLeap = new Date(theYear,1,29).getDate() == 29;

Nice! That’s something simple that I enjoy. Let’s dissect it.

  1. new Date(theYear, 1, 29)

This line simply create a date object that is initialized with the variable theYear. 1 is the month. As in java, the months are 0 = january and 11 = december (I hate that!). 29 is the last day of february when it’s a leap year.

  1. .getDate()

Returns the date part of a date (sic!). It means that for May 23, 2007, it will return 23.

  1. == 29

That’s the magic part of it. As I said in Mastering the date object in Javascript, there’s a special twist that let you work with dates differently than in most of the languages that I used before. When you initialize a date at the 29th day of february on a non-leap year, it will simply use the date March 1, 2007. So a call to the getDate() function would return 1 and not 29.

  • Trent Gardner
    function isLeap(year) {
    return (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0));
    }

    Should be the most efficient way to calculate this.
  • here is an article of how to determine a leap year.

    http://faq.puthik.com/js/js_faq_leapY.html
  • Dan
    @pam
    From the "leap year" article on Wikipedia :
    "However, some exceptions to this rule are required since the duration of a solar year is slightly less than 365.25 days. Years that are divisible by 100 are not leap years, unless they are also divisible by 400, in which case they are leap years."

    Take a look at http://en.wikipedia.org/wiki/Leap_year
  • pam
    Why do you guys have to make things so complicated? If the last digit of the year ends with a 0,2,4,6, or 8 then its a leap year! It doesn't take a rocket scientist to figure that one out!
  • dear john
    if you ever forget how to calculate:
    http://en.wikipedia.org/wiki/Leap_year

    and there is also pseudo-code which can easily be translated to any language.
  • Aunt Edie
    I like the one from Katatunix--easy to see the date logic and its progression returns a value as quickly as possible. Thanks!
  • Dan
    Why does everyone wants to use the old way with the if and the modulo?

    new Date(theYear,1,29).getDate() == 29 is so much better!
  • ALT
    if ( ((year % 4 == 0) && !(year % 100 == 0))
    || (year % 400 == 0) )
    numDays = 29;
    else
    numDays = 28;
  • SANiK
    Correct code:
    var dateObject = new Date(theYear,1,29);
    var isLeap = dateObject.getDate() == 29;

    To get the # of days in February, one would do:
    var dateObject = new Date(theYear,2,0);
    var daysInMonth = dateObject.getDate();

    "Huh, why is it a '2' now?"
    Date(2008, 2, 1) is March 1st which is '1'
    Date(2008, 2, 0) is March 0, which doesn't exist and it would wrap BACK to February =o
  • Dan Simard
    The point was that

    new Date(theYear,1,29).getDate() == 29

    was the easiest way of doing it. No hard to read parenthesis or special move, just a simple date object creation...
  • Spacix
    function isLeap(theYear) {
    return (theYear % 4 == 0)? (theYear % 100 == 0)? (theYear % 400 == 0)? true:false:true:false;
    }


    that's too much kludge code

    best method:

    function isLeap(intYear){return ((intYear > 1582) && ((!(intYear%400)) || ((!!(intYear%100)) && (!(intYear%4)))));}

    this takes into count when leapss years were added and does other dates correctly as well
  • Gentle Geek
    Thanks for checking it Giri... I had mistyped it here- I had typed one more ":" and one less "?" than I should have typed. This is the corrected version:

    function isLeap(theYear) {
    return (theYear % 4 == 0)? (theYear % 100 == 0)? (theYear % 400 == 0)? true:false:true:false;
    }
  • Giri
    The solution you have provided does not work.
  • Dan
    @Gentle Geek
    thanks, I'll take a look at it and update the post when I'll have the time.
  • Gentle Geek
    The following is someting I had developed myself, and is very similar to what Katatunix has. However, it benefits from executing the most significant evaluations first, and thereby is more efficient- 3 of every 4 years will only do the first comparison. Also, it is one statement, so that also improves it.

    function isLeap(theYear) {
    return (theYear % 4 == 0)? (theYear % 100 == 0)? (theYear % 400 == 0): true:false:true:false;
    }
  • I think the code is simple!
  • function isLeap(theYear) {
    if (theYear % 400 == 0) return true;
    if (theYear % 100 == 0) return false;
    if (theYear % 4 == 0) return true;
    return false;
    }
  • Dan
    As I said in the post :
    "As in java, the months are 0 = january and 11 = december (I hate that!)."

    January is 0, february is 1 and march is 2...
  • bob
    Am I missing something or shouldn't your code be:

    var isLeap = new Date(theYear,2,29).getDate() == 29;
  • BK
    Just be aware of the date limitation with the year: minimum=1970
  • I wouldn't exactly say it's the "only" way, but it does seem like a good idea to reuse the already-implemented and presumably debugged leap year logic via the Date object. Good idea, thanks.
  • Dan
    @Seth
    The unnecessary Date object will be deleted as soon as possible. It would be better to have it in a util library but the problem is that we don't always have that type of library in hands when we code. I must admit that I really enjoy the shortness of the code...
  • Doesn't this run the risk of creating unnecessary objects?

    Isn't a better solution to use the mathematical method and stick it in a util library?
blog comments powered by Disqus