Table of Contents
- The Logic Behind a Leap Year (It's Not Just Every 4 Years)
- Method 1: The Standard if-elif-else Approach
- Method 2: The Optimized One-Liner
- Method 3: Using Python's Built-in calendar Module
- More leap year programs, with output
- Common Mistakes Beginners Make
- Leap year in Python: common questions
- Conclusion
A year is a leap year if it is divisible by 4 and not by 100, or if it is divisible by 400. In Python the whole rule fits on one line, (year % 4 == 0 and year % 100 != 0) or year % 400 == 0, and the standard library already has it as calendar.isleap(year). Here it is as a function, with its output:
def is_leap(year):
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
for year in [1900, 2000, 2024, 2100]:
print(year, is_leap(year))
1900 False
2000 True
2024 True
2100 False
That is why 1900 and 2100 are not leap years while 2000 is. Below: the logic in plain words, three ways to write the check, programs that find the next leap year and every leap year in a range, and a way to prove your function right. It is a common beginner exercise and interview question because it tests whether you can combine conditions without breaking the logic.
The Logic Behind a Leap Year (It's Not Just Every 4 Years)
The most common mistake beginners make is assuming a leap year happens exactly every four years, no matter what. If you code that logic, your program will fail test cases for years like 1900 or 2100.
The year of the seasons is a little shorter than 365.25 days, so adding a day every fourth year would slowly push the calendar ahead of the seasons. The Gregorian calendar corrects this by dropping three leap days every 400 years (1700, 1800 and 1900 were not leap years; 2000 was). That leaves 97 leap years in every 400, an average year of 365 + 97/400 = 365.2425 days. The rules your code must follow are:
- The year must be evenly divisible by 4.
- BUT if the year is also evenly divisible by 100, it is NOT a leap year.
- UNLESS the year is also evenly divisible by 400. Then it IS a leap year.
To check if a number is "evenly divisible" by another number, we don't use standard division. We use the modulo operator (%), which returns the remainder of a division problem. If year % 4 == 0, it means there is no remainder, so it divides perfectly. If you are still getting the hang of how Python handles division and remainders, taking a few minutes to review understanding operators like floor division in Python will make this math much easier to grasp.
Method 1: The Standard if-elif-else Approach
Let's write this out using standard conditional logic. We will put our logic inside a reusable function. Learning the advantages of functions in Python early on is crucial because it keeps your code clean and allows you to test multiple years without rewriting the logic.
Here is the standard, step-by-step approach:
def check_leap_year(year):
# Rule 1: Is it divisible by 4?
if year % 4 == 0:
# Rule 2: Is it also divisible by 100?
if year % 100 == 0:
# Rule 3: Is it ALSO divisible by 400?
if year % 400 == 0:
return True
else:
return False
else:
return True
else:
return False
# Testing the function
user_year = int(input("Enter a year to check: "))
if check_leap_year(user_year):
print(f"{user_year} is a leap year!")
else:
print(f"{user_year} is not a leap year.")
How it works: The code takes a year and filters it through nested if statements. It first checks if the year is divisible by 4. If it is, it moves deeper to check the 100 rule, and then the 400 rule. It is highly readable and explicitly follows the calendar logic step-by-step.
Method 2: The Optimized One-Liner
While the nested if-else block above works perfectly, it is a bit bulky. Professional developers try to avoid heavily nested code (often called the "Arrow Anti-Pattern" because the indentation looks like a sideways arrow).
We can use Python's logical operators, and and or, to combine all three calendar rules into a single, clean line of code.
These operators are the software version of the logic gates inside every processor. If you want to see how AND, OR and NOT work in hardware, and how they add numbers, read our guide to logic gates for beginners.
def is_leap_year(year):
# A year is a leap year if it is divisible by 4 AND NOT 100, OR if it is divisible by 400.
if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
return True
else:
return False
# You can even shrink the function down to just returning the evaluated boolean:
# return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
Why it's better: This is much more "Pythonic." The code evaluates the left side of the or statement first. If the year is a normal leap year (like 2024), it passes. If it is a century year (like 2000), the left side fails, but the right side (year % 400 == 0) catches it and correctly identifies it as a leap year.
Method 3: Using Python's Built-in calendar Module
Here is a secret: you almost never have to write this math from scratch in a real-world software project. Python has a massive standard library filled with pre-written modules that handle common tasks for you.
For dates and times, you can just import the calendar module.
import calendar
year = 2026
if calendar.isleap(year):
print(f"{year} is a leap year.")
else:
print(f"{year} is not a leap year.")
The shortcut: calendar.isleap() returns True or False for you. It is not magic: inside Python's own calendar module it is the same three rules, written as year % 4 == 0 and (year % 100 != 0 or year % 400 == 0). In real projects that work with dates, use it, and browse the calendar module documentation for what else it can do.
More leap year programs, with output
These four come up as exercises again and again. Each reuses the one-line rule.
Leap year program in Python using functions
Put the rule in a function with a docstring, then call it on a year the user types. Keeping the logic in a function means you can test it on many years without touching the input code.
def is_leap(year):
"""Return True if year is a leap year in the Gregorian calendar."""
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
year = int(input("Enter a year: "))
if is_leap(year):
print(year, "is a leap year")
else:
print(year, "is not a leap year")
Enter a year: 2024
2024 is a leap year
Find the next leap year after a given year
Start one year after the input and count upwards until the function says yes. Starting after the input matters: if the user types a leap year such as 2024, the answer must be the following one, 2028. Typing 2023 gives 2024.
def is_leap(year):
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
year = int(input("Year: "))
next_year = year + 1 # start AFTER the year typed, even if it is a leap year
while not is_leap(next_year):
next_year += 1
print(f"The next leap year after {year} is {next_year}")
Year: 2024
The next leap year after 2024 is 2028
Print all leap years between two years
A list comprehension with the same function collects every leap year in a range. Notice that 1900 is missing from the output: divisible by 100, not by 400.
def is_leap(year):
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
start = int(input("From: "))
end = int(input("To: "))
leap_years = [y for y in range(start, end + 1) if is_leap(y)]
print(leap_years)
print(len(leap_years), "leap years")
From: 1890
To: 1920
[1892, 1896, 1904, 1908, 1912, 1916, 1920]
7 leap years
How many days are in February?
calendar.monthrange(year, month) returns the weekday of the first day and the number of days in the month, so February is 29 days long exactly when the year is a leap year.
import calendar
year = int(input("Year: "))
days = calendar.monthrange(year, 2)[1] # (weekday of the 1st, number of days)
print(f"February {year} has {days} days")
Year: 2100
February 2100 has 28 days
Common Mistakes Beginners Make
If your leap year program is crashing or returning the wrong answers, check for these two massive beginner pitfalls:
Mistake 1: Forgetting to Convert User Input
When you use the input() function, Python assumes everything the user types is a text string. You cannot do math on a string.
Wrong: year = input("Enter year: ") โ year % 4 will crash.
Right: year = int(input("Enter year: ")) โ Safely converts the text "2024" into the number 2024.
Mistake 2: Using Division Instead of Modulo
If you write year / 4 == 0, your program will never work. Standard division (/) returns a decimal (e.g., 2024 / 4 = 506.0). Modulo (%) returns the remainder. You need to check if the remainder is zero. If you are still confused by the century math, check out this excellent breakdown on Math is Fun: Leap Years to reinforce why the 100/400 rule is necessary.
Mistake 3: Testing Only Easy Years
A program that says 2024 is a leap year can still be wrong about 1900 or 2100. Test the century years, or better, compare your function with calendar.isleap for every year from 1 to 3000. An empty list of disagreements means your logic matches Python's own.
import calendar
def is_leap(year):
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
wrong = [y for y in range(1, 3001) if is_leap(y) != calendar.isleap(y)]
print("Years checked: 3000")
print("Disagreements:", wrong)
Years checked: 3000
Disagreements: []
Leap year in Python: common questions
A year is a leap year if it is divisible by 4 and not divisible by 100, or if it is divisible by 400. In code: (year % 4 == 0 and year % 100 != 0) or year % 400 == 0. The modulo operator % gives the remainder, so year % 4 == 0 means the year divides exactly by 4.
No. 2100 is divisible by 4 and by 100 but not by 400, so it is not a leap year. 2000 was a leap year because it is divisible by 400.
2028. The program above finds it by starting at 2025 and counting up until the leap year rule is true.
Import the calendar module and call calendar.isleap(year). It returns True or False and uses the same three rules. Writing the rule yourself is still worth doing once, because the exercise is about combining conditions.
Because it probably checks only divisibility by 4. 1900 divides by 4 but also by 100 and not by 400, so it is not a leap year. Add the 100 and 400 rules, or test your function against calendar.isleap as shown above.
input() always returns text. "2024" % 4 does not do arithmetic, so convert first: year = int(input("Enter a year: ")).
Conclusion
Mastering the leap year program in Python is an excellent milestone. It forces you to think about edge cases (like the year 2000 vs 2100) and proves you know how to string together logical operators.
Your next challenge? Try combining this script with a menu-driven interface, or build a program that asks the user for a year and tells them exactly how many days are in that specific year's February. If you want to review the core concepts you used today, keep our comprehensive Python for beginners guide bookmarked.
For more practice at exactly this level, try finding the HCF and LCM in Python next, or watch loops draw shapes in our 30 star pattern programs.
Learn Python live, with a teacher reading your code
A leap year check is small, but it is exactly the kind of logic our students learn to reason about before they write a line. Ages 9 to 12: Python and AI for Kids. Ages 13 to 18: Python for Teens. College students and adults: Python Masterclass. The first class is a free demo, so you can see how it is taught before you decide.