In this short tutorial, you'll see how to get the previous month and year in Python using the datetime and dateutil libraries. Whether you're generating monthly reports, processing billing cycles, or handling time-based data, calculating the last month correctly (including year transitions) is essential.

Python's datetime module provides powerful tools for date manipulation, but handling month boundaries and year rollover requires careful consideration. This guide shows you practical, production-ready solutions.

The relativedelta from the dateutil library is the most reliable way to calculate last month because it automatically handles year boundaries and varying month lengths.

from datetime import datetime
from dateutil.relativedelta import relativedelta

current_date = datetime.now()
last_month_date = current_date - relativedelta(months=1)

print(f"Current date: {current_date.strftime('%Y-%m-%d')}")
print(f"Last month: {last_month_date.strftime('%Y-%m')}")
print(f"Last month year: {last_month_date.year}")
print(f"Last month number: {last_month_date.month}")

Output Result:

Current date: 2026-02-14
Last month: 2026-01
Last month year: 2026
Last month number: 1

How it works: The relativedelta(months=1) subtracts exactly one month from the current date, automatically handling transitions like January → December (previous year). This is perfect for monthly billing, report generation, and subscription management.

Installation: If you don't have dateutil installed, run:

pip install python-dateutil

2. Handling Year Boundary Transitions

Here's a practical example showing how relativedelta correctly handles year transitions when the current month is January.

from datetime import datetime
from dateutil.relativedelta import relativedelta

january_date = datetime(2026, 1, 15)
last_month_from_jan = january_date - relativedelta(months=1)

print(f"Starting date: {january_date.strftime('%B %Y')}")
print(f"Last month: {last_month_from_jan.strftime('%B %Y')}")
print(f"Year correctly changed: {last_month_from_jan.year}")

march_date = datetime(2026, 3, 31)
last_month_from_march = march_date - relativedelta(months=1)

print(f"\nStarting date: {march_date.strftime('%B %Y')}")
print(f"Last month: {last_month_from_march.strftime('%B %Y')}")
print(f"Handles different month lengths: Day is {last_month_from_march.day}")

Output Result:

Starting date: January 2026
Last month: December 2025
Year correctly changed: 2025

Starting date: March 2026
Last month: February 2026
Handles different month lengths: Day is 28

Real-world scenario: When processing Q1 reports in January, you need December data from the previous year. The relativedelta method automatically adjusts the year, unlike manual calculations that might break at year boundaries.

3. Getting Last Month Name and Formatted Dates

For generating reports, invoices, or user-facing displays, you often need the month name and formatted dates rather than just numbers.

from datetime import datetime
from dateutil.relativedelta import relativedelta
import calendar

current_date = datetime.now()
last_month_date = current_date - relativedelta(months=1)

last_month_name = last_month_date.strftime('%B')
last_month_short = last_month_date.strftime('%b')
last_month_year_full = last_month_date.strftime('%B %Y')

first_day_last_month = last_month_date.replace(day=1)
last_day_last_month = last_month_date.replace(
    day=calendar.monthrange(last_month_date.year, last_month_date.month)[1]
)

print(f"Last month full name: {last_month_name}")
print(f"Last month short name: {last_month_short}")
print(f"Last month with year: {last_month_year_full}")
print(f"First day of last month: {first_day_last_month.strftime('%Y-%m-%d')}")
print(f"Last day of last month: {last_day_last_month.strftime('%Y-%m-%d')}")

Output Result:

Last month full name: January
Last month short name: Jan
Last month with year: January 2026
First day of last month: 2026-01-01
Last day of last month: 2026-01-31

Practical applications: Use this for invoice generation ("Invoice for January 2026"), email subject lines ("Monthly Report - Jan 2026"), or database queries (filtering records between first and last day of previous month).

4. Batch Processing: Getting Multiple Previous Months

When building analytics dashboards or trend reports, you often need data for the last N months. Here's how to generate a list of previous months efficiently.

from datetime import datetime
from dateutil.relativedelta import relativedelta

def get_last_n_months(n):
    """Get last N months with year"""
    current_date = datetime.now()
    months_list = []
    
    for i in range(1, n + 1):
        past_month = current_date - relativedelta(months=i)
        months_list.append({
            'year': past_month.year,
            'month': past_month.month,
            'month_name': past_month.strftime('%B'),
            'full_date': past_month.strftime('%Y-%m')
        })
    
    return months_list

last_6_months = get_last_n_months(6)

print("Last 6 months of data:")
for month_data in last_6_months:
    print(f"{month_data['full_date']} - {month_data['month_name']} {month_data['year']}")

Output Result:

Last 6 months of data:
2026-01 - January 2026
2025-12 - December 2025
2025-11 - November 2025
2025-10 - October 2025
2025-09 - September 2025
2025-08 - August 2025

Use cases: Perfect for sales trend analysis, quarterly reports, customer retention metrics, or any time series visualization requiring historical month data.

Common Use Cases

Monthly Billing Systems: Calculate billing period for subscription services

billing_month = datetime.now() - relativedelta(months=1)
invoice_title = f"Invoice for {billing_month.strftime('%B %Y')}"

Report Generation: Create automated monthly reports with proper naming

report_date = datetime.now() - relativedelta(months=1)
filename = f"sales_report_{report_date.strftime('%Y_%m')}.pdf"

Database Queries: Filter records from last month

last_month = datetime.now() - relativedelta(months=1)
first_day = last_month.replace(day=1)
last_day = last_month.replace(day=calendar.monthrange(last_month.year, last_month.month)[1])

Subscription Management: Check if subscription was active last month

Analytics Dashboards: Display month-over-month comparisons

Alternative Methods

Manual Calculation (Problematic)

from datetime import datetime

current_date = datetime.now()
month = current_date.month - 1 if current_date.month > 1 else 12
year = current_date.year if current_date.month > 1 else current_date.year - 1

print(f"Last month: {year}-{month:02d}")

Output Result:

Last month: 2026-01

Why avoid: This works but requires manual year adjustment, doesn't handle day overflow (e.g., March 31 → February 31 doesn't exist), and is error-prone. Always prefer relativedelta for production code.

Quick Reference: Date Format Codes

Code Output Example
%Y 4-digit year 2026
%y 2-digit year 26
%m Month number 01
%B Full month name January
%b Short month name Jan
%d Day of month 14
%Y-%m-%d ISO date format 2026-01-14

Choosing the Right Method

  • Production code? → Use relativedelta (Method 1)
  • Year boundary transitions?relativedelta handles automatically (Method 2)
  • Human-readable formats? → Use strftime() formatting (Method 3)
  • Multiple months? → Build helper function with relativedelta (Method 4)

For all production applications, relativedelta from python-dateutil is the recommended approach. It's reliable, handles edge cases, and is the industry standard for date arithmetic in Python.