mirror of
https://github.com/eggent-ai/eggent.git
synced 2026-03-07 18:13:07 +00:00
125 lines
3.2 KiB
Python
125 lines
3.2 KiB
Python
"""Date utilities for last30days skill."""
|
|
|
|
from datetime import datetime, timedelta, timezone
|
|
from typing import Optional, Tuple
|
|
|
|
|
|
def get_date_range(days: int = 30) -> Tuple[str, str]:
|
|
"""Get the date range for the last N days.
|
|
|
|
Returns:
|
|
Tuple of (from_date, to_date) as YYYY-MM-DD strings
|
|
"""
|
|
today = datetime.now(timezone.utc).date()
|
|
from_date = today - timedelta(days=days)
|
|
return from_date.isoformat(), today.isoformat()
|
|
|
|
|
|
def parse_date(date_str: Optional[str]) -> Optional[datetime]:
|
|
"""Parse a date string in various formats.
|
|
|
|
Supports: YYYY-MM-DD, ISO 8601, Unix timestamp
|
|
"""
|
|
if not date_str:
|
|
return None
|
|
|
|
# Try Unix timestamp (from Reddit)
|
|
try:
|
|
ts = float(date_str)
|
|
return datetime.fromtimestamp(ts, tz=timezone.utc)
|
|
except (ValueError, TypeError):
|
|
pass
|
|
|
|
# Try ISO formats
|
|
formats = [
|
|
"%Y-%m-%d",
|
|
"%Y-%m-%dT%H:%M:%S",
|
|
"%Y-%m-%dT%H:%M:%SZ",
|
|
"%Y-%m-%dT%H:%M:%S%z",
|
|
"%Y-%m-%dT%H:%M:%S.%f%z",
|
|
]
|
|
|
|
for fmt in formats:
|
|
try:
|
|
return datetime.strptime(date_str, fmt).replace(tzinfo=timezone.utc)
|
|
except ValueError:
|
|
continue
|
|
|
|
return None
|
|
|
|
|
|
def timestamp_to_date(ts: Optional[float]) -> Optional[str]:
|
|
"""Convert Unix timestamp to YYYY-MM-DD string."""
|
|
if ts is None:
|
|
return None
|
|
try:
|
|
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
|
|
return dt.date().isoformat()
|
|
except (ValueError, TypeError, OSError):
|
|
return None
|
|
|
|
|
|
def get_date_confidence(date_str: Optional[str], from_date: str, to_date: str) -> str:
|
|
"""Determine confidence level for a date.
|
|
|
|
Args:
|
|
date_str: The date to check (YYYY-MM-DD or None)
|
|
from_date: Start of valid range (YYYY-MM-DD)
|
|
to_date: End of valid range (YYYY-MM-DD)
|
|
|
|
Returns:
|
|
'high', 'med', or 'low'
|
|
"""
|
|
if not date_str:
|
|
return 'low'
|
|
|
|
try:
|
|
dt = datetime.strptime(date_str, "%Y-%m-%d").date()
|
|
start = datetime.strptime(from_date, "%Y-%m-%d").date()
|
|
end = datetime.strptime(to_date, "%Y-%m-%d").date()
|
|
|
|
if start <= dt <= end:
|
|
return 'high'
|
|
elif dt < start:
|
|
# Older than range
|
|
return 'low'
|
|
else:
|
|
# Future date (suspicious)
|
|
return 'low'
|
|
except ValueError:
|
|
return 'low'
|
|
|
|
|
|
def days_ago(date_str: Optional[str]) -> Optional[int]:
|
|
"""Calculate how many days ago a date is.
|
|
|
|
Returns None if date is invalid or missing.
|
|
"""
|
|
if not date_str:
|
|
return None
|
|
|
|
try:
|
|
dt = datetime.strptime(date_str, "%Y-%m-%d").date()
|
|
today = datetime.now(timezone.utc).date()
|
|
delta = today - dt
|
|
return delta.days
|
|
except ValueError:
|
|
return None
|
|
|
|
|
|
def recency_score(date_str: Optional[str], max_days: int = 30) -> int:
|
|
"""Calculate recency score (0-100).
|
|
|
|
0 days ago = 100, max_days ago = 0, clamped.
|
|
"""
|
|
age = days_ago(date_str)
|
|
if age is None:
|
|
return 0 # Unknown date gets worst score
|
|
|
|
if age < 0:
|
|
return 100 # Future date (treat as today)
|
|
if age >= max_days:
|
|
return 0
|
|
|
|
return int(100 * (1 - age / max_days))
|