Year 2004 is a leap year, with 29 days in February. We all generally know that leap years occur every four years, and most of the time, that is the case. However, there are some subtle but complex and important rules for calculating leap years.
In a recent project that I was working on, I was creating a custom calendar-type component for a rock band. They wanted a custom calendar that had a very specific look-and-feel and some unique functionality than the standard Flash Calendar Component does not provide.
Creating a Calendar Component from scratch isn't very difficult. The most complicated thing that I encountered was having to understand and calculate leap years, as users would page between various months or years on the calendar component.
Which Years are Leap Years?
In the Gregorian calendar, which is the calendar used by most modern countries, the following rules describe which years are leap years:
- Every year evenly divisible by 4 is PROBABLY a leap year
- The exception to rule #1 is that every year evenly divisible by 100 is NOT a leap year.
- The exception to rule #2 is that every year evenly divisible by 100 that is also evenly divisible by 400 IS a leap year.
This means that the years 1800, 1900, 2100, 2200, 2300 and 2500 are NOT leap years, while the years 2000 and 2400 are leap years. Though most of the talk when we went into the year 2000 was about Y2K, there was also some minor discussion that we were in a situation where all three exceptions applied making 2000, a year divisible by 100 normally not a leap year, was actually a leap year because it's also evenly divisible by 400.
It's kind of a confusing set of rules, and translating this into an ActionScript function that will tell you if a particular year is a leap year can be a little challenging. The verbose, but easier to read way of writing this function in ActionScript is as follows:
checkLeapYear = function (inYear) {
if (inYear % 4 == 0) {
if (inYear % 100 == 0) {
return (inYear % 400 == 0);
} else {
return (true);
}
} else {
return (false);
}
};
If you use this function by passing a year into the function call, it will return a true (is a leap year) or false (is not a leap year) value.
If we step through the code, you can see that we start by testing if the year passed into the function (inYear) is evenly divisible by zero. The modulus operator (%) tells us if there is a remainder value after dividing by another value, in this case 4. By using '==0' after it, we are effectively evaluating the incoming variable to see if it's evenly divisible by the number 4. This like will come back as a true or false. If it's false, the function skips to the bottom 'else' statement and returns the value 'false' meaning that this year is not a leap year.
If however, line 2 'if(inYear %4 == 0)' evaluates out to true, we move to the next line down. This line uses the same modulus operator to see if the year is evenly divisible by 100. If it's not, it goes to the inner else statement and returns 'true' indicating that it is a leap year. Otherwise, it does a final test to see if the inYear value is evenly divisible by 400. If it is, it returns true (is a leap year), if it is not, it returns false (not a leap year). This line return (inYear % 400 == 0); does not use an if statement to return a true or false value because the == operator is going to return a Boolen value of true or false, make it simpler to write it as one line and allowing the result of true or false to be returned from the function.
This same function can actually be written on a single line of code. Because we are always working with Boolean values, we can use Boolean operators such as not (!) and (&&) and or (||) to avoid using any 'if' statements at all.
The simplified version of this formula would be written as:
checkLeapYear2 = function (inYear) {
return ((inYear % 4 == 0) && !(inYear % 100 == 0)) || (inYear % 400 == 0);
};You can test both functions with this code to see that they will result with the same result.
for(var i = 1880; i<2020; i++){
trace(checkLeapYear (i) +" : "+ checkLeapYear2(i))
}