Timestamps vs periods
A Timestamp is an instant — one exact point in time. A Period is a span —
"the whole month of March 2024" or "fiscal Q4 2024." Payroll, budgeting, and
reporting usually think in periods, not instants, so pandas gives Period its own
type instead of forcing you to fake spans with pairs of timestamps.
import pandas as pd
p = pd.Period("2024", freq="Y-DEC")
print(p) # the whole year 2024Period arithmetic
Adding or subtracting an integer shifts the period by that many units of its own frequency — no need to think in days:
print(p + 5) # 2029
print(p - 2) # 2022
q1 = pd.Period("2024", freq="Y-DEC")
q2 = pd.Period("2027", freq="Y-DEC")
print(q2 - q1) # <3 * YearEnds: month=12>Subtracting two periods of the same frequency gives you the number of periods
between them — like subtracting two dates gives you a timedelta.
PeriodIndex and period_range
periods = pd.period_range("2024-01", "2024-06", freq="M")
print(periods)
ts = pd.Series(range(6), index=periods)
print(ts)Converting frequency with asfreq
asfreq re-expresses a period at a different granularity. Since a year contains
months, you must say whether you want the start or end sub-period:
p = pd.Period("2024", freq="Y-JUN") # fiscal year ending in June
print(p.asfreq("M", how="start")) # 2023-07 — the fiscal year begins in July
print(p.asfreq("M", how="end")) # 2024-06 — and ends in JuneQuarterly periods
Quarterly reporting is usually anchored to a fiscal year end. Q-DEC means quarters
line up with a December year end (a normal calendar quarter):
q = pd.Period("2024Q4", freq="Q-DEC")
print(q)
print(q.asfreq("D", how="start")) # first day of the quarter
print(q.asfreq("D", how="end")) # last day of the quarterConverting timestamps to periods (and back)
dates = pd.date_range("2024-01-01", periods=3, freq="ME")
ts = pd.Series(range(3), index=dates)
pts = ts.to_period() # timestamps -> periods
print(pts)
print(pts.to_timestamp()) # periods -> timestamps (start of period, by default)Common pitfalls
- A timestamp belongs to exactly one period for a given frequency — but the same
period can repeat (e.g. two dates in January both map to
2024-01). Period("Aug-2011", "M").asfreq("A-JUN")maps August into the next fiscal year — frequency conversion depends on where the fiscal year boundary falls, not just the date.to_timestamp()returns the start of the period unless you passhow="end".
Visualize it
flowchart LR A["Timestamp
'2024-03-15 10:00'"] -->|"to_period()"| B["Period('2024-03', 'M')
the whole month"] B -->|"asfreq('D', how='start')"| C["First day: 2024-03-01"] B -->|"asfreq('D', how='end')"| D["Last day: 2024-03-31"] B -->|"asfreq('Y-DEC')"| E["Period('2024', 'Y-DEC')
the whole year"]
🧪 Try It Yourself
Exercise 1 – Shift a Period by Integer Arithmetic
Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.
Press Run to see what your code prints.Exercise 2 – Build a Monthly PeriodIndex
Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.
Press Run to see what your code prints.Exercise 3 – Convert a Year Period Down to Its Start Month
Tab indents. Press Escape, then Tab, to leave the editor. Control plus Enter runs the code; Control plus Shift plus Enter submits it.
Press Run to see what your code prints.Check your understanding
What is the difference between a Timestamp and a Period?
Payroll and reporting think in spans, which is why pandas gives Period its own type.
Show answer
A — A Timestamp is one exact instant, a Period is a span such as a whole month — Payroll and reporting think in spans, which is why pandas gives Period its own type.
For p = pd.Period("2024", freq="Y-DEC"), what are p + 5 and p - 2?
Adding an integer shifts the period by that many units of its own frequency, here years.
Show answer
A — 2029 and 2022 — Adding an integer shifts the period by that many units of its own frequency, here years.
For a fiscal year p = pd.Period("2024", freq="Y-JUN"), what does p.asfreq("M", how="start") return?
A fiscal year ending in June 2024 began in July 2023. how="end" would give 2024-06.
Show answer
B — 2023-07 — A fiscal year ending in June 2024 began in July 2023. how="end" would give 2024-06.
What does pts.to_timestamp() return by default for each period?
to_timestamp returns the start of each period unless you pass how="end".
Show answer
A — The start of the period — to_timestamp returns the start of each period unless you pass how="end".
Next
Periods describe fixed spans — Resampling and Frequency Conversion shows how to actually convert an irregular or high-frequency series into those spans, with real aggregation.