views:

782

answers:

4

What is a good implementation of a IsLeapYear function in VBA?

Edit: I ran the if-then and the DateSerial implementation with iterations wrapped in a timer, and the DateSerial was quicker on the average by 1-2 ms (5 runs of 300 iterations, with 1 average cell worksheet formula also working).

+7  A: 
Public Function isLeapYear(Yr As Integer) As Boolean  

    ' returns FALSE if not Leap Year, TRUE if Leap Year  

    isLeapYear = (Month(DateSerial(Yr, 2, 29)) = 2)  

End Function

I originally got this function from Chip Pearson's great Excel site.

Pearson's site

Lance Roberts
creative solution! I wonder how it performs against the others posted.
Erik van Brakel
performance now listed in the question
Lance Roberts
That does not take into account all of the leap year rules.
StingyJack
Actually, if you study what they're doing, it always works. They check to see if the february month has 29 days, and that makes it a leapyear. It basically pawns the leapyear rules onto Microsoft. Chip has a lot of good solutions.
Lance Roberts
+9  A: 
public function isLeapYear (yr as integer) as boolean
    isLeapYear   = false
    if (mod(yr,400)) = 0 then isLeapYear  = true
    elseif (mod(yr,100)) = 0 then isLeapYear  = false
    elseif (mod(yr,4)) = 0 then isLeapYear  = true
end function

Wikipedia for more... http://en.wikipedia.org/wiki/Leap_year

seanyboy
this one might even be more efficient. i like that it specifically takes the definition of leap year and works it into the answer.
nathaniel
I should have used an elseif. To make it more obvious. In fact, I'll do that...
seanyboy
the variable isLeap isn't being used
Lance Roberts
So it isn't. I've fixed it.
seanyboy
Being evenly divisible by 4 doesn't a leap year make! 2100 isn't a leap year. The division by 400 part of the test should come before the division by 4.
rp
+3  A: 

If efficiency is a consideration and the expected year is random, then it might be slightly better to do the most frequent case first:

public function isLeapYear (yr as integer) as boolean
    if (mod(yr,4)) <> 0 then isLeapYear  = false
    elseif (mod(yr,400)) = 0 then isLeapYear  = true
    elseif (mod(yr,100)) = 0 then isLeapYear  = false
    else isLeapYear = true
end function
Brent.Longborough
If efficiency is the goal you can get rid of isLeapYear = false, as boolean values default to false:)
Oorang
A: 

I found this funny one on CodeToad :

Public Function IsLeapYear(Year As Varient) As Boolean
IsLeapYear = IsDate("29-Feb-" & Year)
End Function

Altough i'm pretty sure that the use of IsDate in a function if probably slower than a couple if, elseif.

Pascal Paradis