Leap years in a range
Enter two years and get every leap year between them, both ends included: from 2000 to 2024 there are 7, starting with 2000 and ending with 2024. Century years follow the Gregorian rule, so 1900 is skipped and 2000 counts. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Start year
- 2,000
- End year
- 2,024
- Year span
- 25
- Quantity
- 7
- Rule
- Gregorian: year%4==0 and (year%100!=0 or year%400==0)
Leap years insert an extra day—February 29—so the civil calendar stays aligned with the tropical year. Under the Gregorian system used by most of the world today, a year is a leap year when it is divisible by four, except century years, which must also be divisible by four hundred. That means 2000 is a leap year, 1900 is not, and ordinary years such as 2024 and 2028 are. This tool takes an inclusive start year and end year, walks every year in the range with a pure deterministic leap test, and returns both the count and the ordered list of leap years.
How Gregorian leap years are decided
The Gregorian reform refined the older Julian rule that every fourth year was a leap year. Under Gregorian rules a year Y is a leap year if and only if Y is divisible by four and either Y is not divisible by one hundred or Y is divisible by four hundred. In compact form: leap when Y modulo four equals zero and (Y modulo one hundred is not zero or Y modulo four hundred equals zero).
Century years that fail the four-hundred test—1700, 1800, 1900, 2100—are common years with only three hundred sixty-five days, while 1600 and 2000 remain leap years. This capability applies the proleptic Gregorian rule uniformly for every integer year from one through nine thousand nine hundred ninety-nine, matching sibling calendar tools in the KIT catalog.
The implementation never calls JavaScript Date, never reads the wall clock, and never hits the network: it parses two integer years, rejects an inverted range, then scans the inclusive interval collecting every year that passes the leap predicate.
Where leap-year range lists show up in real work
School and contest problems constantly ask how many leap years fall between two years or which years in a century include February twenty-nine; a trusted oracle that returns both the count and the full list speeds grading and demo setup. Product and operations teams building multi-year roadmaps, retention cohorts, or billing calendars need to know when February has twenty-nine days so schedules, SLAs, and day-count formulas stay honest.
Software that generates ICS files, school term calendars, or payroll periods for long horizons benefits from a pure function that never depends on the host timezone or Date constructor quirks. If you later need day-of-year ordinals, weekend counts between two ISO dates, or Julian Day Numbers, treat those as separate search intents and landings rather than overloading this leap-year range page.
What you can do with it
Homework and contest answer keys
Generate the ordered list and count of leap years between two years so teachers and auto-graders share one Gregorian ground truth.
Multi-year planning and billing calendars
Mark every February 29 in a product roadmap, retention cohort, or billing horizon without timezone-sensitive Date bugs.
FAQ
What leap-year rule does this use?
Proleptic Gregorian: a year is a leap year if it is divisible by 4, except century years, which must be divisible by 400. So 2000 is leap, 1900 is not, and 2024 is.
Is the year range inclusive?
A single-year range returns either one leap year or an empty list with count zero.
Does it use JavaScript Date?
No. The algorithm is pure integer arithmetic on the Gregorian leap predicate. No Date, no network, no randomness.
What does it cost?
The browser tool is free and runs locally.
What if I enter the start year after the end year?
The range is refused with a clear message instead of being swapped quietly, so a typo in either year shows up at once. Enter the earlier year first; a range of a single year is fine.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/date/leap-years-between \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"start_year":2000,"end_year":2024}'const res = await fetch("https://api.kit.forhosting.com/date/leap-years-between", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"start_year": 2000,
"end_year": 2024
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/date/leap-years-between",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"start_year": 2000,
"end_year": 2024
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/date/leap-years-between", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"start_year":2000,"end_year":2024}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"start_year":2000,"end_year":2024}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/date/leap-years-between", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"start_year": 2000,
"end_year": 2024
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "date.leap_years_between",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
When the start year is greater than the end year the request fails with a clear validation error instead of silently swapping the bounds.
How Gregorian leap years are decided
The result JSON echoes the bounds, the year span, the count, the ascending list, and a short rule string so you can audit the algorithm without opening the source. Pricing for successful API calls is the published base of $0.002 per item; validation failures do not consume prepaid balance.
What you send and what you get back
Both are required and must be finite integers from one to nine thousand nine hundred ninety-nine. The range is inclusive: a request from two thousand to two thousand four reports every leap year among two thousand, two thousand one, two thousand two, two thousand three, and two thousand four. Typical checks include two thousand through two thousand twenty-four for modern decades, eighteen ninety-six through nineteen oh four to show that nineteen hundred is skipped while two thousand is not, and a single-year range where the only possible leap year is that year itself. Send two integer fields named start_year and end_year. Missing fields, non-numeric strings, floats, NaN, Infinity, and years outside the allowed band also fail with invalid_input and are not charged. On success the response includes start_year, end_year, inclusive true, year_span equal to end minus start plus one, count equal to the length of the leap year list, leap_years as an ascending array of integers, plus rule and formula strings describing the Gregorian test. The browser path runs locally at no charge; API pricing is $0.002 per successful item.
Where leap-year range lists show up in real work
Because this capability is a pure parse engine, API pricing is the published base of $0.002 per successful item and failed validation does not consume balance.
Integration use cases
Data warehouse date-dimension tests
Fixture Gregorian leap lists for ETL validation, fiscal calendars, and proleptic year tables across decades or centuries.
Technical questions
What if start_year is greater than end_year?
The request fails with invalid_input. The bounds are not swapped automatically so inverted input is never silently accepted.