Get your leap years right

Thirty days hath September
April, June and November
All the rest hath thirty one
Except February alone

Snowboarder up high by Jason Lugo @ iStockphoto

You just divided the year by 4 right? If the year is divisible by 4, then it’s a leap year, isn’t it? Yes it is, if you still use 2 digit years, and that’s if 00 represents 2000 and not 1900.

[The Gregorian calendar is the basis used for the following discussion.]

Back in the pre-Y2K years, many programs were written with 2 digit representations of years. Actually, I have no idea when the first computer was built. I’m not talking about abacus, or big light bulbs, or gas chambers. There were gas chambers right? *smile* I remember hearing about humongous contraptions that required entire rooms to house them. They’re not what I’m referring to. I’m talking about the computer as we know it now, that’s about a few decades old, back in the 90’s.

Anyway, the time period when those programs were written was between 1900 and 2000. So any 2 digit year, such as 1940 represented by 40, divisible by 4 was a leap year. 2000 came and went. There were still many programs written with the 2 digit year representation. This presented a problem.

Does 04 represent 1904, or 2004? To minimise changes from a 2 digit to a 4 digit representation, a workaround was used. Any 2 digit year below a certain number was designated to be in the 21st century, otherwise it’s in the 20th century.

For example, 15 would represent 2015, whereas 63 referred to 1963. The Oracle database uses 50 as the magic number. So 2 digit years range from 1950 to 2049.

I’ve maintained legacy code which uses 80, so it could handle 1980 to 2079. Probably with the assumption that anything before 1980 was really really old and thus was no longer useful data.

The magic number was introduced to allow the divide-by-4 leap year calculation to continue working.

I implore you. Please use the proper calculation formula for leap years. And please use the 4 digit year representation.

if ((year modulo 4 is 0) and (year modulo 100 is not 0)) or (year modulo 400 is 0)
then leap
else no_leap

I’ve had occasion to write a Javascript function involving counting days in months. Which involved February. Which inevitably involved calculating leap years. So we have,

(year modulo 4 is 0) and (year modulo 100 is not 0)

which translates to

(iCurrentYear%4==0) && (iCurrentYear%100!=0)


year modulo 400 is 0



It’s not that hard, is it? So the final if condition becomes

if ( ((iCurrentYear%4==0) && (iCurrentYear%100!=0)) || (iCurrentYear%400==0) )

In English: Any year that’s divisible by 4 but is not a century year (I made that up) is a leap year. So 1896, 1904 are leap years but 1900 is not.

What about 2000? That’s a leap year, and it’s a century year. Aahhh… Century years are not leap years, unless they are divisible by 400. So 1600, 2000, 2400 are leap years.

“But that formula won’t kick in till 2100!” you exclaim. “I can still use the divide-by-4 method!”

You and I will probably not be around in 2100. The application will probably not even live past 2010, let alone 2100.

The point is, the change is minor, yet allows your application to live a lot longer. So why don’t you change? Your unwillingness to change (or improve)? Your laziness? What is holding you back?

P.S. The Wikipedia article on leap years indicate that in 8000 years, the above formula might fail. 8000 years is plenty time.

An alien might time-travel to 2008 and use an application I wrote. Then the alien travels back to his time, year 2099 and finds that my application fails once 2100 crosses over. I’d hate to have an angry extraterrestrial breathing down my neck…

And happy birthday to leaplings!

Comments are closed.