Data AnalyticsPandas & NumPybeginner
Updated:

Pandas Datetime Handling for Analysis

4 min read

Dates power most analysis. Learn to parse them with to_datetime, extract parts via the dt accessor, filter by date range, and resample time series in pandas.

TL;DR – Quick Answer

Convert a text date column with pd.to_datetime so pandas understands it as a real datetime, then use the .dt accessor to pull out parts like year, month and weekday. Once a column is datetime, you can filter by date range, sort chronologically, and resample to weekly or monthly totals. Correct date handling is essential for any time-based analysis.

On This Page

Almost every dataset an analyst touches has a date in it: when an order was placed, when a user signed up, when a ticket was resolved. Time-based questions, trends, growth, seasonality, cohort behaviour, are among the most valuable an analyst answers, and they all depend on pandas understanding your dates as real dates rather than plain text. This tutorial covers the datetime workflow end to end.

The single most important step is conversion. A date stored as a string is useless for math; once you turn it into a proper datetime, an entire toolkit of extraction, filtering and resampling opens up.

Parsing dates with to_datetime

Dates usually arrive as text. pd.to_datetime converts them into pandas' datetime type. Start with a small illustrative sample:

import pandas as pd

df = pd.DataFrame({
    "order_id": [1, 2, 3, 4],
    "order_date": ["2026-01-05", "2026-01-20", "2026-02-11", "2026-03-02"],
    "amount": [1200, 850, 1500, 600],
})

df["order_date"] = pd.to_datetime(df["order_date"])
print(df.dtypes)
order_id               int64
order_date    datetime64[ns]
amount                 int64
dtype: object

The order_date column is now datetime64[ns], which is what unlocks everything below. For unusual formats pass format, for example format="%d/%m/%Y", and for messy data pass errors="coerce" to turn unparseable strings into NaT (the datetime version of NaN) instead of raising an error. When reading files you can also parse dates during the load with pd.read_csv(..., parse_dates=["order_date"]).

Extracting parts with the dt accessor

Once a column is datetime, the .dt accessor exposes its components. This is how you create year, month or weekday columns to group by:

df["year"] = df["order_date"].dt.year
df["month"] = df["order_date"].dt.month
df["weekday"] = df["order_date"].dt.day_name()
print(df[["order_date", "year", "month", "weekday"]])
  order_date  year  month    weekday
0 2026-01-05  2026      1     Monday
1 2026-01-20  2026      1    Tuesday
2 2026-02-11  2026      2  Wednesday
3 2026-03-02  2026      3     Monday

.dt also gives you .day, .hour, .quarter, .dayofweek and many more. These extracted columns are ordinary Series, so you can immediately group or filter on them, for example counting orders per weekday.

Filtering by date

With a real datetime column you can compare against date strings directly, which reads naturally:

recent = df[df["order_date"] >= "2026-02-01"]
print(recent[["order_id", "order_date", "amount"]])
   order_id order_date  amount
2         3 2026-02-11    1500
3         4 2026-03-02     600

For a bounded window use between("2026-01-01", "2026-01-31"). If you set the date column as the index, pandas lets you slice ranges with elegant partial strings like df.loc["2026-01"] to get all of January.

Resampling a time series

The signature time-series operation is resampling: bucketing rows into regular periods and aggregating each. It works when a datetime is the index. Here we total sales by month:

ts = df.set_index("order_date")
print(ts["amount"].resample("ME").sum())
order_date
2026-01-31    2050
2026-02-28    1500
2026-03-31     600
Freq: ME, Name: amount, dtype: int64

The frequency code "ME" means month-end; other common codes are "D" for daily, "W" for weekly and "QE" for quarter-end. Resampling is how you turn transaction-level data into the monthly or weekly trend lines that fill dashboards.

Date arithmetic

Because datetimes are numeric under the hood, subtracting two of them yields a Timedelta, a duration you can analyze:

df["days_since_order"] = (pd.Timestamp("2026-03-15") - df["order_date"]).dt.days
print(df[["order_id", "days_since_order"]])
   order_id  days_since_order
0         1                69
1         2                54
2         3                32
3         4                13

This pattern powers recency metrics, ageing reports and cohort analysis, where "how long since X" is the core question. You can also add durations to a date using pd.Timedelta, for example df["due_date"] = df["order_date"] + pd.Timedelta(days=30) to compute a payment deadline thirty days after each order. Because pandas treats dates as true numeric quantities, shifting, differencing and comparing them all work with ordinary arithmetic once the column is a proper datetime.

Practical usage

Date handling underpins the most common analyst deliverables. A monthly revenue trend is to_datetime, then resample("ME").sum(). A day-of-week pattern is .dt.day_name() then a groupby. A cohort or retention analysis leans on date subtraction to measure elapsed time. The reliable workflow is always the same: parse dates immediately after loading, verify the dtype is datetime64, then extract, filter or resample as the question demands. Skipping the conversion step is the root cause of most date-related bugs.

Common mistakes

  • Leaving dates as text. String dates sort alphabetically, not chronologically, and cannot be subtracted or resampled. Always convert with to_datetime first and confirm the dtype.
  • Ignoring day/month ambiguity. 03/04/2026 is March 4th or April 3rd depending on locale. Pass an explicit format or dayfirst=True so the parse is unambiguous.
  • Calling .dt on a non-datetime column. The accessor only works after conversion; on an object column it raises an error. Convert first.
  • Forgetting NaT after coerce. Using errors="coerce" silently turns bad dates into NaT. Check df["date"].isna().sum() so you know how many rows failed to parse.

In interviews

Time-based questions are common because so much business data is temporal. Expect prompts like "compute monthly active users" or "find orders in the last 30 days," which test whether you convert to datetime, use the .dt accessor, and resample or filter correctly. A frequent conceptual question is why string dates are a problem, where the answer is that they cannot be sorted chronologically or used in arithmetic. Mentioning parse_dates at read time and resample for period aggregation shows a complete, practical grasp of the topic.

Where this fits in your learning path

Datetime handling is an essential applied skill in the data analytics path and often begins right at load time, which connects to reading CSV and Excel files with parse_dates. Extracted date parts feed straight into filtering rows and groupby for trend analysis. Comfort with dates is a baseline expectation for the data analyst role, where time is almost always one of the dimensions.

Frequently Asked Questions

How do I convert a column to datetime in pandas?
Use pd.to_datetime(df['date']), which parses text into real datetime values. Assign it back with df['date'] = pd.to_datetime(df['date']). Pandas recognizes most common formats automatically, and you can pass format for unusual layouts or errors='coerce' to turn unparseable values into NaT.
How do I extract the year or month from a date in pandas?
Once a column is datetime, use the .dt accessor: df['date'].dt.year, df['date'].dt.month, df['date'].dt.day_name(). These return Series you can group by or filter on. The .dt accessor only works on columns whose dtype is datetime64.
How do I filter rows by date range in pandas?
With a datetime column, compare it to date strings: df[df['date'] >= '2026-01-01']. To bound both ends use between: df[df['date'].between('2026-01-01', '2026-03-31')]. Setting the date column as the index also lets you slice ranges directly with df.loc['2026-01':'2026-03'].
What does resample do in pandas?
resample groups time-series data into regular time buckets such as days, weeks or months, then aggregates each bucket. df.resample('ME')['sales'].sum() gives monthly total sales when the index is a datetime. It is like groupby specifically for time periods.
What is NaT in pandas?
NaT means Not a Time and is the datetime equivalent of NaN, marking a missing or unparseable date. It appears when to_datetime is called with errors='coerce' on values it cannot read. Filter it out with df[df['date'].notna()] just like other missing values.

Want to Build Your Career in Data Analytics with AI?

Join CodeBegun and train with working industry engineers — View the Data Analytics curriculum

Apply for Demo Class →
Siva Prasad Galaba
Founder, CodeBegun · Staff Engineer

Founder of CodeBegun. 15+ years building Java systems at companies like Crunchyroll. Teaches Java, Spring Boot and system design the way the industry actually works, and mentors students through projects, mock interviews and placement preparation.

Technically reviewed by CodeBegun Technical TeamLast reviewed 16 July 2026 LinkedIn
Chat with us