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 a Pandas class used as pd.DateOffset(). It is not a method such as DataFrame.DateOffset().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.
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.
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.
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
df['dt_end']=df['dt_start']-pd.DateOffset(days=30)
The minus operator applies the offset in the opposite direction.
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.
df['dt_end']=df['dt_start']-pd.DateOffset(years=1)
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.
df['dt_end']=df['dt_start']-pd.DateOffset(months=2)
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
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
df['dt_end']=df['dt_start']+pd.DateOffset(hours=2)
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.
This is one of the most important features of DateOffset.
| Relative / Plural | Meaning | Absolute / Singular | Meaning |
|---|---|---|---|
years=1 | Add one year | year=2026 | Set year to 2026 |
months=1 | Add one month | month=6 | Set month to June |
days=1 | Add one day | day=15 | Set day of month to 15 |
hours=2 | Add two hours | hour=9 | Set hour to 9 |
minutes=10 | Add ten minutes | minute=30 | Set minute to 30 |
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.
Singular keywords replace parts of a date:
year
month
day
weekday
hour
minute
second
microsecond
nanosecond
dt=pd.Timestamp('2020-06-18 14:25:30')
result=dt+pd.DateOffset(year=2026)
print(result)
Output
2026-06-18 14:25:30
result=dt+pd.DateOffset(month=12, day=1)
print(result)
Output
2020-12-01 14:25:30
DateOffset(year=2026) represent component replacement. For scalar Timestamp replacement, Timestamp.replace() can also express this intention clearly.dt=pd.Timestamp('2020-06-18 14:25:30')
result=dt.replace(year=2026, month=12)
print(result)
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
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
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.
years=1 when you mean "one calendar year later". Use days=365 only when you specifically mean a duration of 365 days.DateOffset and Timedelta overlap for many operations, but they represent different ideas.
| DateOffset | Timedelta |
|---|---|
| Calendar-aware relative arithmetic | Fixed elapsed duration |
| Supports calendar months and years | Best for fixed days, hours, minutes, seconds |
DateOffset(months=1) | No fixed Timedelta equivalent to one calendar month |
| Can adjust invalid month-end dates | Represents an exact duration |
dt=pd.Timestamp('2026-01-15')
print(dt+pd.Timedelta(days=10))
print(dt+pd.DateOffset(months=1))
For fixed elapsed-time calculations, see Pandas date differences and timedelta64.
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.
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.
Pandas provides specialized DateOffset subclasses for common calendar rules.
dt=pd.Timestamp('2026-09-15')
print(dt+pd.offsets.MonthEnd())
Output
2026-09-30 00:00:00
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.
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.Specialized offsets can check whether a timestamp lies on a valid offset date and move it to the nearest valid date.
dt=pd.Timestamp('2026-09-15')
offset=pd.offsets.MonthEnd()
print(offset.rollforward(dt))
Output
2026-09-30 00:00:00
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.
Incorrect:
df.DateOffset(months=1)
Use:
pd.DateOffset(months=1)
pd.DateOffset(month=6) # replace month with June
pd.DateOffset(months=6) # add six months
Leap years mean that days=365 and years=1 can produce different dates.
Calendar months contain 28, 29, 30 or 31 days. Use months=1 when the requirement is one calendar month.
If the destination month does not have the original day number, Pandas adjusts to a valid month-end date.
year=2026 sets the year. It does not mean "add 2026 years".
Months and years do not have fixed durations. Prefer DateOffset(months=...) or DateOffset(years=...) when working with calendar dates.
For timezone-aware values, a calendar day and an exact 24-hour duration can differ across daylight-saving transitions.
pd.DateOffset() for calendar-aware date arithmetic.DateOffset is not a DataFrame method.years, months and days perform relative arithmetic.year, month and day replace date components.months=1 for one calendar month, not a fixed number of days.years=1 different from days=365.DateOffset works with Timestamp, DatetimeIndex and datetime Series.Timedelta for fixed elapsed durations such as hours or seconds.DateOffset(days=1) follows calendar-day rules, which can matter across daylight-saving transitions.MonthEnd, MonthBegin and BusinessDay for calendar rules.rollforward() and rollback() move timestamps to valid offset dates.Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.