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/Date_of_Easter#Anonymous_Gregorian_algorithm 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()