Support inexact conference dates

Closes: #188
This commit is contained in:
Edward Betts 2026-06-22 09:25:51 +01:00
parent 14f5baf77c
commit 098c7e4447
9 changed files with 464 additions and 66 deletions

View file

@ -7,7 +7,6 @@ import hashlib
import importlib
import inspect
import json
import operator
import os.path
import sys
import time
@ -26,6 +25,7 @@ from authlib.integrations.flask_client import OAuth
from werkzeug.middleware.proxy_fix import ProxyFix
import agenda.data
import agenda.conference
import agenda.error_mail
import agenda.fx
import agenda.holidays
@ -380,18 +380,18 @@ def build_conference_list() -> list[StrDict]:
conference_trip_lookup[key] = trip
for conf in items:
conf["start_date"] = agenda.utils.as_date(conf["start"])
conf["end_date"] = agenda.utils.as_date(conf["end"])
conf.update(agenda.conference.validate_conference_date_fields(conf))
price = conf.get("price")
if price:
conf["price"] = decimal.Decimal(price)
key = (conf["start"], conf["name"])
if this_trip := conference_trip_lookup.get(key):
conf["linked_trip"] = this_trip
if "start" in conf:
key = (conf["start"], conf["name"])
if this_trip := conference_trip_lookup.get(key):
conf["linked_trip"] = this_trip
items.sort(key=operator.itemgetter("start_date"))
items.sort(key=lambda item: item["sort_date"])
return items
@ -442,7 +442,7 @@ def _conference_description(conf: StrDict) -> str:
def build_conference_timeline(
current: list[StrDict], future: list[StrDict], today: date, days: int = 90
) -> dict | None:
) -> dict[str, typing.Any] | None:
"""Build data for a Gantt-style timeline of upcoming conferences."""
timeline_start = today
timeline_end = today + timedelta(days=days)
@ -450,7 +450,9 @@ def build_conference_timeline(
visible = [
c
for c in (current + future)
if c["start_date"] <= timeline_end and c["end_date"] >= today
if c["has_exact_dates"]
and c["start_date"] <= timeline_end
and c["end_date"] >= today
]
if not visible:
return None
@ -500,7 +502,9 @@ def build_conference_timeline(
d = today.replace(day=1)
while d <= timeline_end:
off = max((d - timeline_start).days, 0)
months.append({"label": d.strftime("%b %Y"), "left_pct": round(off / days * 100, 2)})
months.append(
{"label": d.strftime("%b %Y"), "left_pct": round(off / days * 100, 2)}
)
# advance to next month
d = (d.replace(day=28) + timedelta(days=4)).replace(day=1)
@ -525,6 +529,8 @@ def build_conference_ical(items: list[StrDict]) -> bytes:
generated = datetime.now(tz=timezone.utc)
for conf in items:
if not conf["has_exact_dates"]:
continue
start_date = agenda.utils.as_date(conf["start"])
end_date = agenda.utils.as_date(conf["end"])
end_exclusive = end_date + timedelta(days=1)
@ -556,9 +562,13 @@ def conference_list() -> str:
current = [
conf
for conf in items
if conf["start_date"] <= today and conf["end_date"] >= today
if conf["has_exact_dates"]
and conf["start_date"] <= today
and conf["end_date"] >= today
]
future = [
conf for conf in items if conf not in current and conf["latest_date"] >= today
]
future = [conf for conf in items if conf["start_date"] > today]
timeline = build_conference_timeline(current, future, today)
@ -579,7 +589,7 @@ def past_conference_list() -> str:
today = date.today()
return flask.render_template(
"conference_list.html",
past=[conf for conf in build_conference_list() if conf["end_date"] < today],
past=[conf for conf in build_conference_list() if conf["latest_date"] < today],
today=today,
get_country=agenda.get_country,
fx_rate=agenda.fx.get_rates(app.config),