VBA is year a leap year
0. Quick guide - test for leap year
In this module:
- Leap year function - from first principles
- Leap year function - using VBA functions: DateSerial, Month, and Year
1. Leap year
A leap year is:
- Any year that is exactly divisible by 4 ✅
- except if exactly divisible by 100 ❌
- but if exactly divisible by 400 ✅
- except if exactly divisible by 100 ❌
The extra day is added to the month of February, with 29th February often described as a leap day. Exactly divisible means remainder 0 and can be determined by the VBA Mod operator.
The leap year calendar adjustment is needed because the earth rotates at 365.242375 times per year.
- Point 1 adds \(+0.25\)
- Then is corrected every 100 years in point 2 giving \(-0.01\)
- Finally point 3 adds 1 days every 400 year, equivalent to \(+0.0025\).
- The result: \(365 + 0.25 - 0.01 + 0.0025 = 365.2425\).
2. VBA code leap year identification
2.1 Using logic components
Code 1 and 2 are variations of the logic depicted in part 1 points 1 to 3. The VBA Mod operator divides two numbers and returns only the remainder.
Code 1: Function
xlfIsLeapYear_v1 returns the Boolean value TRUE if Year is a leap year
Function xlfIsLeapYear_v1(Year As Integer) As Boolean
Dim bLY As Boolean
' -- point 1 --- --- point 2 ---- --- point 3 ----
If Year Mod 4 = 0 And (Year Mod 100 <> 0 Or Year Mod 400 = 0) Then bLY = True Else bLY = False
xlfIsLeapYear_v1 = bLY
End Function
Code 2 uses an If...Then construct to achieve the same outcome.
Code 2: Function
xlfIsLeapYear_v2 returns the Boolean value TRUE if Year is a leap year.
Function xlfIsLeapYear_v11(Year As Integer) As Boolean
Dim Tmp As Boolean
If Year Mod 400 = 0 Then ' point 3
Tmp = True
ElseIf Year Mod 100 = 0 Then ' point 2
Tmp = False
ElseIf Year Mod 4 = 0 Then ' point 1
Tmp = True
Else
Tmp = False
End If
xlfIsLeapYear_v2 = Tmp
End Function
VBA dates run from 1 January 100 to 31 December 9999 with corresponding serial date values -657434 to 2958465
Excel dates run from 1 January 1900 to 31 December 9999 with corresponding serial date values 1 to 2958465. Negative serial dates are not recognised in Excel. It is well known that the serial date sequence is incorrect because Excel includes 1900 as a leap. Thus 29th February 1900 with serial date value 60 is an error (inherited from Lotus 123). The VBA based functions in code 1, 2 and 3 each handle the 1900 date error correctly.
Table 1: A comparison of WS and VBA dates
| Date | Excel WS | VBA |
|---|---|---|
| 1 January 100 | ######## | -657434 |
| 30 December 1899 | ######## | 0, stored as 12:00:00 AM |
| 31 December 1899 | ######## | 1 |
| 0 January 1900, WS date format applied to zero | 0 | |
| 1 January 1900 | 1 | 2 |
| 2 January 1900 | 2 | 3 |
| 28 February 1900 | 59 | 60 |
| 29 February 1900 (the 1900 leap year error) | 60 | 61, stored as 1 March 1900 |
| 1 March 1900 | 61 | 61 |
| 31 December 2030 | 47848 | 47848 |
2.2 Using the VBA date functions
This is another variation uses VBA functions DateSerial, Month, and Year.
Code 3: Function
xlfIsLeapYear_v3 returns the Boolean value TRUE if Year is a leap year
Function xlfIsLeapYear_v3(Year As Integer) As Boolean
xlfIsLeapYear_v3 = Month(DateSerial(Year, 2, 29)) = 2
End Function
Note: the WS version of code 3 would fail in the year 1900. See lines 2 and 3 of the worksheet in figure 1.

WS formula line 3 =MONTH(DATE(1900,2,29))=2 returns TRUE ❌
WS formula called from VBA Application.ExecuteExcel4Macro("MONTH(DATE(1900,2,29))=2") returns FALSE
- Development platform: Office 365 ProPlus Excel 64 bit.
- Published: 29th February 2016
- Revised: Friday 24th of February 2023 - 03:12 PM, Pacific Time (PT)
