Leap Year Calculator

Level: Beginner 15–30 min

Concepts: Validation

Solutions: C# | TypeScript | Python


Create a program to determine if a given year is a leap year.

Requirements

  1. Implement leap year rules:
    • A year is a leap year if it is divisible by 4
    • However, if the year is divisible by 100, it is not a leap year
    • Unless the year is also divisible by 400, then it is a leap year
  2. Handle input validation:
    • Input must be a positive integer
    • Input must be a valid year (e.g., not negative)
  3. Return appropriate results:
    • Boolean indicating if the year is a leap year
    • Error message for invalid inputs

Test Cases

YearIs Leap Year?Reason
2000YesDivisible by 400
2004YesDivisible by 4, not by 100
2100NoDivisible by 100, not by 400
2001NoNot divisible by 4
0ErrorInvalid year
-1ErrorInvalid year

Edge Cases to Consider

  • Year 0
  • Negative years
  • Non-integer inputs
  • Very large years
  • Null or undefined inputs

Tips

  • Start with the basic divisible by 4 rule
  • Add the divisible by 100 exception
  • Finally add the divisible by 400 rule
  • Consider using a separate method for input validation
  • Use descriptive variable names for the rules

Reference Walkthrough

Reference implementations in C#, TypeScript, and Python live at tddbuddy-reference-katas/leap-year. Eight scenarios cover the full rule cascade — typical leap years (2020, 2024), century non-leap years (1900, 2100), four-hundred-divisible leaps (2000, 1600), and plain non-leap years (2001, 2023) — shared across all three languages, each a single pure function int → bool. Input validation concerns listed above (zero, negative years, non-integer inputs) are not implemented in the reference — the Gregorian rule cascade alone is sufficient to demonstrate the shape.

This kata ships in Agent Full-Bake mode at high gear (F1 tier): the algorithm is small enough to land as one commit per language, with a brief walkthrough noting there are no builders because the algorithm’s inputs and outputs are the domain. No aggregates to construct, no value types to introduce, no collaborators to inject — just isLeapYear(year). See the repo’s Gears section for when high gear is the right call.