feat(talon): add cron days-of-week helpers module#4499
feat(talon): add cron days-of-week helpers module#4499John Kennedy (jkennedyvz) wants to merge 2 commits into
Conversation
| candidate_date = now_local.date() | ||
| if _local_time_of(now_local) >= time: | ||
| candidate_date += timedelta(days=1) | ||
| candidate = _build_local(zone, candidate_date, time, fold=0) |
There was a problem hiding this comment.
🟡 Fall-back scheduling can return the past
During the repeated hour after a DST fall-back, this branch compares only the wall-clock LocalTimeOfDay before building the candidate with fold=0. For example, at 2026-11-01T09:15Z in America/Los_Angeles (01:15 PST, the second 1am hour), asking for 01:30 takes this path and returns 2026-11-01T08:30Z (01:30 PDT), which is already 45 minutes in the past. Callers expecting the next run can immediately mark a job due or loop on a stale scheduled time. After constructing the same-day candidate, verify it is still after now_utc (or use the second fold when applicable) before returning it.
(Refers to line 248)
Your feedback helps Open SWE learn. React with 👍 or 👎 to tell us if this review comment was useful.
| candidate = _build_local(zone, candidate_date, time, fold=0) | |
| candidate = _build_local(zone, candidate_date, time, fold=0) | |
| if _as_utc(candidate) <= now_utc: | |
| candidate = _build_local(zone, candidate_date + timedelta(days=1), time, fold=0) |
Closes JKB-15
Split out of PR #4426 (JKB-9) after review flagged the day-of-week types as out of scope for the time-helpers PR boundary. This PR gives them a focused home ahead of downstream schedule-parsing and tool-contract tickets.
Why
JKB-9 shipped overreach into day-of-week territory with
Weekday,DaysOfWeek,parse_weekday, andparse_days_of_week. These don't appear anywhere in JKB-9's scope/acceptance criteria and need their own home so JKB-9 can merge as a focused time-helpers PR while the day-of-week types ship separately and become importable for schedule parsing (JKB-10) and the cron tool contract (JKB-14).Stacked PR note
This branch sits on top of #4426 (JKB-9). GitHub's diff view on this PR is against
main, so it shows both the time-helpers module (from #4426) and the day-of-week module (this PR). The incremental contribution of this PR is 415 insertions across 2 files:libs/talon/deepagents_talon/cron/days_of_week.py(296 lines)libs/talon/tests/cron/test_days_of_week.py(119 lines)time.pyandtest_time.pyappear in the GitHub diff only because they haven't merged via #4426 yet. Merge #4426 first, then this PR resolves to just the two DoW files.What landed
deepagents_talon/cron/days_of_week.py:Weekday—IntEnumwith Monday=0 through Sunday=6, matchingdatetime.weekday()numbering.label/abbreviationproperties,from_date/from_datetimeclassmethods.DaysOfWeek— frozen dataclass (days: tuple[Weekday, ...]), normalized (deduped + sorted Monday through Sunday) in__post_init__, rejected when empty.all()/weekdays()/weekends()constructors,contains_date/contains_datetime/next_date_on_or_afterhelpers.parse_weekday(value) -> Weekday— full names (monday), abbreviations (mon,thu,sat), single letters (m,f); strips trailingsand.. Rejects empty, ambiguous single letters (s,t), and unknown tokens withCronTimeError.parse_days_of_week(value) -> DaysOfWeek— acceptsdaily/every day/everyday/any day/weekdays/weekends, plus spaced/comma/slash/plus-separated day lists (mon wed fri,monday, wednesday, and friday,sat/sun).CronTimeErrorfrom the time helpers module — no new error type.Tests
tests/cron/test_days_of_week.py— 30 deterministic unit tests covering:parse_weekdayaccepts common names/abbreviations, rejects unknown/ambiguous.parse_days_of_weekaccepts timer forms, rejects invalid values.DaysOfWeekdedupes, sorts, contains dates/datetimes, and computesnext_date_on_or_after.Weekday.from_date/from_datetimeagree withdate.weekday().Merge order
Depends on #4426 (JKB-9) for
CronTimeError. Branch sits on top of the JKB-9 commit; merge #4426 first, then this.Review notes
days_of_week.pyrather than folding intotime.pyto keep the JKB-9 time-helpers module focused and to make the downstream import surface explicit. Open to collapsing if a reviewer prefers.splural stripping inparse_weekday(mondays->monday) is intentional — natural language from the model often includes plurals. Ambiguous single letters (sfor Saturday/Sunday,tfor Tuesday/Thursday) are rejected rather than guessing.Release note
Add
deepagents_talon.cron.days_of_weekpure-function module withWeekday,DaysOfWeek,parse_weekday, andparse_days_of_week. Downstream schedule-parsing and tool-contract tickets import from this module.