agent skill · summarization · pandas
Fiscal Year and Quarter Calculations
Add fiscal year and fiscal quarter columns to dated transaction data for any non-calendar year-end (e.g., federal government October-September), so every later summary groups on the same fiscal periods.
When to use this skill
- Your organization’s fiscal year does not match the calendar year — federal government (Oct 1 to Sep 30), many state and local governments (Jul 1 to Jun 30), UK/Japan (Apr 1 to Mar 31).
- You are about to summarize transactions “by quarter” or “by fiscal year” and the raw file only has a transaction date.
- You inherited a workbook full of nested IF formulas that translate months into fiscal quarters, and you want one calculation you can trust and reuse.
The core idea: compute Fiscal_Year and Fiscal_Quarter once as columns on the detail data. Every pivot, groupby, and report after that just uses those columns — no formula ever gets re-derived.
Inputs it expects
- A DataFrame with one row per transaction (journal entries, payments, receipts, holdings).
- A date column (
Posting_Datebelow) that pandas can parse — Excel dates,YYYY-MM-DDstrings, etc. - The month your fiscal year ends in (September for federal, June for many state/local governments). That’s the only setting you need.
- An amount column if you plan to summarize (
Amountbelow).
Steps
- Convert the date column with
pd.to_datetime— do this first, and check for unparseable dates. - Pick the pandas frequency code for your year-end month:
Q-SEP/Y-SEPfor a September 30 year-end,Q-JUN/Y-JUNfor June 30,Q-MAR/Y-MARfor March 31. (Older pandas versions spell the annual codeA-SEP.) - Add
Fiscal_YearandFiscal_Quartercolumns using that frequency. By convention the fiscal year is named for the year it ends in (October 2025 falls in FY2026 for a September year-end). - Spot-check the boundary months: the first month of the fiscal year should show Q1 of the next fiscal year label, and the last month should show Q4.
- Group by the new columns for your summary.
Code
import pandas as pd
# Detail transactions with a posting date
df = pd.DataFrame({
'Posting_Date': ['2025-10-15', '2026-01-20', '2026-04-10', '2026-07-05', '2026-09-30'],
'Fund': ['General', 'General', 'Capital', 'General', 'Capital'],
'Amount': [125000.00, 98000.00, 245000.00, 87500.00, 132000.00],
})
df['Posting_Date'] = pd.to_datetime(df['Posting_Date'])
# Federal fiscal year: October 1 - September 30 (year-end month = SEP)
# For a June 30 year-end use 'Q-JUN' / 'Y-JUN'; March 31 use 'Q-MAR' / 'Y-MAR'.
df['Fiscal_Year'] = df['Posting_Date'].dt.to_period('Y-SEP').dt.year
df['Fiscal_Quarter'] = pd.PeriodIndex(df['Posting_Date'], freq='Q-SEP').strftime('Q%q')
print(df)
# October 2025 -> FY2026 Q1; September 2026 -> FY2026 Q4
# Reuse the columns in any summary
quarterly_summary = (
df.groupby(['Fiscal_Year', 'Fiscal_Quarter'])['Amount']
.agg(Total='sum', Count='count', Average='mean')
)
print(quarterly_summary)
Validation (control totals)
- Row count unchanged: adding the two columns must not add or drop rows —
len(df)before equalslen(df)after. - Grand total unchanged:
df['Amount'].sum()on the detail must equalquarterly_summary['Total'].sum()to the penny. Every row lands in exactly one fiscal quarter, so the summary must tie out. - No unassigned periods:
df['Fiscal_Year'].isna().sum()anddf['Fiscal_Quarter'].isna().sum()should both be 0. A blank fiscal period means a date failed to parse. - Boundary check: filter one transaction from the first month of the fiscal year (e.g., October for a September year-end) and confirm it shows Q1 of the correct fiscal year.
Exceptions to surface
- Rows where
pd.to_datetime(..., errors='coerce')producedNaT— the original date text was unparseable and a human must decide the real date. - Transactions dated outside the expected fiscal range (e.g., a “FY2026” file containing dates from FY2024) — likely prior-period adjustments or data entry errors.
- Dates exactly on the fiscal year boundary (Sep 30 vs. Oct 1) when the source system’s cutoff practices are unclear — confirm which fiscal year the accounting records assign them to.
- Any row where the fiscal year derived from the date disagrees with a fiscal-year field already present in the source file.