Periods and Period Arithmetic
Timestamps vs periods
Section titled “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
Section titled “Period 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
Section titled “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
Section titled “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
Section titled “Quarterly 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)
Section titled “Converting 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
Section titled “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
Section titled “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
Section titled “🧪 Try It Yourself”Exercise 1 – Shift a Period by Integer Arithmetic
Section titled “Exercise 1 – Shift a Period by Integer Arithmetic”Exercise 2 – Build a Monthly PeriodIndex
Section titled “Exercise 2 – Build a Monthly PeriodIndex”Exercise 3 – Convert a Year Period Down to Its Start Month
Section titled “Exercise 3 – Convert a Year Period Down to Its Start Month”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.
pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading