Replacing Parts of a Datetime in Python
Replacing specific parts of a datetime object (year, month, day, hour, minute, etc.) is a common and powerful operation in data science. It allows you to normalize timestamps, set all records to the start of the day, align events to specific times, or adjust timezones without recreating the entire object. The .replace() method makes this task clean, readable, and efficient.
TL;DR — How to Replace Datetime Parts
dt.replace(year=..., month=..., hour=..., etc.)- Works on both
datetimeanddateobjects - Creates a new object (immutable-style behavior)
- Pandas equivalent with
.dtaccessor orpd.to_datetime
1. Basic .replace() Usage
from datetime import datetime
from zoneinfo import ZoneInfo
dt = datetime(2026, 3, 19, 14, 30, 0, tzinfo=ZoneInfo("UTC"))
# Replace specific parts
dt_midnight = dt.replace(hour=0, minute=0, second=0, microsecond=0)
dt_new_year = dt.replace(year=2027)
dt_new_month = dt.replace(month=12)
print(dt_midnight) # 2026-03-19 00:00:00+00:00
2. Real-World Data Science Examples
import pandas as pd
# Create a small demo file so this example runs as-is
# (in your project, sales_data.csv is your real export)
import numpy as np
rng = np.random.default_rng(42)
n = 60
pd.DataFrame({
"order_id": range(1001, 1001 + n),
"order_date": pd.date_range("2026-01-01", periods=n, freq="3D"),
"customer_id": rng.integers(101, 121, n),
"customer_name": rng.choice([" ana", "ben ", "chen", "dana"], n),
"product_id": rng.integers(1, 9, n),
"region": rng.choice(["North", "South", "East", "West"], n),
"category": rng.choice(["Electronics", "Computers", "Books", "Home"], n),
"payment_method": rng.choice(["card", "cash", "wallet"], n),
"segment": rng.choice(["consumer", "business"], n),
"quantity": rng.integers(1, 6, n),
"amount": rng.uniform(50, 2500, n).round(2),
"discount": rng.choice([0.0, 0.05, 0.1, 0.2], n),
}).assign(
price=lambda d: (d["amount"] / d["quantity"]).round(2),
profit=lambda d: (d["amount"] * rng.uniform(0.05, 0.3, n)).round(2),
).assign(
ship_date=lambda d: d["order_date"] + pd.Timedelta(days=2),
status=lambda d: np.where(d["amount"] > 2000, "priority", "standard"),
).to_csv("sales_data.csv", index=False)
df = pd.read_csv("sales_data.csv", parse_dates=["order_date"])
# Example 1: Normalize all timestamps to midnight (start of day)
df["order_date_start"] = df["order_date"].apply(
lambda x: x.replace(hour=0, minute=0, second=0, microsecond=0)
)
# Example 2: Set all events to the same hour for comparison
df["order_date_hour"] = df["order_date"].apply(lambda x: x.replace(minute=0, second=0))
# Example 3: Move all records to the first day of the month
df["first_of_month"] = df["order_date"].apply(lambda x: x.replace(day=1))
3. Replacing Timezone Information
dt = datetime.now(ZoneInfo("UTC"))
# Change timezone without changing the instant in time
dt_ny = dt.replace(tzinfo=ZoneInfo("America/New_York")) # wrong way
# Correct way:
dt_ny = dt.astimezone(ZoneInfo("America/New_York"))
4. Best Practices in 2026
- Use
.replace()for simple component changes on individual datetime objects - For large DataFrames, prefer vectorized pandas methods or
.apply()with lambda - Always work with timezone-aware objects before replacing parts
- Keep original datetime column and create new derived columns for replaced values
- Use
replace()to normalize times (e.g., set to midnight or hour start)
How replace Works on Datetimes
datetime.replace returns a new datetime with selected fields changed, such as replace(day=1) for the first of the month or replace(hour=0, minute=0, second=0, microsecond=0) for midnight. The original object is unchanged, because datetimes are immutable.
replace does not move a timestamp in time; it simply overwrites fields. Using it to change tzinfo therefore relabels the time zone without converting the clock time, which is usually a bug.
In pandas, .dt.to_period("M").dt.start_time and .dt.normalize() cover common replace use cases for whole columns.
Worked Example: Month Starts and Invalid Dates
We compute month starts and see what happens with an impossible day.
from datetime import datetime
import pandas as pd
dt = datetime(2026, 3, 19, 14, 30, 45)
print(dt.replace(day=1, hour=0, minute=0, second=0))
print(dt)
try:
datetime(2026, 1, 31).replace(month=2)
except ValueError as err:
print("ValueError:", err)
s = pd.Series(pd.to_datetime(["2026-03-19 14:30", "2026-04-02 08:00"]))
print(s.dt.to_period("M").dt.start_time.tolist())
replace returns the month start while dt itself is unchanged. Changing 31 January to February fails with a ValueError, because February has no 31st. pandas returns month starts for the whole column.
Common Mistakes
- Using replace to convert time zones.
- Expecting replace to modify the original object.
- Replacing the month without checking the day.
- Looping over rows instead of using .dt methods.
Quick Summary
- replace overwrites fields in a new object.
- It does not convert time zones.
- Invalid dates raise ValueError.
- Use .dt methods for columns.
Conclusion
Replacing parts of a datetime object with .replace() is a simple yet powerful technique that every data scientist should master. In 2026, it is commonly used for normalizing timestamps, creating start-of-day/hour features, aligning data, and preparing clean time-based features for modeling and reporting.
Next steps:
- Go through one of your datasets and create new columns by replacing specific parts of the datetime (e.g., start of day, first of month, etc.)