Source code for calendar_smith.utils
# src/calendar_smith/utils.py
import datetime
import re
[docs]
def parse_date_lenient(date_str: str) -> datetime.date:
"""Parse common date formats and reject ambiguous shorthand values."""
date_part = date_str.split('T')[0].split(' ')[0]
digits_only = re.sub(r'[^0-9]', '', date_part)
if len(digits_only) == 8 and date_part.isdigit():
return datetime.datetime.strptime(digits_only, "%Y%m%d").date()
normalized = re.sub(r'[./]', '-', date_part)
if '-' in normalized:
try:
return datetime.datetime.strptime(normalized, "%Y-%m-%d").date()
except ValueError:
pass
if len(digits_only) in (6, 7):
raise ValueError(
f"Ambiguous date '{date_str}' rejected. "
"Please use 8-digit YYYYMMDD or delimiters (YYYY-MM-DD)."
)
raise ValueError(f"Could not parse '{date_str}'. Expected YYYY-MM-DD or YYYYMMDD.")
[docs]
def ensure_date(date_input: str | datetime.date | None) -> datetime.date:
"""Convert a string, date, or ``None`` into a ``datetime.date``."""
if not date_input:
return datetime.date.today()
if isinstance(date_input, datetime.date):
return date_input
clean_input = str(date_input).strip()
try:
return datetime.date.fromisoformat(clean_input)
except ValueError:
return parse_date_lenient(clean_input)