Start learning free

LESSON 84 OF 338 · CONDITIONAL STATEMENTS - CHALLENGES

Leap Year in Go: Checking 400, 100 and 4 in Order

Practice Read the full explanation

A leap year happens every four years, so it's a year that is perfectly divisible by four.

However, if the year is a multiple of 100 (1800, 1900, etc), the year must be divisible by 400 to be leap.

Write a function that determines if the year is a leap year or not.

Examples:

leapYear(2020) ➞ true

leapYear(2021) ➞ false

leapYear(1968) ➞ true

leapYear(1900) ➞ false

Video Solution:

STEP 1 OF 4
    Ctrl + Enter to check

    GO · CONDITIONAL STATEMENTS - CHALLENGES

    Leap Year in Go, explained

    Problem overview

    The function isLeapYear receives a year as an int and returns true when it is a leap year and false otherwise. The rule has three layers:

    • a year divisible by 4 is a leap year;
    • except that a year divisible by 100 is not;
    • except that a year divisible by 400 is, after all.

    So 2020 and 1968 are leap years (divisible by 4, not by 100). 2021 is not (not divisible by 4). 1900 is not, because it is divisible by 100 but not by 400. 2000 is, because it is divisible by 400.

    Approach

    The rule has exceptions to exceptions, which is easy to get wrong if you test the conditions in the order they were written. The way out is to test from the most specific case to the most general, and to return as soon as one test decides the answer.

    Checking 400 first means a year like 2000 is accepted before the century rule gets a chance to reject it. After that, a year that reaches the 100 test is a century year that failed the 400 test, so the answer is false. A year that reaches the 4 test is not a century year, so divisibility by 4 settles it. Anything left over is not divisible by 4, so it is false.

    Each test relies on the ones before it having returned, which keeps every condition short.

    Step by step

    1. Test divisibility by 400. If year % 400 == 0, return true. The remainder operator % gives what is left after a division, so a remainder of 0 means the division is exact.
    2. Test divisibility by 100. If year % 100 == 0, return false. Only century years that are not multiples of 400 reach this line, such as 1900 or 2100.
    3. Test divisibility by 4. If year % 4 == 0, return true. Years that reach this line are not multiples of 100, so the ordinary every-four-years rule applies.
    4. Return false. If none of the three tests matched, the year is not divisible by 4.

    The solution in Go

    func isLeapYear(year int) bool {
        if year % 400 == 0 {
            return true
        }
        if year % 100 == 0 {
            return false
        }
        if year % 4 == 0 {
            return true
        }
        return false
    }
    

    Go details to notice:

    • No else branches. Each return leaves the function, so the code after an if only runs when its condition was false. The chain reads top to bottom as a list of rules.
    • Operator precedence. % binds tighter than ==, so year % 400 == 0 means (year % 400) == 0. The standard formatter, gofmt, writes it as year%400 == 0, with the tight spacing showing the higher precedence.
    • Integer remainder. The result of % takes the sign of the left operand in Go, so -7 % 4 is -3. That cannot trip up this lesson, because a remainder of 0 is 0 whatever the sign.
    • The result is a bool. The function can also be written as a single return: year%4 == 0 && (year%100 != 0 || year%400 == 0). This gives the same results as the step-by-step version, but the ordered version is easier to read and to extend.

    Complexity

    The function performs at most three remainder operations and comparisons, so time is O(1) and extra space is O(1).

    Edge cases and common mistakes

    • Century years. 1900 and 2100 are not leap years; 1600 and 2000 are. These are the years the order of the tests exists to handle.
    • Testing 4 first. If the function returned true for year % 4 == 0 before anything else, 1900 would be reported as a leap year.
    • Testing 100 first. If the function returned false for multiples of 100 first, 2000 would be reported as a non-leap year.
    • Using = instead of ==. In Go, = assigns and cannot appear in a condition, so if year % 4 = 0 is a compile error.
    • Years before 1 and year 0. The rule is applied mechanically to any integer, so isLeapYear(0) returns true. The calendar never had a year 0, but the lesson's tests do not depend on that.

    Testing

    • isLeapYear(2020) gives true.
    • isLeapYear(2021) gives false.
    • isLeapYear(1968) gives true.
    • isLeapYear(1900) gives false.
    • isLeapYear(2000) gives true.
    • isLeapYear(2100) gives false.
    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free