feat: generate 2026-2040 liturgical calendar

Co-authored-by: rafa <rcalvotorrejon@gmail.com>
Signed-off-by: rafa <rcalvotorrejon@gmail.com>
This commit is contained in:
2026-08-17 05:33:09 -04:00
parent 5807151a99
commit 2713e13470
2 changed files with 21999 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env python3
"""Generate the reviewable civil-date lookup used by the daily Gospel shortcode.
Sources: CEE, "Tabla temporal de las principales celebraciones del Año
Litúrgico 2021-2044"; Normas Universales sobre el Año litúrgico.
"""
from datetime import date, timedelta
import json
from pathlib import Path
WEEKDAYS = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]
def easter(year):
a=year%19; b=year//100; c=year%100; d=b//4; e=b%4; f=(b+8)//25; g=(b-f+1)//3
h=(19*a+b-d-g+15)%30; i=c//4; k=c%4; l=(32+2*e+2*i-h-k)%7; m=(a+11*h+22*l)//451
return date(year,(h+l-7*m+114)//31,(h+l-7*m+114)%31+1)
def advent(year):
# Sunday falling from 27 November through 3 December.
d=date(year,11,27)
return d+timedelta(days=(6-d.weekday())%7)
def cycle(d):
start=d.year+1 if d>=advent(d.year) else d.year
return "ABC"[(start-2026)%3]
def special(d, pascha):
fixed={(1,1):"mary-mother",(1,6):"epiphany",(2,2):"presentation",
(3,19):"joseph",(3,25):"annunciation",(6,24):"john-baptist",
(6,29):"peter-paul",(7,22):"magdalene",(7,25):"james",
(8,6):"transfiguration",(8,15):"assumption",(11,1):"all-saints",
(11,2):"all-souls",(12,8):"immaculate",(12,25):"christmas"}
if (d.month,d.day) in fixed: return fixed[(d.month,d.day)]
offsets={-46:"ash-wednesday",-7:"palm-sunday",-3:"holy-thursday",-2:"good-friday",
0:"easter-sunday",1:"easter-monday",49:"pentecost",56:"trinity",60:"corpus-christi"}
return offsets.get((d-pascha).days)
def liturgical_day(d):
p=easter(d.year); a_this=advent(d.year); a_prev=advent(d.year-1)
sp=special(d,p)
if sp: return sp
if d>=a_this: return f"advent-{((d-a_this).days//7)+1}-{WEEKDAYS[d.weekday()]}"
# Christmas starts on the previous Advent's Dec 25 and runs through Baptism.
baptism=date(d.year,1,6)+timedelta(days=(6-date(d.year,1,6).weekday())%7 or 7)
if (d.month == 12 and d.day >= 25) or (d.month == 1 and d <= baptism):
return f"christmas-{WEEKDAYS[d.weekday()]}"
ash=p-timedelta(days=46)
if ash<=d<p:
return f"lent-{max(0,(d-ash).days//7)}-{WEEKDAYS[d.weekday()]}"
if p<d<=p+timedelta(days=49):
return f"easter-{((d-p).days-1)//7+1}-{WEEKDAYS[d.weekday()]}"
if d<ash:
first=baptism+timedelta(days=1)
return f"ordinary-{((d-first).days//7)+1}-{WEEKDAYS[d.weekday()]}"
# Number the resumed Ordinary Time backwards from the 34th week.
last_sunday=a_this-timedelta(days=7)
sunday=d+timedelta(days=(6-d.weekday())%7)
sunday_number=34-((last_sunday-sunday).days//7)
return f"ordinary-{sunday_number-1}-{WEEKDAYS[d.weekday()]}"
def main():
out={"schema":1,"range":{"from":"2026-01-01","to":"2040-12-31"},
"sources":["https://www.conferenciaepiscopal.es/tabla-temporal-celebraciones-ano-liturgico-2021-2044/"],"dates":{}}
d=date(2026,1,1); end=date(2040,12,31)
while d<=end:
out["dates"][d.isoformat()]={"key":liturgical_day(d),"cycle":cycle(d)}
d+=timedelta(days=1)
path=Path("data/evangelio-diario/calendario-liturgico-2026-2040.json")
path.write_text(json.dumps(out,ensure_ascii=False,indent=2)+"\n",encoding="utf-8")
print(f"wrote {len(out['dates'])} dates")
if __name__=="__main__": main()