Master every way to check leap years in C#, from beginner to enterprise-grade validations.
⭐ Why Leap Year Checks Matter in Real Applications
Leap year calculations appear everywhere:
- Date validation systems
- Scheduling, booking, and payroll
- Time-series databases
- Financial interest calculations
- Scientific and astronomical apps
- Calendar generation
- Game development and simulation engines
Doing it wrong causes real bugs — especially around 29 February, which can crash systems if not handled correctly.
✅ The Official Leap Year Rules
A year is a leap year if:
| Rule | Condition | Example |
|---|---|---|
| 1 | Divisible by 4 | ✔ 2024, 2028 |
| 2 | Except if divisible by 100 | ✘ 1900, 2100 (not leap) |
| 3 | Unless divisible by 400 | ✔ 2000, 2400 (leap) |
So in English:
A leap year occurs every 4 years,
except centuries (years ending in 00),
unless the century is divisible by 400.
🌟 The Best Way (Built-In API) — DateTime.IsLeapYear(year)
C# has a native method that automatically applies all leap-year rules:
bool isLeap = DateTime.IsLeapYear(year);
Example:
Console.WriteLine(DateTime.IsLeapYear(2024)); // True
Console.WriteLine(DateTime.IsLeapYear(1900)); // False
Console.WriteLine(DateTime.IsLeapYear(2000)); // True
Use this unless you have a specific reason not to.
🧠 Manual Leap Year Logic (The Classic Formula)
If you want to implement the logic yourself:
bool IsLeapYear(int year)
{
return (year % 4 == 0 && year % 100 != 0)
|| (year % 400 == 0);
}
Examples:
Console.WriteLine(IsLeapYear(2024)); // True
Console.WriteLine(IsLeapYear(2023)); // False
Console.WriteLine(IsLeapYear(2100)); // False
Console.WriteLine(IsLeapYear(2400)); // True
🧪 Unit Tests for Leap Years (NUnit / xUnit)
NUnit Example
[TestCase(2024, true)]
[TestCase(2023, false)]
[TestCase(2000, true)]
[TestCase(1900, false)]
public void LeapYearTests(int year, bool expected)
{
Assert.AreEqual(expected, DateTime.IsLeapYear(year));
}
xUnit Example
[Theory]
[InlineData(2024, true)]
[InlineData(2023, false)]
[InlineData(2000, true)]
[InlineData(1900, false)]
public void LeapYearTests(int year, bool expected)
{
Assert.Equal(expected, DateTime.IsLeapYear(year));
}
🗓️ Checking if a Date Is 29 February
bool IsLeapDay(DateTime date)
{
return date.Month == 2 && date.Day == 29;
}
Example:
Console.WriteLine(IsLeapDay(new DateTime(2024, 2, 29))); // True
Console.WriteLine(IsLeapDay(new DateTime(2023, 2, 28))); // False
📅 Get Number of Days in February
int days = DateTime.DaysInMonth(year, 2);
Examples:
Console.WriteLine(DateTime.DaysInMonth(2024, 2)); // 29
Console.WriteLine(DateTime.DaysInMonth(2023, 2)); // 28
Great for calendar generation.
🧩 Leap Year + Date Validation (Avoid 29 Feb Crashes)
Bad:
var date = new DateTime(2023, 2, 29); // ❌ Throws ArgumentOutOfRangeException
Safe:
bool valid = DateTime.IsLeapYear(year) || day != 29;
Or:
DateTime.TryParse("29/02/" + year, out var date);
📘 Leap Year Utility Class
public static class LeapYearHelper
{
public static bool IsLeap(int year) =>
DateTime.IsLeapYear(year);
public static bool HasLeapDay(int year) =>
DateTime.IsLeapYear(year);
public static int DaysInFebruary(int year) =>
DateTime.DaysInMonth(year, 2);
}
🔍 Leap-Year Table (Quick Reference)
| Year | Result | Reason |
|---|---|---|
| 2024 | ✔ Leap | Divisible by 4 |
| 2023 | ✘ No | Not divisible by 4 |
| 2000 | ✔ Leap | Divisible by 400 |
| 1900 | ✘ No | Divisible by 100, not 400 |
| 2100 | ✘ No | Future non-leap century |
| 2400 | ✔ Leap | Divisible by 400 |
⚡ Examples of Common Leap-Year Checks
✔ Check a list of years
var years = new[] { 1996, 2000, 2020, 2023, 2024, 2100 };
foreach (var y in years)
Console.WriteLine($"{y}: {DateTime.IsLeapYear(y)}");
✔ Count leap years within a range
int CountLeapYears(int start, int end)
{
return Enumerable.Range(start, end - start + 1)
.Count(DateTime.IsLeapYear);
}
✔ Find next leap year
int NextLeapYear(int year)
{
year++;
while (!DateTime.IsLeapYear(year))
year++;
return year;
}
✔ Get all leap days for the next 50 years
var leapDays = Enumerable.Range(DateTime.Now.Year, 50)
.Where(DateTime.IsLeapYear)
.Select(y => new DateTime(y, 2, 29))
.ToList();
✔ Validate date components
bool IsValidDate(int y, int m, int d)
{
return m == 2 && d == 29
? DateTime.IsLeapYear(y)
: d <= DateTime.DaysInMonth(y, m);
}
🏆 Best Practice Summary
| Task | Best Method |
|---|---|
| Check leap year | DateTime.IsLeapYear(year) |
| Validate Feb 29 | DaysInMonth(year, 2) |
| Avoid crashes | Use DateTime.TryParse |
| Handle ranges | LINQ + DateTime.IsLeapYear |
| Edge cases | Always check year < 1 (invalid) |
What did you learn?
- What is a leap year in C#?
- How to check leap years in C#
- Manual leap-year formula
- Validate 29 February
- Count leap years in a range
- Leap-year utility class
- Unit tests for leap-year logic
- Why 1900 isn’t a leap year but 2000 is