Data SciencePractical workplace data tasks

Compare Diwali sales year on year by aligning to the festival

PK
Pankit Kumar
Sr. Data Scientist at Parexel (a Goldman Sachs–backed company) · 27 September 2026 · 6 min read
In this article (5 sections)

Related programme: the Data Science course (6 months; ₹1,30,000 (inclusive of GST) · EMI from ₹5,000/month).

The short answer

To compare festive sales across years, stop comparing October with October. Diwali moved from Thursday 31 October in 2024 to Monday 20 October in 2025, so a calendar-month comparison mixes build-up days, the festival and the post-festival lull in different proportions each year. Index every date by days from Diwali, compare the same window (for example 14 days before to 6 days after), and then adjust for weekday mix. In the synthetic example below, those three methods report 5.6%, 10.6% and 8.0% growth, and only the last matches the true 8%.

Where the dates come from

Take festival dates from an official list rather than memory or a web calendar. The Department of Personnel and Training publishes the holidays observed in central government offices each year: Diwali (Deepavali) is Thursday 31 October in the 2024 list, Monday 20 October in the 2025 list, and Sunday 8 November in the 2026 list. If your stores trade in several states, keep the state holiday calendars too, since closures and regional festivals differ.

Store the dates in a small table in your repository or workbook, one row per year, with the source link beside each row. The analysis then reads from that table instead of hard-coded dates.

A synthetic store with a known answer

To test a method, you need data where the right answer is known. The script builds daily sales for two festive seasons with an invented demand shape: a ten-day build-up peaking the day before Diwali, a quieter Diwali day, a four-day lull, and a weekday pattern where Saturday is the strongest day. Underlying growth is set to exactly 8% in 2025. Every rupee is synthetic.

python
import pandas as pd

# Diwali dates from the DoPT central government holiday lists (linked in the article).
DIWALI = {2024: pd.Timestamp("2024-10-31"), 2025: pd.Timestamp("2025-10-20")}

def festive_lift(offset):
    """Synthetic shape of festive demand around Diwali (offset in days)."""
    if -10 <= offset <= -1:
        return 1 + 0.15 * (offset + 11)        # builds from 1.15x to 2.5x
    if offset == 0:
        return 1.2                              # shops shut early on the day
    if 1 <= offset <= 4:
        return 0.6                              # post-festival lull
    return 1.0

WEEKDAY = [0.9, 0.9, 0.95, 0.95, 1.05, 1.25, 1.1]   # Monday..Sunday, synthetic

# Synthetic daily store sales, with true underlying growth of exactly 8% in 2025.
frames = []
for year, growth in ((2024, 1.00), (2025, 1.08)):
    days = pd.date_range(f"{year}-09-15", f"{year}-11-30")
    offset = (days - DIWALI[year]).days
    sales = [round(100000 * growth * WEEKDAY[d.weekday()] * festive_lift(o))
             for d, o in zip(days, offset)]
    frames.append(pd.DataFrame({"date": days, "year": year, "offset": offset, "sales": sales}))
daily = pd.concat(frames, ignore_index=True)

def yoy(a, b):
    return round((b / a - 1) * 100, 1)

# 1. The comparison usually asked for: October against October.
octo = daily[daily["date"].dt.month == 10].groupby("year")["sales"].sum()
print("October vs October:", yoy(octo[2024], octo[2025]), "%")

# 2. Aligned on Diwali: the same 21-day window, D-14 to D+6, in each year.
win = daily[daily["offset"].between(-14, 6)].groupby("year")["sales"].sum()
print("Diwali-aligned D-14..D+6:", yoy(win[2024], win[2025]), "%")

# 3. Aligned and weekday-balanced: compare each offset's sales divided by its weekday factor.
daily["adj"] = daily["sales"] / daily["date"].dt.weekday.map(dict(enumerate(WEEKDAY)))
adj = daily[daily["offset"].between(-14, 6)].groupby("year")["adj"].sum()
print("Aligned and weekday-adjusted:", yoy(adj[2024], adj[2025]), "%")

# Day-by-day view for the review deck: sales by offset, both years side by side.
side = daily[daily["offset"].between(-3, 3)].pivot(index="offset", columns="year", values="sales")
print(side.to_string())
assert abs(yoy(adj[2024], adj[2025]) - 8.0) < 0.05

Reading the three answers

October vs October: 5.6%. In 2024, October contained the whole build-up and Diwali itself, with the lull in November. In 2025, October also contained the lull and several ordinary days after it. The 2025 October total is dragged down by days that 2024's October never had. Nothing about the business changed; the calendar did.

Aligned on Diwali: 10.6%. Comparing the same 21 days relative to the festival removes most of the distortion, but it overshoots. In 2025 the two days before Diwali fell on a Saturday and a Sunday, the strongest weekdays, so the peak itself was bigger for a reason that has nothing to do with growth. The side-by-side table shows it: two days before Diwali was ₹2,11,500 in 2024 and ₹3,17,250 in 2025.

Aligned and weekday-adjusted: 8.0%. Dividing each day's sales by its weekday factor before summing removes the weekday effect, and the true growth reappears. In real data you do not know the weekday factors in advance; estimate them from ordinary, non-festive weeks, which is the subject of separate holiday and weekday effects in daily sales.

Presenting it to a sales head

Lead with one aligned chart: days from Diwali on the horizontal axis, one line per year. It explains the comparison without any statistics, and people immediately see the build-up and lull line up. Then give one growth number, the adjusted aligned figure, with the method in a single sentence underneath. Keep the October vs October figure out of the headline, but be ready with it, since someone will have calculated it already and will ask why yours is different.

MethodWhat it answersUse it for
Calendar monthHow did October go?Monthly MIS, targets, accounts
Aligned windowHow did the festive season go?Festive review, marketing spend
Aligned and weekday-adjustedUnderlying festive growthPlanning next year's stock and staffing

The calendar-month figure is not wrong; it answers a different question. Monthly targets and the accounts are set on months, so the monthly MIS should still report October as October.

Plan now for 2026

Diwali on 8 November 2026 moves the build-up into late October and early November. An October 2026 vs October 2025 comparison will therefore look weak, because October 2025 held the peak and October 2026 holds only the start of the build-up. Warn stakeholders before the October numbers arrive, set festive targets on the aligned window, and split monthly targets so that November carries more of the season than it did last year.

Other decisions to write down before the season: whether the window starts earlier for categories like gold and electronics, where demand builds around Dhanteras, whether online and store sales are aligned separately, and how days lost to closures or stock-outs are treated.

Aligning events, estimating seasonal effects and checking a method against data with a known answer are standard habits in forecasting work. Our Data Science programme covers them with Indian retail calendars, taught live online, with optional in-person labs at our Noida centre.

Frequently asked questions

When is Diwali in 2026?

The central government holiday list published by the Department of Personnel and Training shows Diwali (Deepavali) on Sunday, 8 November 2026. State holiday lists and regional observance can differ, so check the list for each state where you trade.

How many days before Diwali should the comparison window start?

Use your own data. Plot daily sales by days from Diwali for two or three past years and start the window where the rise begins. The 14 days used in this article suit the synthetic example only.

PK
Pankit Kumar
Lead Instructor, NeuraPath Academy

Pankit Kumar has 10 years in Data Science & AI, building and shipping production systems in regulated pharma and clinical environments. He is a freelance trainer at Boston Institute of Analytics, AnalytixLabs and Scaler, and has taught this material to thousands of working professionals.

This article is part of our Data Science programme — 6 months. From data foundations to machine learning, deep learning and deployment.

Explore Data Science
Counselling is free · no obligation

Not sure which programme fits?

Tell us your background and we will map it to the right entry point — including saying so when a cheaper programme is the better fit. A counsellor replies within one working day.