import datetime

This commit is contained in:
Edward Betts 2024-01-10 13:06:29 +00:00
parent 199eb82bce
commit 82de51109f

View file

@ -1,8 +1,8 @@
"""Types.""" """Types."""
import datetime
import typing import typing
from dataclasses import dataclass, field from dataclasses import dataclass, field
from datetime import date, datetime, timezone
from pycountry.db import Country from pycountry.db import Country
@ -10,13 +10,14 @@ import agenda
from agenda import format_list_with_ampersand from agenda import format_list_with_ampersand
StrDict = dict[str, typing.Any] StrDict = dict[str, typing.Any]
DateOrDateTime = datetime.datetime | datetime.date
def as_date(d: datetime | date) -> date: def as_date(d: DateOrDateTime) -> datetime.date:
"""Convert datetime to date.""" """Convert datetime to date."""
if isinstance(d, datetime): if isinstance(d, datetime.datetime):
return d.date() return d.date()
assert isinstance(d, date) assert isinstance(d, datetime.date)
return d return d
@ -24,7 +25,7 @@ def as_date(d: datetime | date) -> date:
class Trip: class Trip:
"""Trip.""" """Trip."""
start: date start: datetime.date
travel: list[StrDict] = field(default_factory=list) travel: list[StrDict] = field(default_factory=list)
accommodation: list[StrDict] = field(default_factory=list) accommodation: list[StrDict] = field(default_factory=list)
conferences: list[StrDict] = field(default_factory=list) conferences: list[StrDict] = field(default_factory=list)
@ -38,21 +39,21 @@ class Trip:
) )
@property @property
def end(self) -> date | None: def end(self) -> datetime.date | None:
"""End date for trip.""" """End date for trip."""
max_conference_end = ( max_conference_end = (
max(as_date(item["end"]) for item in self.conferences) max(as_date(item["end"]) for item in self.conferences)
if self.conferences if self.conferences
else date.min else datetime.date.min
) )
assert isinstance(max_conference_end, date) assert isinstance(max_conference_end, datetime.date)
arrive = [item["arrive"].date() for item in self.travel if "arrive" in item] arrive = [item["arrive"].date() for item in self.travel if "arrive" in item]
travel_end = max(arrive) if arrive else date.min travel_end = max(arrive) if arrive else datetime.date.min
assert isinstance(travel_end, date) assert isinstance(travel_end, datetime.date)
max_date = max(max_conference_end, travel_end) max_date = max(max_conference_end, travel_end)
return max_date if max_date != date.min else None return max_date if max_date != datetime.date.min else None
@property @property
def countries(self) -> list[Country]: def countries(self) -> list[Country]:
@ -85,7 +86,7 @@ class Holiday:
name: str name: str
country: str country: str
date: date date: datetime.date
@dataclass @dataclass
@ -93,40 +94,42 @@ class Event:
"""Event.""" """Event."""
name: str name: str
date: date | datetime date: DateOrDateTime
end_date: date | datetime | None = None end_date: DateOrDateTime | None = None
title: str | None = None title: str | None = None
url: str | None = None url: str | None = None
going: bool | None = None going: bool | None = None
@property @property
def as_datetime(self) -> datetime: def as_datetime(self) -> datetime.datetime:
"""Date/time of event.""" """Date/time of event."""
d = self.date d = self.date
t0 = datetime.min.time() t0 = datetime.datetime.min.time()
return ( return (
d d
if isinstance(d, datetime) if isinstance(d, datetime.datetime)
else datetime.combine(d, t0).replace(tzinfo=timezone.utc) else datetime.datetime.combine(d, t0).replace(tzinfo=datetime.timezone.utc)
) )
@property @property
def has_time(self) -> bool: def has_time(self) -> bool:
"""Event has a time associated with it.""" """Event has a time associated with it."""
return isinstance(self.date, datetime) return isinstance(self.date, datetime.datetime)
@property @property
def as_date(self) -> date: def as_date(self) -> datetime.date:
"""Date of event.""" """Date of event."""
return self.date.date() if isinstance(self.date, datetime) else self.date return (
self.date.date() if isinstance(self.date, datetime.datetime) else self.date
)
@property @property
def end_as_date(self) -> date: def end_as_date(self) -> datetime.date:
"""Date of event.""" """Date of event."""
return ( return (
( (
self.end_date.date() self.end_date.date()
if isinstance(self.end_date, datetime) if isinstance(self.end_date, datetime.datetime)
else self.end_date else self.end_date
) )
if self.end_date if self.end_date
@ -136,14 +139,22 @@ class Event:
@property @property
def display_time(self) -> str | None: def display_time(self) -> str | None:
"""Time for display on web page.""" """Time for display on web page."""
return self.date.strftime("%H:%M") if isinstance(self.date, datetime) else None return (
self.date.strftime("%H:%M")
if isinstance(self.date, datetime.datetime)
else None
)
@property @property
def display_timezone(self) -> str | None: def display_timezone(self) -> str | None:
"""Timezone for display on web page.""" """Timezone for display on web page."""
return self.date.strftime("%z") if isinstance(self.date, datetime) else None return (
self.date.strftime("%z")
if isinstance(self.date, datetime.datetime)
else None
)
def delta_days(self, today: date) -> str: def delta_days(self, today: datetime.date) -> str:
"""Return number of days from today as a string.""" """Return number of days from today as a string."""
delta = (self.as_date - today).days delta = (self.as_date - today).days
@ -158,7 +169,7 @@ class Event:
@property @property
def display_date(self) -> str: def display_date(self) -> str:
"""Date for display on web page.""" """Date for display on web page."""
if isinstance(self.date, datetime): if isinstance(self.date, datetime.datetime):
return self.date.strftime("%a, %d, %b %Y %H:%M %z") return self.date.strftime("%a, %d, %b %Y %H:%M %z")
else: else:
return self.date.strftime("%a, %d, %b %Y") return self.date.strftime("%a, %d, %b %Y")