{{ message }}

Instantly share code, notes, and snippets.

Last active Feb 6, 2020
Possible Leap Year Bugs in Your Python Code

Possible Leap Year Bugs in Your Python Code

``````Author: Ray Luo
Date: 2020-2-6
``````
``````    Know your enemy.
- Sun Tzu
``````

This is a Python code snippet to demonstrate how some possible leap-year bugs could happen in your Python code base.

With such understanding, you are better educated to know what to look for in your code base.

 # Experiencing all the leap year anti-patterns defined in # https://dev.azure.com/msazure/AzureWiki/_wiki/wikis/AzureWiki.wiki/14194/Leap-Year-Code-Anti-patterns from datetime import date, datetime from datetime import timedelta # Anti-pattern 1: Adding/subtracting/modifying year while keeping the existing month and day leapday2020 = date(2020, 2, 29) # leapday2020.replace(year=2019) # It raises ValueError # Anti-pattern 1a, 6: Assuming all combinatinos of year-month-day components are valid # nonexist = date(2019, 2, 29) # It raises ValueError # Anti-pattern 2: Adding or subtracting days when intending to represent a year first_day_2020 = date(2020, 1, 1) next_year = first_day_2020 + timedelta(days=365) print(next_year.year) # It will not be 2021 # Solution real_next_year = first_day_2020.replace(year=first_day_2020.year + 1) print(real_next_year.year) # It will be 2021 # Anti-pattern 3: Behavior and solution similar to Anti-pattern 2 # Anti-pattern 4: days = [0] * 365 print(len(days)) # Insufficient to store daily data sample in a leap year # Anti-pattern 5, 7: Detect leap year incorrectly year = 1900 is_leap_year = year % 4 == 0 # This is True if is_leap_year: print("Is year 1900 really a leap year?") # date(year, 2, 29) # 1900 is not a leap year # Anti-pattern 8: Parsing a date string containing only month and day information print(datetime.strptime("2-28", "%m-%d")) # Year defaults to 1900, so got 1900-2-28 # print(datetime.strptime("2-29", "%m-%d")) # ValueError