# Leap year algorithm?

I wrote two functions for determining leap years. ("Kabisat" means "leap year" in Indonesia.)

def kabisat? y
return false if y%4!=0
return true if y%100!=0
y%400==0
end

def kabisat_2? y
return true if y%400==0
return false if y%100==0
y%4==0
end

require 'date';

(1..Date.today.year).each { |y|
puts y if kabisat?(y)!=kabisat_2?(y)
}

Is it correct? And it is possible to write a shorter one?

• Why not use the built-in Date#leap? method? In any event, your kabisat_1 function is broken. It'll return true for, say, 2013, because it's not divisible by 100. But 2013 certainly isn't a leap year. Commented Mar 14, 2013 at 10:06
• no it is not? kabisat? 2013 == false Commented Mar 14, 2013 at 10:30
• Yes, your method checks y%4!=0 first, so it'll return the right thing. But reversing the checks is suspect. The logic is that "if a year is divisible by 100, it's not a leap year". But that does not mean, that every year that isn't divisible automatically is a leap year. I.e. the check against 100 can only can only tell you if something's not a leap year; it can't tell you if it is. Commented Mar 14, 2013 at 10:55
• You should test it with some corner cases, e.g. 1900, 2000, 2004. Commented Mar 14, 2013 at 11:32
• Why don't u google? rosettacode.org/wiki/Leap_year#Ruby Commented Mar 14, 2013 at 23:34

Some notes:

• I assume that, for some reason, you want to write your own function/method instead of the existing Date#leap? that @Flambino linked above.
• kabisat? We all love our mother tongue, but in computing English is the lingua franca, specially when you share your code with people around the world. It's a nice word to learn, though :-)
• This is a personal advice, not all Ruby programmers agree: don't use inline returns. Use the good old full-fledged conditionals, it's much more clear. In general, use expressions instead of statements.

Let's see the standard algorithm. Ok, I'll just translate it to Ruby (if I felt fancy I'd even add Integer#divisible_by?(n) for a fully declarative code):

def is_leap_year?(year)
if year % 400 == 0
true
elsif year % 100 == 0
false
elsif year % 4 == 0
true
else
false
end
end

Too verbose? use boolean logic:

def is_leap_year?(year)
(year % 400 == 0) || (year % 100 != 0 && year % 4 == 0)
end
• i like the boolean logic :3 Commented Mar 14, 2013 at 12:05