Launch offer: the first 1,000 users get Settl free for a year*Claim your spot
settlbuilding in public

Time-Zone-Safe Scheduling Pack

An offset is a number. A time zone is a rule set for a place.

-08:00 cannot tell you that Los Angeles moves to -07:00 in summer. If a reminder should stay at 9:00 in the user's local time, store an IANA zone such as America/Los_Angeles, not the offset that happened to be correct when the account was created.

Model the two kinds of time

An instant is one point on the global timeline. Store it in UTC for an event that already happened: payment received, message sent, deployment completed.

A local schedule is a wall-clock intention plus a zone: every weekday at 9:00 in America/New_York. Do not precompute years of future UTC instants and forget the local rule. Time-zone law and tzdata can change.

Store:

Gaps and overlaps

During the spring transition, some local times do not exist. During the autumn transition, some happen twice. Your product must choose rather than letting a date library choose invisibly.

For a nonexistent 2:30, you might reject it, move to the next valid time, or ask the user. For a repeated 1:30, choose the earlier or later occurrence and show the selected offset. Scheduling money, medicine, or access changes may require a stricter policy than sending a digest.

Recurring work

Calculate the next occurrence from the local rule and current time-zone data. Keep historical instants unchanged when tzdata updates, but recalculate future occurrences that have not executed. Make the scheduler idempotent so recalculation cannot send the same job twice.

Verification checklist

  1. Test the spring gap in every supported zone with daylight saving.
  2. Test both occurrences in the autumn overlap.
  3. Prove a 9:00 local recurrence remains at 9:00 when its UTC offset changes.
  4. Test half-hour and quarter-hour zones, not only whole-hour examples.
  5. Update the tzdata fixture and prove future occurrences recalculate while history does not.
  6. Cross a date boundary between the user zone and UTC.
  7. Retry one scheduled execution and prove it runs once.

The starter accepts stored timestamps, an IANA zone, local and recurrence rules, transition fixtures, and a tzdata policy. It returns the time model, persistence rule, gap/overlap decisions, recurrence calculation, and transition tests. Dry-run schedules and sends nothing.

Download the runnable pack

Comment TIMEZONE for the pack. A place stays meaningful after its offset expires.

Get the next one in your inbox