This commit is contained in:
2026-04-17 20:49:21 -04:00
parent 4e243751b2
commit bbddd58f98
6 changed files with 106 additions and 19 deletions

View File

@@ -6,10 +6,12 @@ All internal timestamps use nanoseconds since epoch (UTC).
"""
import logging
import re
from typing import Union
from datetime import datetime
from datetime import datetime, timezone
import pandas as pd
from dateutil import parser as dateparser
from dateutil import parser as _dateutil_parser
from dateutil.relativedelta import relativedelta
log = logging.getLogger(__name__)
@@ -18,6 +20,20 @@ TimestampInput = Union[int, float, str, datetime, pd.Timestamp]
NANOS_PER_SECOND = 1_000_000_000
_RELATIVE_RE = re.compile(
r'^(\d+)\s+(second|minute|hour|day|week|month|year)s?\s+ago$',
re.IGNORECASE,
)
def _parse_relative_date(s: str) -> datetime | None:
"""Parse relative date strings like '30 days ago', '2 weeks ago'."""
m = _RELATIVE_RE.match(s.strip())
if not m:
return None
n, unit = int(m.group(1)), m.group(2).lower()
return datetime.now(timezone.utc) - relativedelta(**{f'{unit}s': n})
def to_nanoseconds(timestamp: TimestampInput) -> int:
"""
@@ -31,6 +47,7 @@ def to_nanoseconds(timestamp: TimestampInput) -> int:
timestamp: Can be:
- Unix timestamp (int/float) - assumed to be in seconds
- ISO date string (str) - parsed using dateutil
- Relative date string (str) - e.g. "30 days ago", "2 weeks ago"
- datetime object
- pandas Timestamp
@@ -48,7 +65,9 @@ def to_nanoseconds(timestamp: TimestampInput) -> int:
if isinstance(timestamp, (int, float)):
return int(timestamp * NANOS_PER_SECOND)
elif isinstance(timestamp, str):
dt = dateparser.parse(timestamp)
dt = _parse_relative_date(timestamp)
if dt is None:
dt = _dateutil_parser.parse(timestamp)
if dt is None:
raise ValueError(f"Could not parse date string: {timestamp}")
return int(dt.timestamp() * NANOS_PER_SECOND)