grant-radar / src /analyzer /utils /dates.py
Riley Coleman
feat: add PDF & supporting materials integration to context
bfcc872
Raw
History Blame Contribute Delete
2.16 kB
"""
utils/dates.py — Date parsing and formatting utilities
Functions:
- parse_date(s): Parse common date formats to datetime
- format_date(s): Format date to readable string
"""
from __future__ import annotations
from datetime import datetime
from typing import Any, Optional
def parse_date(s: Any) -> Optional[datetime]:
"""
Parse common date formats to datetime object.
Supports:
- ISO 8601: 2024-12-31T23:59:59
- Date only: 2024-12-31
- UK format: 31/12/2024
Args:
s: Date string or datetime object
Returns:
datetime object or None if parsing fails
"""
if not s:
return None
if isinstance(s, datetime):
return s
# Try common formats
s_str = str(s)
# ISO 8601 with time: 2024-12-31T23:59:59
if 'T' in s_str and len(s_str) >= 19:
try:
return datetime.strptime(s_str[:19], "%Y-%m-%dT%H:%M:%S")
except Exception:
pass
# ISO 8601 date only: 2024-12-31
if len(s_str) >= 10 and s_str[4:5] == '-' and s_str[7:8] == '-':
try:
return datetime.strptime(s_str[:10], "%Y-%m-%d")
except Exception:
pass
# UK format: 31/12/2024
if '/' in s_str and len(s_str) >= 10:
try:
return datetime.strptime(s_str[:10], "%d/%m/%Y")
except Exception:
pass
return None
def format_date(s: Any, *, include_time: bool = False) -> str:
"""
Format date to human-readable string.
Args:
s: Date string, datetime object, or None
include_time: If True, include time if available
Returns:
Formatted date string or "—" if parsing fails
Examples:
>>> format_date("2024-12-31")
'2024-12-31'
>>> format_date("2024-12-31T14:30:00", include_time=True)
'2024-12-31 14:30:00'
"""
d = parse_date(s)
if not d:
return str(s) if s else "—"
# Auto-detect if time should be included
has_time = d.hour or d.minute or d.second
if include_time or has_time:
return d.strftime("%Y-%m-%d %H:%M:%S")
else:
return d.strftime("%Y-%m-%d")