150 lines
3.9 KiB
Python
150 lines
3.9 KiB
Python
"""Types."""
|
|
|
|
import datetime
|
|
from dataclasses import dataclass
|
|
|
|
from . import utils
|
|
from .types import DateOrDateTime, StrDict
|
|
|
|
emojis = {
|
|
"market": "🧺",
|
|
"us_presidential_election": "🗳️🇺🇸",
|
|
"bus_route_closure": "🚌❌",
|
|
"meetup": "👥",
|
|
"dinner": "🍷",
|
|
"party": "🍷",
|
|
"ba_voucher": "✈️",
|
|
"accommodation": "🏨", # alternative: 🧳
|
|
"flight": "✈️",
|
|
"conference": "🎤",
|
|
"rocket": "🚀",
|
|
"birthday": "🎈",
|
|
"waste_schedule": "🗑️",
|
|
"economist": "📰",
|
|
"running": "🏃",
|
|
"critical_mass": "🚴",
|
|
"trip": "🧳",
|
|
"hackathon": "💻",
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class Event:
|
|
"""Event."""
|
|
|
|
name: str
|
|
date: DateOrDateTime
|
|
end_date: DateOrDateTime | None = None
|
|
title: str | None = None
|
|
url: str | None = None
|
|
going: bool | None = None
|
|
|
|
@property
|
|
def as_datetime(self) -> datetime.datetime:
|
|
"""Date/time of event."""
|
|
return utils.as_datetime(self.date)
|
|
|
|
@property
|
|
def has_time(self) -> bool:
|
|
"""Event has a time associated with it."""
|
|
return isinstance(self.date, datetime.datetime)
|
|
|
|
@property
|
|
def as_date(self) -> datetime.date:
|
|
"""Date of event."""
|
|
return (
|
|
self.date.date() if isinstance(self.date, datetime.datetime) else self.date
|
|
)
|
|
|
|
@property
|
|
def end_as_date(self) -> datetime.date:
|
|
"""Date of event."""
|
|
return (
|
|
(
|
|
self.end_date.date()
|
|
if isinstance(self.end_date, datetime.datetime)
|
|
else self.end_date
|
|
)
|
|
if self.end_date
|
|
else self.as_date
|
|
)
|
|
|
|
@property
|
|
def display_time(self) -> str | None:
|
|
"""Time for display on web page."""
|
|
return (
|
|
self.date.strftime("%H:%M")
|
|
if isinstance(self.date, datetime.datetime)
|
|
else None
|
|
)
|
|
|
|
@property
|
|
def display_timezone(self) -> str | None:
|
|
"""Timezone for display on web page."""
|
|
return (
|
|
self.date.strftime("%z")
|
|
if isinstance(self.date, datetime.datetime)
|
|
else None
|
|
)
|
|
|
|
def display_duration(self) -> str | None:
|
|
"""Duration for display."""
|
|
if self.end_as_date != self.as_date or not self.has_time:
|
|
return None
|
|
|
|
assert isinstance(self.date, datetime.datetime)
|
|
assert isinstance(self.end_date, datetime.datetime)
|
|
|
|
secs: int = int((self.end_date - self.date).total_seconds())
|
|
|
|
hours: int = secs // 3600
|
|
mins: int = (secs % 3600) // 60
|
|
|
|
if mins == 0:
|
|
return f"{hours:d}h"
|
|
if hours == 0:
|
|
return f"{mins:d} mins"
|
|
|
|
return f"{hours:d}h {mins:02d} mins"
|
|
|
|
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")
|
|
|
|
@property
|
|
def display_title(self) -> str:
|
|
"""Name for display."""
|
|
return self.title or self.name
|
|
|
|
@property
|
|
def emoji(self) -> str | None:
|
|
"""Emoji."""
|
|
if self.title == "LHG Run Club":
|
|
return "🏃🍻"
|
|
return emojis.get(self.name)
|
|
|
|
@property
|
|
def title_with_emoji(self) -> str | None:
|
|
"""Title with optional emoji at the start."""
|
|
title = self.title or self.name
|
|
if title is None:
|
|
return None
|
|
emoji = self.emoji
|
|
return f"{emoji} {title}" if emoji else title
|