The Email That Broke Me
From: CFO To: Me Subject: Q2 Numbers Look Wrong Message: “Why does Q2 show January-March? Our fiscal year starts in July.”
My Internal Monologue: Because Excel thinks January is Q1 like a NORMAL PERSON.
My Actual Response: “I’ll fix it right away.”
The Problem: Excel Was Built for Calendar Years
Excel’s QUARTER() function assumes:
- Q1 = January-March
- Q2 = April-June
- Q3 = July-September
- Q4 = October-December
Great for most businesses!
Terrible for:
- Government agencies (July 1 year-end)
- Schools & universities (June 30 year-end)
- Nonprofits (various year-ends)
- International companies (April 1 year-end in Japan/UK)
- Any organization that doesn’t follow the calendar year
Translation: Excel assumes you’re “normal.”
If you’re not? Good luck.
The Excel “Solution” (I Use That Term Loosely)
Attempt #1: Nested IF Statements
=IF(MONTH(A2)>=7, "Q"&ROUNDUP((MONTH(A2)-6)/3,0), "Q"&ROUNDUP((MONTH(A2)+6)/3,0))
What This Does:
- If month ≥ July: Calculate quarter from July
- If month < July: Add 6 months, then calculate
Problems:
- Unreadable
- Error-prone
- Slow to write
- Impossible to audit 6 months later
Maintenance: “What does this formula do again?” ¯\_(ツ)_/¯
Attempt #2: Lookup Table
| Month | Fiscal_Quarter |
|-------|----------------|
| 1 | Q3 |
| 2 | Q3 |
| 3 | Q3 |
| 4 | Q4 |
| 5 | Q4 |
| 6 | Q4 |
| 7 | Q1 |
| 8 | Q1 |
| 9 | Q1 |
| 10 | Q2 |
| 11 | Q2 |
| 12 | Q2 |
Then: =VLOOKUP(MONTH(A2), Lookup_Table, 2, FALSE)
Problems:
- Extra worksheet/table required
- Another thing that can break
- Needs documentation
- Different fiscal years = different lookup tables
Scalability: “We need to support 5 different fiscal calendars…” cries in Excel
Attempt #3: Power Query (For the Brave)
Power Query can handle custom fiscal years!
Steps:
- Import data into Power Query
- Add custom column
- Write M language code:
= Date.QuarterOfYear(
Date.AddMonths([Date], -6)
)
Problems:
- Power Query learning curve
- Locked in Excel (can’t easily share logic)
- M language debugging = nightmare
- Refresh delays on large datasets
Collaboration: “Can you send me the Power Query code?” sends 500-line M script
Why Fiscal Years Are Actually Hard
It’s not just quarters. It’s everything:
Problem #1: Fiscal Year Calculation
Calendar Year: Easy
- Date: January 15, 2025
- Year: 2025
Fiscal Year (July 1 year-end): Confusing
- Date: January 15, 2025
- Fiscal Year: 2025 or 2024?
Answer: FY 2025 (because it’s July 2024 - June 2025)
But if the date was June 15, 2025:
- Fiscal Year: Still FY 2025
And if the date was July 15, 2025:
- Fiscal Year: FY 2026
My Brain:
Problem #2: Fiscal Quarter Calculation
July 1 Fiscal Year:
- Q1 = July, August, September
- Q2 = October, November, December
- Q3 = January, February, March
- Q4 = April, May, June
Excel: “January is Q1. Fight me.”
Problem #3: Year-Over-Year Comparisons
Task: Compare Q2 FY2025 vs Q2 FY2024
Excel Thinks:
- Q2 2025 = Apr-Jun 2025
- Q2 2024 = Apr-Jun 2024
Reality:
- Q2 FY2025 = Oct-Dec 2024
- Q2 FY2024 = Oct-Dec 2023
Result: Your comparison is completely wrong.
Enter Python: Fiscal Years Done Right
One Line. That’s It.
import pandas as pd
df['Date'] = pd.to_datetime(df['Date'])
# Calculate fiscal quarter (July 1 year-end)
df['Fiscal_Quarter'] = pd.PeriodIndex(df['Date'], freq='Q-JUN').strftime('Q%q')
# Done.
Result:
Date Fiscal_Quarter
2025-01-15 Q3
2025-04-20 Q4
2025-07-10 Q1
2025-10-05 Q2
Perfect!
How It Works
The Magic Parameter: freq='Q-JUN'
Translation: “Quarters ending in June”
Q-JAN= Quarters ending in January (Feb-Apr, May-Jul, Aug-Oct, Nov-Jan)Q-FEB= Quarters ending in FebruaryQ-MAR= Quarters ending in March (Apr-Jun, Jul-Sep, Oct-Dec, Jan-Mar) = Calendar year!- …
Q-JUN= Quarters ending in June (Jul-Sep, Oct-Dec, Jan-Mar, Apr-Jun) = Fiscal year (July 1 start)- …
Q-DEC= Quarters ending in December = Also calendar year
Your Organization Uses Different Fiscal Year?
Just change the ending month!
# April 1 fiscal year (Japan, UK)
df['Fiscal_Quarter'] = pd.PeriodIndex(df['Date'], freq='Q-MAR').strftime('Q%q')
# October 1 fiscal year (US Federal Government)
df['Fiscal_Quarter'] = pd.PeriodIndex(df['Date'], freq='Q-SEP').strftime('Q%q')
# Custom: February 28 year-end
df['Fiscal_Quarter'] = pd.PeriodIndex(df['Date'], freq='Q-FEB').strftime('Q%q')
One parameter change. That’s it.
Bonus: Fiscal Year Calculation
# Calculate fiscal year (July 1 year-end)
df['Fiscal_Year'] = df['Date'].dt.to_period('A-JUN').dt.year
Examples:
Date Fiscal_Year
2025-01-15 2025 # In FY 2025 (Jul 2024 - Jun 2025)
2025-06-30 2025 # Last day of FY 2025
2025-07-01 2026 # First day of FY 2026
2024-12-15 2025 # Also in FY 2025
Real-World Example: Monthly Expense Report by Fiscal Quarter
The Scenario
Task: Analyze expenses by fiscal quarter for government agency (July 1 year-end)
Data:
Date Expense_Type Amount
2024-07-15 Payroll 125000
2024-08-20 Supplies 15000
2024-10-05 Payroll 125000
2024-11-12 Equipment 45000
2025-01-10 Payroll 125000
2025-02-14 Travel 8000
2025-04-18 Payroll 125000
2025-05-22 Consulting 25000
Goal: Sum expenses by fiscal quarter
The Excel Way: Pain
Step 1: Add fiscal quarter column with formula
=IF(MONTH(A2)>=7, "Q"&ROUNDUP((MONTH(A2)-6)/3,0), "Q"&ROUNDUP((MONTH(A2)+6)/3,0))
Step 2: Copy formula down
Step 3: Create pivot table
Step 4: Group by fiscal quarter and expense type
Step 5: Format results
Time: 15 minutes
Errors: “Wait, why is October showing as Q2? It should be Q2… oh wait, I messed up the formula.”
The Python Way: Joy
import pandas as pd
# Read data
df = pd.read_excel('expenses.xlsx')
df['Date'] = pd.to_datetime(df['Date'])
# Calculate fiscal periods
df['Fiscal_Quarter'] = pd.PeriodIndex(df['Date'], freq='Q-JUN').strftime('Q%q')
df['Fiscal_Year'] = df['Date'].dt.to_period('A-JUN').dt.year
# Summarize by fiscal quarter
summary = df.groupby(['Fiscal_Year', 'Fiscal_Quarter', 'Expense_Type'])['Amount'].sum()
print(summary)
Output:
Fiscal_Year Fiscal_Quarter Expense_Type
2025 Q1 Payroll 125000
Supplies 15000
Q2 Equipment 45000
Payroll 125000
Q3 Payroll 125000
Travel 8000
Q4 Consulting 25000
Payroll 125000
Time: 30 seconds
Errors: Zero
Accuracy: Perfect
Advanced: Handling Partial Fiscal Years
Scenario: You started tracking expenses mid-year (October 2024)
Question: How much did we spend in Q1 and Q2 so far this fiscal year?
import pandas as pd
from datetime import datetime
# Read data
df = pd.read_excel('expenses.xlsx')
df['Date'] = pd.to_datetime(df['Date'])
# Current fiscal year
current_fy = pd.Period(datetime.now(), freq='A-JUN').year
# Filter to current fiscal year
df_fy = df[
df['Date'].dt.to_period('A-JUN').dt.year == current_fy
].copy()
# Calculate fiscal quarter
df_fy['Fiscal_Quarter'] = pd.PeriodIndex(df_fy['Date'], freq='Q-JUN').strftime('Q%q')
# Summary by quarter
quarterly_summary = df_fy.groupby('Fiscal_Quarter')['Amount'].sum()
print(f"Expenses for FY {current_fy}:")
print(quarterly_summary)
print(f"\nTotal FY {current_fy} to date: ${df_fy['Amount'].sum():,.2f}")
Output:
Expenses for FY 2025:
Fiscal_Quarter
Q1 140000
Q2 170000
Q3 133000
Q4 25000 # Partial (not complete yet)
Total FY 2025 to date: $468,000.00
Bonus: Month Numbers in Fiscal Calendar
Problem: I need month 1 = July, month 2 = August, …, month 12 = June
Solution:
# Calculate fiscal month (1-12, starting in July)
df['Fiscal_Month'] = ((df['Date'].dt.month - 7) % 12) + 1
Result:
Date Calendar_Month Fiscal_Month
2024-07-15 7 (July) 1
2024-08-20 8 (August) 2
2024-12-05 12 (December) 6
2025-01-10 1 (January) 7
2025-06-20 6 (June) 12
Perfect for:
- Budget vs. actual reporting (“We’re in month 8 of 12”)
- Fiscal month-over-month comparisons
- “Months remaining in fiscal year” calculations
The “Aha!” Moment
My director walked by my desk:
Director: “How long will the Q2 analysis take?”
Me (Old Way): “A few hours. Need to fix the fiscal quarter formulas, rebuild the pivot tables…”
Me (Python Way): “Already done. Sent it 5 minutes ago.”
Director: checks email “This is… really detailed. How did you do this so fast?”
Me: “Python handles fiscal years natively. One line of code.”
Director: “Can you show the rest of the team?”
Me: “Already scheduled a brown bag lunch session for next week.”
Director: “You’re getting a raise.”
(Okay, that last part didn’t happen, but a guy can dream!)
Common Fiscal Year Scenarios
Scenario #1: Government Agency (July 1 year-end)
df['Fiscal_Quarter'] = pd.PeriodIndex(df['Date'], freq='Q-JUN').strftime('Q%q')
df['Fiscal_Year'] = df['Date'].dt.to_period('A-JUN').dt.year
Scenario #2: UK/Japan (April 1 year-end)
df['Fiscal_Quarter'] = pd.PeriodIndex(df['Date'], freq='Q-MAR').strftime('Q%q')
df['Fiscal_Year'] = df['Date'].dt.to_period('A-MAR').dt.year
Scenario #3: US Federal Government (October 1 year-end)
df['Fiscal_Quarter'] = pd.PeriodIndex(df['Date'], freq='Q-SEP').strftime('Q%q')
df['Fiscal_Year'] = df['Date'].dt.to_period('A-SEP').dt.year
Scenario #4: Retail (February 1 year-end - avoids holiday season)
df['Fiscal_Quarter'] = pd.PeriodIndex(df['Date'], freq='Q-JAN').strftime('Q%q')
df['Fiscal_Year'] = df['Date'].dt.to_period('A-JAN').dt.year
The Bottom Line
Excel:
- Complex nested formulas
- Lookup tables
- Power Query learning curve
- Error-prone
- Hard to maintain
Python:
- One line of code
- Works for ANY fiscal year
- Easy to read
- Zero maintenance
- Portable (works across organizations)
Your Turn
Next time you need fiscal quarters:
df['Fiscal_Quarter'] = pd.PeriodIndex(df['Date'], freq='Q-JUN').strftime('Q%q')
That’s it. You’re done.
No more Excel gymnastics. No more nested IFs. No more lookup tables.
Just one line that actually works.
Try It Yourself
Want the complete working example with sample data? Download from GitHub
Have a fiscal year horror story? Share it in the comments! Let’s commiserate together.
Join the Discussion on Discord! -
Stuck with a weird fiscal calendar? Need help with date calculations? Join our Discord community!
Next time: “The Case of the Missing Millions: Tracking Down Rounding Errors” →