From 6b6e038b671a195ac8194a3c4e9679159c747e12 Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Sat, 21 Oct 2023 22:58:44 +0100 Subject: [PATCH] Add time to some events --- agenda/__init__.py | 12 ++++++++---- agenda/types.py | 43 +++++++++++++++++++++++++++++++++++++++++-- templates/index.html | 4 ++-- web_view.py | 19 ++----------------- 4 files changed, 53 insertions(+), 25 deletions(-) diff --git a/agenda/__init__.py b/agenda/__init__.py index 4d9a4b4..8a5908e 100644 --- a/agenda/__init__.py +++ b/agenda/__init__.py @@ -269,6 +269,10 @@ def get_us_holidays(input_date: date) -> list[Event]: ] +def as_date(d: date | datetime) -> date: + return d.date() if isinstance(d, datetime) else d + + def get_conferences(input_date: date, filepath: str) -> List[Event]: """Read conferences from a YAML file and return a list of Event objects.""" with open(filepath, "r") as f: @@ -279,7 +283,7 @@ def get_conferences(input_date: date, filepath: str) -> List[Event]: event_date = conf["start"] # Skip the conference if it is before the input date. - if event_date < input_date: + if as_date(event_date) < input_date: continue event = Event( name="conference", @@ -337,7 +341,7 @@ def get_accommodation(from_date: date, filepath: str) -> list[Event]: ) from_date = item["from"] to_date = item["to"] - nights = (to_date - from_date).days + nights = (to_date.date() - from_date.date()).days night_str = f"{nights} nights" if nights != 1 else "1 night" checkin = Event( date=from_date, @@ -359,7 +363,7 @@ def get_travel(from_date: date, method: str, filepath: str) -> list[Event]: """Get travel events.""" return [ Event( - date=item["depart"].date(), + date=item["depart"], name="transport", title=f'{method} from {item["from"]} to {item["to"]}', url=item.get("url"), @@ -441,7 +445,7 @@ def get_data(now: datetime) -> dict[str, str | object]: ) events.append(next_up_series) - events.sort(key=operator.attrgetter("date")) + events.sort(key=operator.attrgetter("as_datetime")) reply["events"] = events diff --git a/agenda/types.py b/agenda/types.py index 026f2ff..a668a64 100644 --- a/agenda/types.py +++ b/agenda/types.py @@ -1,7 +1,8 @@ """Types.""" import dataclasses -from datetime import date +import datetime +from datetime import date, timezone @dataclasses.dataclass @@ -9,6 +10,44 @@ class Event: """Event.""" name: str - date: date + date: date | datetime.datetime title: str | None = None url: str | None = None + + @property + def as_datetime(self) -> datetime.datetime: + """Date/time of event.""" + d = self.date + t0 = datetime.datetime.min.time() + return ( + d + if isinstance(d, datetime.datetime) + else datetime.datetime.combine(d, t0).replace(tzinfo=timezone.utc) + ) + + @property + def as_date(self) -> datetime.date: + """Date of event.""" + return ( + self.date.date() if isinstance(self.date, datetime.datetime) else self.date + ) + + def delta_days(self, today: datetime.date) -> str: + """Return number of days from today as a string.""" + delta = (self.as_date - today).days + + match delta: + case 0: + return "today" + case 1: + return "1 day" + case _: + return f"{delta:,d} days" + + @property + def display_date(self) -> str: + """Date for display on web page.""" + if isinstance(self.date, datetime.datetime): + return self.date.strftime("%a, %d, %b %Y %H:%M %z") + else: + return self.date.strftime("%a, %d, %b %Y") diff --git a/templates/index.html b/templates/index.html index 5bdf5e3..8b4d99b 100644 --- a/templates/index.html +++ b/templates/index.html @@ -52,7 +52,7 @@ {% for event in events %} - {{event.date.strftime("%a, %d, %b %Y")}} + {{event.display_date}} {% if event.url %}{% endif %} @@ -61,7 +61,7 @@ {% if event.url %}{% endif %} - {{ days(event.date) }} + {{ event.delta_days(today) }} {% endfor %} diff --git a/web_view.py b/web_view.py index 3314156..1bd66e7 100755 --- a/web_view.py +++ b/web_view.py @@ -2,11 +2,10 @@ """Web page to show upcoming events.""" -import functools import inspect import sys import traceback -from datetime import date, datetime +from datetime import datetime import flask import werkzeug @@ -45,27 +44,13 @@ def exception_handler(e: werkzeug.exceptions.InternalServerError) -> tuple[str, ) -def delta_days(today: date, when: date) -> str: - """Return number of days from today as a string.""" - delta = (when - today).days - - match delta: - case 0: - return "today" - case 1: - return "1 day" - case _: - return f"{delta:,d} days" - - @app.route("/") def index() -> str: """Index page.""" now = datetime.now() data = get_data(now) - days = functools.partial(delta_days, now.date()) - return flask.render_template("index.html", days=days, **data) + return flask.render_template("index.html", today=now.date(), **data) if __name__ == "__main__":