Calculate Month Difference in Python

PythonPythonBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

Working with dates and times is a common task in programming. Python provides the powerful datetime module to handle date and time operations efficiently. In this lab, you will learn how to calculate the difference between two dates in terms of months, which is useful for financial calculations, project timelines, and data analysis.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/BasicConceptsGroup(["Basic Concepts"]) python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/ModulesandPackagesGroup(["Modules and Packages"]) python(("Python")) -.-> python/FileHandlingGroup(["File Handling"]) python(("Python")) -.-> python/PythonStandardLibraryGroup(["Python Standard Library"]) python/BasicConceptsGroup -.-> python/type_conversion("Type Conversion") python/FunctionsGroup -.-> python/function_definition("Function Definition") python/FunctionsGroup -.-> python/arguments_return("Arguments and Return Values") python/ModulesandPackagesGroup -.-> python/standard_libraries("Common Standard Libraries") python/FileHandlingGroup -.-> python/file_opening_closing("Opening and Closing Files") python/PythonStandardLibraryGroup -.-> python/date_time("Date and Time") subgraph Lab Skills python/type_conversion -.-> lab-13696{{"Calculate Month Difference in Python"}} python/function_definition -.-> lab-13696{{"Calculate Month Difference in Python"}} python/arguments_return -.-> lab-13696{{"Calculate Month Difference in Python"}} python/standard_libraries -.-> lab-13696{{"Calculate Month Difference in Python"}} python/file_opening_closing -.-> lab-13696{{"Calculate Month Difference in Python"}} python/date_time -.-> lab-13696{{"Calculate Month Difference in Python"}} end

Understanding Date Objects in Python

Before calculating the month difference between dates, we need to understand how to work with date objects in Python. In this step, we will learn about the datetime module and create some date objects.

First, let's create a new Python file in the project directory. Open the WebIDE and click on the "New File" icon in the explorer panel on the left side. Name the file month_difference.py and save it in the /home/labex/project directory.

Now add the following code to import the necessary modules:

from datetime import date
from math import ceil

## Create example date objects
date1 = date(2023, 1, 15)  ## January 15, 2023
date2 = date(2023, 3, 20)  ## March 20, 2023

## Print the dates to see their format
print(f"Date 1: {date1}")
print(f"Date 2: {date2}")

## Calculate the difference in days
day_difference = (date2 - date1).days
print(f"Difference in days: {day_difference}")

Save the file and run it using the terminal:

python3 ~/project/month_difference.py

You should see output similar to this:

Date 1: 2023-01-15
Date 2: 2023-03-20
Difference in days: 64

The date class from the datetime module allows us to create date objects by specifying the year, month, and day. When we subtract one date from another, Python returns a timedelta object. We can access the number of days in this object using the .days attribute.

In this example, there are 64 days between January 15, 2023, and March 20, 2023.

Creating the Month Difference Function

Now that we understand how to work with date objects and calculate the difference in days, let's create a function to calculate the difference in months.

In many applications, a month is approximated as 30 days. While this is not always accurate (months can have 28 to 31 days), it is a common simplification that works well for many business calculations.

Open your month_difference.py file and add this function below your existing code:

def months_diff(start, end):
    """
    Calculate the difference in months between two dates.

    Args:
        start (date): The start date
        end (date): The end date

    Returns:
        int: The number of months between the dates (rounded up)
    """
    ## Calculate the difference in days
    days_difference = (end - start).days

    ## Convert days to months (assuming 30 days per month) and round up
    months = ceil(days_difference / 30)

    return months

Let's understand what this function does:

  1. It takes two parameters: start and end, which are date objects
  2. It calculates the difference in days between these dates
  3. It divides by 30 to convert days to months
  4. It uses ceil() to round up to the nearest integer
  5. It returns the result as an integer

The ceil() function is used because in many business scenarios, even a partial month is counted as a full month for billing purposes.

To test our function, add the following code at the end of your file:

## Test the months_diff function with our example dates
print(f"Months between {date1} and {date2}: {months_diff(date1, date2)}")

## Test with some other date pairs
print(f"Months between 2020-10-28 and 2020-11-25: {months_diff(date(2020, 10, 28), date(2020, 11, 25))}")
print(f"Months between 2020-12-15 and 2021-01-10: {months_diff(date(2020, 12, 15), date(2021, 01, 10))}")

Save your file and run it again:

python3 ~/project/month_difference.py

You should see output like:

Date 1: 2023-01-15
Date 2: 2023-03-20
Difference in days: 64
Months between 2023-01-15 and 2023-03-20: 3
Months between 2020-10-28 and 2020-11-25: 1
Months between 2020-12-15 and 2021-01-10: 1

Notice that:

  • The 64 days between 2023-01-15 and 2023-03-20 is calculated as 3 months (64/30 = 2.13, rounded up to 3)
  • The difference between October 28 and November 25 is calculated as 1 month
  • The difference between December 15 and January 10 (across a year boundary) is also calculated as 1 month

Testing with Various Date Scenarios

To better understand how our months_diff function works with different date scenarios, let's create a separate test file. This approach is common in software development to verify that our code works as expected.

Create a new file called month_diff_test.py in the /home/labex/project directory:

from datetime import date
from month_difference import months_diff

## Test scenario 1: Dates in the same month
date1 = date(2023, 5, 5)
date2 = date(2023, 5, 25)
print(f"Same month: {months_diff(date1, date2)} month(s)")

## Test scenario 2: Consecutive months
date3 = date(2023, 6, 28)
date4 = date(2023, 7, 15)
print(f"Consecutive months: {months_diff(date3, date4)} month(s)")

## Test scenario 3: Dates crossing year boundary
date5 = date(2023, 12, 20)
date6 = date(2024, 1, 10)
print(f"Across years: {months_diff(date5, date6)} month(s)")

## Test scenario 4: Several months apart
date7 = date(2023, 3, 10)
date8 = date(2023, 9, 20)
print(f"Several months: {months_diff(date7, date8)} month(s)")

## Test scenario 5: Dates in reverse order (negative result)
print(f"Reverse order: {months_diff(date8, date7)} month(s)")

## Test scenario 6: Exact multiples of 30 days
date9 = date(2023, 1, 1)
date10 = date(2023, 1, 31)  ## 30 days
date11 = date(2023, 3, 2)   ## 60 days
print(f"30 days exactly: {months_diff(date9, date10)} month(s)")
print(f"60 days exactly: {months_diff(date9, date11)} month(s)")

Save this file and run it:

python3 ~/project/month_diff_test.py

You should see output similar to:

Same month: 1 month(s)
Consecutive months: 1 month(s)
Across years: 1 month(s)
Several months: 7 month(s)
Reverse order: -7 month(s)
30 days exactly: 1 month(s)
60 days exactly: 2 month(s)

Let's analyze these results:

  1. Same month: Even within the same month, our function returns 1 month. This is because even a partial month is counted as a full month.

  2. Consecutive months: For dates in consecutive months, the function returns 1 month.

  3. Across years: For dates that cross the year boundary, the function still calculates correctly.

  4. Several months: For dates that are several months apart, the function calculates the appropriate number of months.

  5. Reverse order: When the end date is before the start date, we get a negative result, which makes sense for scenarios like calculating remaining time.

  6. Exact multiples: For exactly 30 days, we get 1 month. For 60 days, we get 2 months. This confirms our function works as expected with exact multiples of our month definition.

Our months_diff function handles all these test cases correctly according to our definition of a month as 30 days.

Creating a Practical Application: Subscription Calculator

Now that we have a reliable function for calculating month differences, let's apply it to a real-world scenario. We will create a subscription calculator that determines the cost of a service subscription between two dates.

Create a new file called subscription_calculator.py in the /home/labex/project directory:

from datetime import date, timedelta
from month_difference import months_diff

def calculate_subscription_cost(start_date, end_date, monthly_fee):
    """
    Calculate the total cost of a subscription between two dates.

    Args:
        start_date (date): Subscription start date
        end_date (date): Subscription end date
        monthly_fee (float): Cost per month

    Returns:
        float: Total subscription cost
    """
    ## Calculate number of months
    months = months_diff(start_date, end_date)

    ## Calculate total cost
    total_cost = months * monthly_fee

    return total_cost

## Example: Calculate subscription cost for a streaming service
start = date(2023, 1, 15)  ## Subscription starts January 15, 2023
end = date(2023, 8, 20)    ## Ends August 20, 2023
monthly_cost = 9.99        ## $9.99 per month

total = calculate_subscription_cost(start, end, monthly_cost)
print(f"Subscription period: {start} to {end}")
print(f"Monthly fee: ${monthly_cost:.2f}")
print(f"Total cost: ${total:.2f}")

## Compare with an annual plan
annual_cost = 99.99  ## $99.99 per year
print(f"\nAnnual plan cost: ${annual_cost:.2f}")
print(f"Monthly plan for same period: ${total:.2f}")

if total > annual_cost:
    print(f"Savings with annual plan: ${total - annual_cost:.2f}")
else:
    print(f"Additional cost for annual plan: ${annual_cost - total:.2f}")

## Calculate cost for a trial period
today = date.today()
trial_end = today + timedelta(days=7)  ## 7-day trial
trial_cost = calculate_subscription_cost(today, trial_end, monthly_cost)
print(f"\nOne-week trial period: {today} to {trial_end}")
print(f"Trial period cost: ${trial_cost:.2f}")

Save the file and run it:

python3 ~/project/subscription_calculator.py

You should see output similar to this (the trial dates will show your current date):

Subscription period: 2023-01-15 to 2023-08-20
Monthly fee: $9.99
Total cost: $79.92

Annual plan cost: $99.99
Monthly plan for same period: $79.92
Additional cost for annual plan: $20.07

One-week trial period: 2023-06-01 to 2023-06-08
Trial period cost: $9.99

This application demonstrates how our months_diff function can be used in a practical scenario:

  1. We calculate the total cost of a subscription based on the number of months between two dates
  2. We compare this cost with an annual plan to help a user decide which plan is more economical
  3. We calculate the cost for a short trial period

Notice how even the 7-day trial gets charged as one full month in our model. This is because our function rounds up any partial month to a full month, which is common in subscription billing.

This type of calculation is frequently used in:

  • Subscription services (streaming, software, memberships)
  • Loan and mortgage calculations
  • Rental agreements
  • Project billing

Summary

In this lab, you learned how to calculate the month difference between two dates in Python. Here is what you accomplished:

  1. You learned how to work with date objects from the datetime module
  2. You created a months_diff function that calculates month differences using a 30-day month approximation
  3. You tested the function with various date scenarios to ensure it works correctly
  4. You applied the function to a real-world scenario by creating a subscription calculator

These skills are valuable for many applications, including:

  • Financial calculations (loans, investments, billing)
  • Project planning and management
  • Subscription services
  • Date-based data analysis

To further enhance your skills in working with dates in Python, you could explore:

  • Working with time components using datetime.datetime
  • Handling different timezones using the pytz library
  • Using the dateutil library for more advanced date operations
  • Implementing different approaches to calculate month differences (e.g., calendar months instead of 30-day periods)

Date and time calculations are essential in many programming tasks, and the techniques you learned in this lab provide a solid foundation for handling these calculations in your Python projects.