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.
1. Using relativedelta from dateutil (Recommended)
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.