Extensions to the standard Python datetime module
—
Computation of Easter Sunday dates using Western, Orthodox, and Julian calendar algorithms for any given year. Supports three different calculation methods based on historical and regional requirements.
def easter(year, method=EASTER_WESTERN):
"""
Calculate Easter date for a given year using specified method.
This implementation is based on algorithms by GM Arts and Claus Tondering,
derived from Ouding (1940) as quoted in "Explanatory Supplement to the
Astronomical Almanac" by P. Kenneth Seidelmann.
Parameters:
- year (int): Year for which to calculate Easter
- method (int, optional): Calculation method constant (default: EASTER_WESTERN)
Returns:
datetime.date: Easter Sunday date for the specified year
Raises:
ValueError: If year is outside valid range for the method
"""EASTER_JULIAN = 1 # Original Julian calendar calculation (valid after 326 AD)
EASTER_ORTHODOX = 2 # Orthodox method in Gregorian calendar (1583-4099)
EASTER_WESTERN = 3 # Western/Gregorian method (1583-4099) - defaultMethod Details:
from dateutil.easter import easter, EASTER_WESTERN, EASTER_ORTHODOX, EASTER_JULIAN
from datetime import date
# Calculate Easter for different years using Western method (default)
easter_2023 = easter(2023) # April 9, 2023
easter_2024 = easter(2024) # March 31, 2024
easter_2025 = easter(2025) # April 20, 2025
print(f"Easter 2023: {easter_2023}")
print(f"Easter 2024: {easter_2024}")
print(f"Easter 2025: {easter_2025}")from dateutil.easter import easter, EASTER_WESTERN, EASTER_ORTHODOX, EASTER_JULIAN
year = 2023
# Compare different methods for the same year
western_easter = easter(year, EASTER_WESTERN)
orthodox_easter = easter(year, EASTER_ORTHODOX)
julian_easter = easter(year, EASTER_JULIAN)
print(f"Western Easter {year}: {western_easter}") # April 9, 2023
print(f"Orthodox Easter {year}: {orthodox_easter}") # April 16, 2023
print(f"Julian Easter {year}: {julian_easter}") # April 16, 2023from dateutil.easter import easter
from datetime import date
def analyze_easter_dates(start_year, end_year):
"""Analyze Easter date patterns over a range of years."""
easter_dates = []
for year in range(start_year, end_year + 1):
easter_date = easter(year)
easter_dates.append((year, easter_date))
# Find earliest and latest Easter dates
earliest = min(easter_dates, key=lambda x: (x[1].month, x[1].day))
latest = max(easter_dates, key=lambda x: (x[1].month, x[1].day))
print(f"Easter date analysis ({start_year}-{end_year}):")
print(f"Earliest: {earliest[1]} in {earliest[0]}")
print(f"Latest: {latest[1]} in {latest[0]}")
return easter_dates
# Analyze Easter dates for a decade
easter_analysis = analyze_easter_dates(2020, 2030)from dateutil.easter import easter
from dateutil.relativedelta import relativedelta
from datetime import datetime
def get_easter_week_dates(year):
"""Get dates for entire Easter week."""
easter_sunday = easter(year)
# Calculate related dates
palm_sunday = easter_sunday - relativedelta(weeks=1)
maundy_thursday = easter_sunday - relativedelta(days=3)
good_friday = easter_sunday - relativedelta(days=2)
easter_monday = easter_sunday + relativedelta(days=1)
return {
'palm_sunday': palm_sunday,
'maundy_thursday': maundy_thursday,
'good_friday': good_friday,
'easter_sunday': easter_sunday,
'easter_monday': easter_monday
}
# Get Easter week dates for 2023
easter_week_2023 = get_easter_week_dates(2023)
for day_name, date_obj in easter_week_2023.items():
print(f"{day_name.replace('_', ' ').title()}: {date_obj}")from dateutil.easter import easter
from dateutil.relativedelta import relativedelta
def get_holiday_schedule(year):
"""Generate common Easter-related holidays for business calendar."""
easter_date = easter(year)
holidays = {
'good_friday': easter_date - relativedelta(days=2),
'easter_sunday': easter_date,
'easter_monday': easter_date + relativedelta(days=1),
}
return holidays
def is_easter_holiday(date_obj, year=None):
"""Check if a date is an Easter-related holiday."""
if year is None:
year = date_obj.year
holidays = get_holiday_schedule(year)
return date_obj in holidays.values()
# Example usage
from datetime import date
test_date = date(2023, 4, 7) # Good Friday 2023
print(f"Is {test_date} an Easter holiday? {is_easter_holiday(test_date)}")from dateutil.easter import easter, EASTER_WESTERN, EASTER_ORTHODOX
def compare_easter_methods(year_range):
"""Compare Western and Orthodox Easter dates over time."""
differences = []
for year in year_range:
western = easter(year, EASTER_WESTERN)
orthodox = easter(year, EASTER_ORTHODOX)
if western != orthodox:
day_diff = (orthodox - western).days
differences.append((year, western, orthodox, day_diff))
return differences
# Compare methods for recent years
recent_years = range(2020, 2031)
easter_differences = compare_easter_methods(recent_years)
print("Years where Western and Orthodox Easter differ:")
for year, western, orthodox, diff in easter_differences:
print(f"{year}: Western {western}, Orthodox {orthodox} ({diff} days difference)")The Easter calculation algorithms implement three different approaches:
All methods are based on the lunar cycle and astronomical calculations established by the Council of Nicaea in 325 AD, which defined Easter as the first Sunday after the first full moon occurring on or after the spring equinox.
from datetime import date
# Easter calculation function
def easter(year: int, method: int = EASTER_WESTERN) -> date: ...
# Method constants
EASTER_JULIAN: int = 1
EASTER_ORTHODOX: int = 2
EASTER_WESTERN: int = 3
# Parameter and return types
EasterMethod = int # One of the three method constants
EasterYear = int # Year for calculation (valid ranges depend on method)
EasterDate = date # Returned Easter dateInstall with Tessl CLI
npx tessl i tessl/pypi-python-dateutil