mirror of
https://github.com/wahyd4/hey-search.git
synced 2026-08-09 05:06:23 +10:00
74 lines
2.3 KiB
Python
74 lines
2.3 KiB
Python
"""Date extraction utilities for search engine result snippets."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from datetime import datetime, timezone, timedelta
|
|
|
|
_MONTHS = {
|
|
"jan": 1, "feb": 2, "mar": 3, "apr": 4, "may": 5, "jun": 6,
|
|
"jul": 7, "aug": 8, "sep": 9, "oct": 10, "nov": 11, "dec": 12,
|
|
}
|
|
|
|
|
|
def parse_date_from_text(text: str) -> str:
|
|
"""
|
|
Try to extract a publication date from the start of a snippet text.
|
|
|
|
Returns an ISO 8601 date string (YYYY-MM-DD) or empty string if not found.
|
|
|
|
Handles:
|
|
- Relative: "3 hours ago", "2 days ago", "1 week ago", "5 months ago"
|
|
- MDY: "Jan 15, 2024" or "January 15, 2024"
|
|
- DMY: "15 Jan 2024" or "15 January 2024"
|
|
- ISO: "2024-01-15"
|
|
"""
|
|
if not text:
|
|
return ""
|
|
|
|
text = text.strip()
|
|
now = datetime.now(timezone.utc)
|
|
|
|
# Relative: "X unit(s) ago"
|
|
m = re.match(r"^(\d+)\s+(second|minute|hour|day|week|month|year)s?\s+ago", text, re.IGNORECASE)
|
|
if m:
|
|
n = int(m.group(1))
|
|
unit = m.group(2).lower()
|
|
deltas: dict[str, timedelta] = {
|
|
"second": timedelta(seconds=n),
|
|
"minute": timedelta(minutes=n),
|
|
"hour": timedelta(hours=n),
|
|
"day": timedelta(days=n),
|
|
"week": timedelta(weeks=n),
|
|
"month": timedelta(days=n * 30),
|
|
"year": timedelta(days=n * 365),
|
|
}
|
|
return (now - deltas[unit]).date().isoformat()
|
|
|
|
# MDY: "Jan 15, 2024" or "January 15, 2024"
|
|
m = re.match(r"^([A-Za-z]{3,9})\s+(\d{1,2}),?\s+(\d{4})", text)
|
|
if m:
|
|
mon = m.group(1).lower()[:3]
|
|
if mon in _MONTHS:
|
|
try:
|
|
return datetime(int(m.group(3)), _MONTHS[mon], int(m.group(2)), tzinfo=timezone.utc).date().isoformat()
|
|
except ValueError:
|
|
pass
|
|
|
|
# DMY: "15 Jan 2024" or "15 January 2024"
|
|
m = re.match(r"^(\d{1,2})\s+([A-Za-z]{3,9})\s+(\d{4})", text)
|
|
if m:
|
|
mon = m.group(2).lower()[:3]
|
|
if mon in _MONTHS:
|
|
try:
|
|
return datetime(int(m.group(3)), _MONTHS[mon], int(m.group(1)), tzinfo=timezone.utc).date().isoformat()
|
|
except ValueError:
|
|
pass
|
|
|
|
# ISO: "2024-01-15"
|
|
m = re.match(r"^(\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01]))", text)
|
|
if m:
|
|
return m.group(1)
|
|
|
|
return ""
|