Pandas DateOffset: Add or Subtract Months, Years and Days

pd.DateOffset() performs calendar-aware date and time arithmetic in Pandas. It can add or subtract months, years, weeks, days, hours, minutes and other date parts from a Timestamp, DatetimeIndex or datetime Series.

DateOffset is especially useful for calendar operations such as "one month later" or "one year earlier", where the duration cannot always be represented by a fixed number of days.


Syntax of pd.DateOffset() 🔝

pd.DateOffset(years=..., months=..., weeks=..., days=..., hours=..., minutes=..., seconds=...)

Plural keywords perform relative arithmetic:

years
months
weeks
days
hours
minutes
seconds
milliseconds
microseconds
nanoseconds

For example:

date + pd.DateOffset(months=2)
date - pd.DateOffset(days=10)

Singular keywords such as year, month and day have a different meaning: they replace a component of the date instead of adding an interval.

Create a Sample Date DataFrame 🔝

import pandas as pd

data={'NAME':['Ravi', 'Raju', 'Alex'],
      'dt_start':['2020-01-31', '2020-02-29', '2019-02-28']}

df=pd.DataFrame(data)
df['dt_start']=pd.to_datetime(df['dt_start'])
print(df)
Output
   NAME   dt_start
0  Ravi 2020-01-31
1  Raju 2020-02-29
2  Alex 2019-02-28

pd.to_datetime() converts the text values to Pandas datetime values so date arithmetic can be performed.

Add or Subtract Days 🔝

Add 365 Days

df['dt_end']=df['dt_start']+pd.DateOffset(days=365)
print(df)
Output
   NAME   dt_start     dt_end
0  Ravi 2020-01-31 2021-01-30
1  Raju 2020-02-29 2021-02-28
2  Alex 2019-02-28 2020-02-28

Subtract 30 Days

df['dt_end']=df['dt_start']-pd.DateOffset(days=30)

The minus operator applies the offset in the opposite direction.

Add or Subtract Calendar Years 🔝

df['dt_end']=df['dt_start']+pd.DateOffset(years=2)
print(df)
Output
   NAME   dt_start     dt_end
0  Ravi 2020-01-31 2022-01-31
1  Raju 2020-02-29 2022-02-28
2  Alex 2019-02-28 2021-02-28

The leap-day value 2020-02-29 becomes 2022-02-28 because February 29 does not exist in 2022.

Subtract One Year

df['dt_end']=df['dt_start']-pd.DateOffset(years=1)

Add or Subtract Calendar Months 🔝

df['dt_end']=df['dt_start']+pd.DateOffset(months=3)
print(df)
Output
   NAME   dt_start     dt_end
0  Ravi 2020-01-31 2020-04-30
1  Raju 2020-02-29 2020-05-29
2  Alex 2019-02-28 2019-05-28

The first result is April 30 because April does not have a 31st day.

Subtract Two Months

df['dt_end']=df['dt_start']-pd.DateOffset(months=2)

What Happens at the End of a Month? 🔝

Calendar months have different numbers of days. If the same day does not exist in the destination month, DateOffset uses the last valid day of that month.

dt=pd.Timestamp('2026-01-31')

print(dt+pd.DateOffset(months=1))
print(dt+pd.DateOffset(months=2))
Output
2026-02-28 00:00:00
2026-03-31 00:00:00

Add Years, Months and Days Together 🔝

Several relative components can be combined in one offset.

df['dt_end']=df['dt_start']+pd.DateOffset(years=2, months=3, days=13)
print(df)
Output
   NAME   dt_start     dt_end
0  Ravi 2020-01-31 2022-05-13
1  Raju 2020-02-29 2022-06-11
2  Alex 2019-02-28 2021-06-10

Add Hours, Minutes and Seconds 🔝

Add Two Hours

df['dt_end']=df['dt_start']+pd.DateOffset(hours=2)

Add Hours, Minutes and Seconds

df['dt_end']=df['dt_start']+pd.DateOffset(hours=2, minutes=50, seconds=43)
print(df)
Output
   NAME   dt_start              dt_end
0  Ravi 2020-01-31 2020-01-31 02:50:43
1  Raju 2020-02-29 2020-02-29 02:50:43
2  Alex 2019-02-28 2019-02-28 02:50:43

milliseconds, microseconds and nanoseconds can also be used.

Plural vs Singular DateOffset Keywords 🔝

This is one of the most important features of DateOffset.

Relative / PluralMeaningAbsolute / SingularMeaning
years=1Add one yearyear=2026Set year to 2026
months=1Add one monthmonth=6Set month to June
days=1Add one dayday=15Set day of month to 15
hours=2Add two hourshour=9Set hour to 9
minutes=10Add ten minutesminute=30Set minute to 30

day=15 vs days=15

dt=pd.Timestamp('2021-02-25')

print(dt+pd.DateOffset(day=15))
print(dt+pd.DateOffset(days=15))
Output
2021-02-15 00:00:00
2021-03-12 00:00:00

day=15 replaces the day-of-month component. days=15 adds 15 calendar days.

Replace Date and Time Components 🔝

Singular keywords replace parts of a date:

year
month
day
weekday
hour
minute
second
microsecond
nanosecond

Replace the Year

dt=pd.Timestamp('2020-06-18 14:25:30')
result=dt+pd.DateOffset(year=2026)
print(result)
Output
2026-06-18 14:25:30

Replace Month and Day

result=dt+pd.DateOffset(month=12, day=1)
print(result)
Output
2020-12-01 14:25:30

Timestamp.replace()

dt=pd.Timestamp('2020-06-18 14:25:30')
result=dt.replace(year=2026, month=12)
print(result)

Use DateOffset with a Pandas Timestamp 🔝

tm=pd.Timestamp(year=2020, month=12, day=23, hour=18, minute=20, second=5)
result=tm+pd.DateOffset(months=2)
print(result)
Output
2021-02-23 18:20:05

Combine Several Components

tm=pd.Timestamp('2026-09-06 10:00:00')
offset=pd.DateOffset(years=1, months=2, days=3, hours=4, minutes=40, seconds=20)
print(tm+offset)
Output
2027-11-09 14:40:20

365 Days Is Not Always One Calendar Year 🔝

A calendar year and 365 days are different concepts.

dt=pd.Timestamp('2020-01-31')

print(dt+pd.DateOffset(days=365))
print(dt+pd.DateOffset(years=1))
Output
2021-01-30 00:00:00
2021-01-31 00:00:00

The year 2020 contains 366 days, so adding 365 days produces January 30, while adding one calendar year preserves January 31.

DateOffset vs Timedelta 🔝

DateOffset and Timedelta overlap for many operations, but they represent different ideas.

DateOffsetTimedelta
Calendar-aware relative arithmeticFixed elapsed duration
Supports calendar months and yearsBest for fixed days, hours, minutes, seconds
DateOffset(months=1)No fixed Timedelta equivalent to one calendar month
Can adjust invalid month-end datesRepresents an exact duration

Fixed Duration

dt=pd.Timestamp('2026-01-15')
print(dt+pd.Timedelta(days=10))

Calendar Month

print(dt+pd.DateOffset(months=1))

For fixed elapsed-time calculations, see Pandas date differences and timedelta64.

Do Not Use NumPy Months or Years as Fixed Durations

NumPy supports M and Y timedelta units internally, but calendar months and years do not correspond to a constant number of days. For Pandas calendar arithmetic, DateOffset(months=...) and DateOffset(years=...) express the intent more clearly.

DateOffset and Daylight Saving Time 🔝

Calendar-day arithmetic can differ from adding an exact 24-hour duration when timezone daylight-saving changes occur.

DateOffset(days=1) means the same local time on the next calendar day, while a 24-hour Timedelta represents exactly 24 elapsed hours.

dt=pd.Timestamp('2026-03-07 12:00', tz='US/Eastern')

print(dt+pd.DateOffset(days=1))
print(dt+pd.Timedelta(hours=24))

This distinction matters when applications work with timezone-aware timestamps across daylight-saving transitions.

MonthEnd and MonthBegin Offsets 🔝

Pandas provides specialized DateOffset subclasses for common calendar rules.

Move to a Month End

dt=pd.Timestamp('2026-09-15')
print(dt+pd.offsets.MonthEnd())
Output
2026-09-30 00:00:00

Move to the Next Month Start

print(dt+pd.offsets.MonthBegin())
Output
2026-10-01 00:00:00

These specialized offsets are useful when the desired result is tied to a calendar boundary rather than simply adding a number of months.

Add Business Days 🔝

BusinessDay advances through weekdays and skips Saturday and Sunday.

dt=pd.Timestamp('2026-09-04')
result=dt+pd.offsets.BusinessDay()
print(result)
Output
2026-09-07 00:00:00

September 4, 2026 is a Friday, so the next business day is Monday, September 7.

BusinessDay handles weekdays. Public holidays are not automatically excluded unless a custom business calendar is configured.

rollforward() and rollback() 🔝

Specialized offsets can check whether a timestamp lies on a valid offset date and move it to the nearest valid date.

Roll Forward to the Next Month End

dt=pd.Timestamp('2026-09-15')
offset=pd.offsets.MonthEnd()

print(offset.rollforward(dt))
Output
2026-09-30 00:00:00

Roll Back to the Previous Month End

print(offset.rollback(dt))
Output
2026-08-31 00:00:00

If the timestamp already satisfies the offset, rollforward() or rollback() can leave it unchanged.

Common Pandas DateOffset Mistakes 🔝

1. Calling DataFrame.DateOffset()

Incorrect:

df.DateOffset(months=1)

Use:

pd.DateOffset(months=1)

2. Confusing month with months

pd.DateOffset(month=6)   # replace month with June
pd.DateOffset(months=6)  # add six months

3. Treating 365 Days as One Year

Leap years mean that days=365 and years=1 can produce different dates.

4. Treating One Month as 30 Days

Calendar months contain 28, 29, 30 or 31 days. Use months=1 when the requirement is one calendar month.

5. Expecting January 31 + One Month to Remain on Day 31

If the destination month does not have the original day number, Pandas adjusts to a valid month-end date.

6. Using Singular Keywords for Relative Arithmetic

year=2026 sets the year. It does not mean "add 2026 years".

7. Using NumPy timedelta64('M') or timedelta64('Y') for Calendar Arithmetic

Months and years do not have fixed durations. Prefer DateOffset(months=...) or DateOffset(years=...) when working with calendar dates.

8. Ignoring Timezones

For timezone-aware values, a calendar day and an exact 24-hour duration can differ across daylight-saving transitions.

Summary of Pandas DateOffset 🔝

  • Use pd.DateOffset() for calendar-aware date arithmetic.
  • DateOffset is not a DataFrame method.
  • Plural keywords such as years, months and days perform relative arithmetic.
  • Singular keywords such as year, month and day replace date components.
  • Use months=1 for one calendar month, not a fixed number of days.
  • Invalid destination dates such as February 31 are adjusted to a valid month-end date.
  • Leap years can make years=1 different from days=365.
  • DateOffset works with Timestamp, DatetimeIndex and datetime Series.
  • Several components can be combined in one offset.
  • Use Timedelta for fixed elapsed durations such as hours or seconds.
  • DateOffset(days=1) follows calendar-day rules, which can matter across daylight-saving transitions.
  • Use specialized offsets such as MonthEnd, MonthBegin and BusinessDay for calendar rules.
  • rollforward() and rollback() move timestamps to valid offset dates.
Pandas Date & Time to_datetime() Timedelta date_range() period_range()




Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
©2000-2026   plus2net.com   All rights reserved worldwide Privacy Policy Disclaimer