Skip to content

feat(reminders): support CRON_TZ prefix for timezone-aware cron schedules - #1789

Open
nixie-ai wants to merge 5 commits into
netclaw-dev:devfrom
nixie-ai:feat/cron-tz-timezones
Open

feat(reminders): support CRON_TZ prefix for timezone-aware cron schedules#1789
nixie-ai wants to merge 5 commits into
netclaw-dev:devfrom
nixie-ai:feat/cron-tz-timezones

Conversation

@nixie-ai

@nixie-ai nixie-ai commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Implements #1788.

Adds support for the Vixie crontab CRON_TZ=<time-zone-id> prefix on reminder cron schedules, e.g. CRON_TZ=Europe/Brussels 0 9 * * *.

What changed

  • CronScheduleHelper — new SplitTimeZone helper strips an optional CRON_TZ= prefix (case-insensitive), resolves it via TimeZoneInfo.FindSystemTimeZoneById, and passes the zone to Cronos GetNextOccurrence(from, tz), which is DST-aware out of the box. Unknown zones throw CronFormatException with a clear message instead of the confusing 'Minutes: Value must be a number' parse error. TryParse gains an out TimeZoneInfo overload; Describe reports the actual zone instead of hardcoded 'UTC'.
  • Zero storage/proto changes — the prefixed expression is stored as-is in ReminderSchedule.CronExpression; ReminderManagerActor.ScheduleDefinitionAsync re-parses it on every (re)schedule, so the zone survives restarts and reschedules for free.
  • Tool/parser docsset_reminder tool description and ReminderScheduleParser validation error now mention the prefix.

Default behavior is unchanged: expressions without the prefix still evaluate in UTC.

Verified against pinned Cronos 0.13.0

CRON_TZ=Europe/Brussels 0 9 * * *  →  2026-08-07 07:00Z  (09:00 CEST)

Tests

New cases in CronScheduleHelperTests: prefix parsing (valid/case-insensitive/missing zone/unknown zone), zone resolution, local-zone evaluation, DST spring-forward and fall-back transitions (Europe/Brussels 2026), unknown-zone rejection, no-prefix UTC regression, and Describe zone reporting. New SetReminderToolTests cases: prefixed expression accepted and stored as-is, unknown zone rejected. Full Reminders suite: 144/144 passing.

…ules (netclaw-dev#1788)

Cron reminder schedules were always evaluated in UTC because
CronScheduleHelper hardcoded TimeZoneInfo.Utc. Add support for the
Vixie crontab CRON_TZ=<time-zone-id> prefix:

- CronScheduleHelper.SplitTimeZone strips/resolves the optional prefix
  via TimeZoneInfo.FindSystemTimeZoneById and passes the zone to
  Cronos GetNextOccurrence (DST-aware). Unknown zones produce a clear
  CronFormatException instead of a confusing parse error.
- TryParse gains an out TimeZoneInfo overload; Describe reports the
  zone instead of hardcoded 'UTC'.
- Stored expressions keep the prefix as-is, so re-scheduling in
  ReminderManagerActor.ScheduleDefinitionAsync picks up the zone with
  no proto or schema changes.
- set_reminder tool description and ReminderScheduleParser error
  message document the prefix.

Default behavior is unchanged: expressions without the prefix still
evaluate in UTC.

Fixes netclaw-dev#1788
@nixie-ai
nixie-ai force-pushed the feat/cron-tz-timezones branch from 823034d to 5ce7815 Compare August 6, 2026 22:22
@Aaronontheweb Aaronontheweb added bug Something isn't working reminders Reminder scheduling, execution, and history labels Aug 7, 2026

@Aaronontheweb Aaronontheweb left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. The DST-aware Cronos change looks good.

I have one correctness request and one documentation request:

  1. The parser currently splits a timezone ID at the first space. Windows IDs such as Eastern Standard Time therefore fail. Please either support quoted IDs or explicitly require IANA identifiers in the parser contract, tool description, and tests.

  2. Please update feeds/skills/.system/files/netclaw-operations/references/scheduling.md with the CRON_TZ guidance. Please also increase the netclaw-operations skill version.

We can handle the broader identity integration, confirmation formatting, culture support, and behavioral eval coverage as maintainer follow-up work.

@Aaronontheweb Aaronontheweb left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had Codex leave a comment while I was reviewing with it - but TL;DR; I think as long as you get the timezone culture parsing sorted out along with some guidance to the LLM via the netclaw-operations skill, we should be able to take this and run evals with it to see if small models can schedule correctly using the correct local timezones.

Per netclaw-dev#1789 (review):

1. Make the CRON_TZ zone contract explicit instead of supporting quoted
   Windows IDs: XML docs on CronScheduleHelper and SplitTimeZone state
   IANA-only, unknown/empty-zone errors now point at the IANA format
   (e.g. 'Europe/Brussels') so 'CRON_TZ=Eastern Standard Time' fails
   with guidance rather than a bare 'Unknown time zone Eastern'.
   Tool description and ReminderScheduleParser error carry the same rule.

2. Add a 'Cron time zones (CRON_TZ)' section to the netclaw-operations
   scheduling reference (UTC default, syntax, DST note, IANA-only rule,
   loose-name translation guidance) and add a prefixed example to the
   schedule-type table. Bump netclaw-operations 2.40.0 -> 2.41.0.

Tests: Windows-style zone rejection (with IANA hint in the message),
IANA guidance in unknown-zone errors.
@nixie-ai

nixie-ai commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review! Addressed both requests in 770de9b:

1. Time zone identifier contract — IANA-only (your second option). I went with an explicit IANA requirement rather than quoted-ID support: IANA ids (Europe/Brussels, America/New_York) are unambiguous, DST-aware by design, and simpler for agents to follow when scheduling. Changes:

  • XML docs on CronScheduleHelper/SplitTimeZone state the contract: IANA identifiers without spaces only; Windows display names are not supported.
  • Unknown/empty-zone errors now carry guidance instead of failing bare: Unknown time zone 'Eastern' in CRON_TZ prefix. Use an IANA time zone id without spaces (e.g. 'Europe/Brussels'). — so CRON_TZ=Eastern Standard Time truncation fails loud with the fix.
  • set_reminder tool description and the ReminderScheduleParser error message carry the same rule.
  • New tests: Windows-style name rejected (asserts the IANA hint is in the message), IANA guidance asserted in unknown-zone errors.

2. Skill docs. Added a Cron time zones (CRON_TZ) section to feeds/skills/.system/files/netclaw-operations/references/scheduling.md (UTC default, syntax, DST note, IANA-only rule, guidance to translate loose names like 'Eastern time' to America/New_York) plus a prefixed example in the schedule-type table. Bumped netclaw-operations 2.40.0 → 2.41.0.

Build clean, Reminders test suite 146/146 passing. Happy to run evals once you have them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working reminders Reminder scheduling, execution, and history

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants