Is a Year a Leap Year in C#? – The Ultimate Guide

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:

RuleConditionExample
1Divisible by 4✔ 2024, 2028
2Except if divisible by 100✘ 1900, 2100 (not leap)
3Unless 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)

YearResultReason
2024✔ LeapDivisible by 4
2023✘ NoNot divisible by 4
2000✔ LeapDivisible by 400
1900✘ NoDivisible by 100, not 400
2100✘ NoFuture non-leap century
2400✔ LeapDivisible 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

TaskBest Method
Check leap yearDateTime.IsLeapYear(year)
Validate Feb 29DaysInMonth(year, 2)
Avoid crashesUse DateTime.TryParse
Handle rangesLINQ + DateTime.IsLeapYear
Edge casesAlways 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