# The distribution of Easter dates

Loosely speaking, in the Gregorian calendar, Easter falls on the first Sunday following the first full Moon on or after 21 March. There are various algorithms (Computus) which can be used to calculate its date, and the cycle of dates repeats every 5.7 million years. The following code produces a bar chart of the distribution of Easter dates using one of these algorithms. The earliest date that Easter can fall is 22 March; the latest is 25 April (this will next happen in 2038). The most frequent Easter date is 19 April.

from collections import defaultdict
import matplotlib.pyplot as plt

# The Gregorian Easter dates repeat every 5.7 million years.
PERIOD = 5_700_000

def get_easter_date(year):
"""Return the day and month of Easter in a requested year."""

# Use the anonymous algorithm, Anon., "To find Easter", Nature, p.487
# (20 April 1876) as described by Wikipedia:
# https://en.wikipedia.org/wiki/Computus#Algorithms
a = year % 19
b, c = divmod(year, 100)
d, e = divmod(b, 4)
f = (b + 8) // 25
g = (b - f + 1) // 3
h = (19*a + b - d - g + 15) % 30
i, k = divmod(c, 4)
l = (32 + 2*(e + i) - h - k) % 7
m = (a + 11*h + 22*l) // 451
month, day = divmod(h + l - 7*m + 114, 31)
day += 1
return day, month

# Count the easter dates across the whole cycle.
counts = defaultdict(int)
for year in range(1, PERIOD+1):
day, month = get_easter_date(year)
counts[(month, day)] += 1

# Sort the dates and get the percentages of Easters by date.
dates = sorted(counts)
percentages = dict((date, counts[date] / PERIOD * 100) for date in dates)

# Plot a bar chart
fig, ax = plt.subplots(figsize=(10, 5))
idx = range(len(counts))
ax.bar(idx, percentages.values())
ax.set_xticks(idx)
ax.set_xticklabels([str(day) for month, day in dates])
ax.set_ylabel('% of Easters')
ax.text(0, -0.4, 'March')
ax.text(10, -0.4, 'April')
plt.show()

Currently unrated