59 lines
1.5 KiB
Python
59 lines
1.5 KiB
Python
"""Utility functions."""
|
|
|
|
from datetime import date, datetime, timezone
|
|
|
|
|
|
def as_date(d: datetime | date) -> date:
|
|
"""Convert datetime to date."""
|
|
match d:
|
|
case datetime():
|
|
return d.date()
|
|
case date():
|
|
return d
|
|
case _:
|
|
raise TypeError(f"Unsupported type: {type(d)}")
|
|
|
|
|
|
def as_datetime(d: datetime | date) -> datetime:
|
|
"""Date/time of event."""
|
|
match d:
|
|
case datetime():
|
|
return d
|
|
case date():
|
|
return datetime.combine(d, datetime.min.time()).replace(tzinfo=timezone.utc)
|
|
case _:
|
|
raise TypeError(f"Unsupported type: {type(d)}")
|
|
|
|
|
|
def human_readable_delta(future_date: date) -> str | None:
|
|
"""
|
|
Calculate the human-readable time delta for a given future date.
|
|
|
|
Args:
|
|
future_date (date): The future date as a datetime.date object.
|
|
|
|
Returns:
|
|
str: Human-readable time delta.
|
|
"""
|
|
# Ensure the input is a future date
|
|
if future_date <= date.today():
|
|
return None
|
|
|
|
# Calculate the delta
|
|
delta = future_date - date.today()
|
|
|
|
# Convert delta to a more human-readable format
|
|
months, days = divmod(delta.days, 30)
|
|
weeks, days = divmod(days, 7)
|
|
|
|
# Formatting the output
|
|
parts = []
|
|
if months > 0:
|
|
parts.append(f"{months} month{'s' if months > 1 else ''}")
|
|
if weeks > 0:
|
|
parts.append(f"{weeks} week{'s' if weeks > 1 else ''}")
|
|
if days > 0:
|
|
parts.append(f"{days} day{'s' if days > 1 else ''}")
|
|
|
|
return " ".join(parts) if parts else None
|