| """Date arithmetic tool (years between, add years, day of week). |
| |
| Stdlib-only β no external client. Errors returned as Observation strings |
| (same convention as calculator), not raised exceptions. |
| """ |
| import re |
| from datetime import datetime |
| from . import tool |
|
|
|
|
| |
| |
| _YEAR_OR_ISO_RE = re.compile(r"^(\d{4})(?:-\d{2}-\d{2})?$") |
|
|
|
|
| def _parse_year(value: str) -> int: |
| """Parse a year from "YYYY" or "YYYY-MM-DD". Raises ValueError on garbage.""" |
| m = _YEAR_OR_ISO_RE.match(value.strip()) |
| if not m: |
| raise ValueError( |
| f"expected year as 'YYYY' or 'YYYY-MM-DD', got {value!r}" |
| ) |
| return int(m.group(1)) |
|
|
|
|
| @tool |
| def datetime_tool( |
| operation: str, |
| date_or_year: str, |
| extra: str | None = None, |
| ) -> str: |
| """Date arithmetic. The 'extra' parameter's meaning depends on 'operation': |
| for years_between it's a second year/date; for add_years it's an integer |
| count; for day_of_week it's ignored. |
| |
| Operations: |
| - "years_between": years from `date_or_year` to `extra` (both as "YYYY" or "YYYY-MM-DD"). |
| Inputs must be valid years; "19" or "abc1976" raise. |
| - "add_years": `date_or_year` (a year string) + `extra` (an integer year count). |
| - "day_of_week": weekday name for `date_or_year` (YYYY-MM-DD). |
| |
| Examples: |
| datetime_tool("years_between", "1976", "2007") -> "31 years" |
| datetime_tool("add_years", "2024", "5") -> "2029" |
| datetime_tool("day_of_week", "2024-07-04") -> "Thursday" |
| """ |
| try: |
| if operation == "years_between": |
| if extra is None: |
| return "Error: years_between requires extra=second date" |
| start = _parse_year(date_or_year) |
| end = _parse_year(extra) |
| return f"{end - start} years" |
| if operation == "add_years": |
| if extra is None: |
| return "Error: add_years requires extra=year count" |
| year = _parse_year(date_or_year) |
| |
| try: |
| count = int(extra) |
| except ValueError: |
| raise ValueError(f"add_years expects extra as integer count, got {extra!r}") |
| return str(year + count) |
| if operation == "day_of_week": |
| d = datetime.strptime(date_or_year, "%Y-%m-%d") |
| return d.strftime("%A") |
| return f"Error: unknown operation {operation!r}. Valid: years_between, add_years, day_of_week." |
| except Exception as e: |
| return f"Datetime error: {type(e).__name__}: {e}" |
|
|