liveBook · Manning

Date arithmetic

As explained in Software Design for Python Programmers

Date arithmetic is the calculation of dates by adding or subtracting time intervals and determining differences between dates.

Date arithmetic calculates dates by adding or subtracting intervals and finding the number of days between dates. Gregorian rules make this difficult because month lengths, leap years, missing year zero, and the 1582 calendar transition all matter. section 5.3

A Date implementation can evolve through two contrasting approaches:

  • Loop day by day, using private methods for the next and previous dates. This handles positive and negative intervals but creates a new Date object on every iteration and becomes expensive for large differences. section 5.3.1
  • Represent each date internally with a Julian day number. Adding days becomes integer addition, and the difference between dates becomes subtraction. section 5.3.2
  • Convert between Julian numbers and Gregorian year, month, and day values through private conversion methods, preserving implementation hiding while introducing conversion cost for getters. section 5.3.2

Checking inverse operations

For September 2, 2025 and April 3, 2027, days_from returns 578. Adding 578 days to the first date produces the second; reversing the calculation returns −578 and recovers the first date. section 5.3.1

Listing 5.3 (Program 5.2 DateArithmetic-1): date.py (1 of 4; very inefficient!)
class Date:
    _JANUARY  = 1    #1
    _FEBRUARY = 2     #1
    _DECEMBER = 12     #1
 #1
    _GREGORIAN_START_YEAR = 1582     #1
    _GREGORIAN_START_MONTH = 10     #1
    _GREGORIAN_START_DATE = 15     #1
    _JULIAN_END_DATE = 4     #1
 #1
    _DAYS_IN_MONTH = ( 31, 28, 31, 30, 31, 30,      #1
                       31, 31, 30, 31, 30, 31 )     #1

    def __init__(self, year, month, day): 
        self._year = year    #2
        self._month = month     #2
        self._day = day     #2

    @property
    def year(self): return self._year    #3

    @property
    def month(self): return self._month    #3

    @property
    def day(self): return self._day    #3

    def __repr__(self):
        date_string = f'{self.month}/{self.day}/'
        if self.year > 0: date_string += str(self.year)
        else:             date_string += str(-self.year) + ' BCE'

        return date_string

Inspect the loop-based Date implementation, including calendar constants, date stepping, and interval methods. section 5.3.1

How Software Design for Python Programmers covers it

How deep it goes
Descends from calendar rules to loop-based stepping and Julian-number internals, while exposing conversion costs and implementation tradeoffs.
Examples
Uses September 2, 2025, April 3, 2027, loop-based stepping, and Julian-number addition and subtraction.
What it assumes
Assumes basic classes, private state, methods, and properties; teaches calendar rules and date representations explicitly.
What you can do after
Build it from scratch in a Python Date class using calendar-aware stepping or Julian-number arithmetic.
How it connects
Connects Gregorian calendar rules, Julian day numbers, Date classes, private methods, and implementation hiding.

Also explained in

Compare how 2 books explain date arithmetic →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Software Design for Python Programmers. The section links point to the parts of the book it draws on.