1001Ferramentas
Generators

Cron Timezone Shifter

Converts a crontab expression from one timezone to another, shifting hour/minute and handling day-of-week wrap.

Cron convertido:

      

Cron timezone shifting in practice

Linux cron interprets its expressions in the server's local timezone. The vast majority of cloud servers run in UTC, but business logic almost always lives in a regional timezone — "run the daily report at 9 AM São Paulo time", "fire off the weekly digest Friday at 5 PM New York time". The mismatch leads to one of the most common operations bugs: a cron entry that drifts by one hour twice a year because daylight saving time was forgotten, or that runs at 6 AM local time because nobody converted UTC.

Concretely, "daily 9 AM in São Paulo" (UTC-3, no DST) translates to a server-UTC cron of 0 12 * * *. "Friday 5 PM in New York" is harder — it is 0 22 * * 5 during EST winter but 0 21 * * 5 during EDT summer. There is no single fixed expression. This is why timezone-aware schedulers exist.

DST: the perennial enemy

  • Brazil has had no DST since 2019 (Decree 9.772). A national-only cron in BRT is now perfectly stable year-round — a huge simplification for Brazilian developers.
  • United States switches on the 2nd Sunday of March (spring forward) and the 1st Sunday of November (fall back).
  • European Union switches on the last Sunday of March and the last Sunday of October.
  • DST jump (clock 2:00 → 3:00): cron jobs scheduled inside the missing hour are skipped.
  • DST fallback (clock 2:00 → 1:00): cron jobs scheduled inside the repeated hour may run twice or zero times depending on the cron implementation.

Mitigation: avoid scheduling between 1:00 and 3:00 AM in any DST region. If you absolutely must, add an idempotency token to the job so the duplicate run is a no-op.

Timezone-aware schedulers (preferred)

Modern systems prefer to declare the intended timezone alongside the cron, rather than pre-shifting to UTC:

  • Linux cron — set CRON_TZ=America/Sao_Paulo at the top of the crontab; entries below it run in that zone.
  • systemd timersOnCalendar=Mon..Fri 09:30 America/Sao_Paulo. Cleaner than cron for timezone-aware schedules.
  • Kubernetes CronJobspec.timeZone field, stable since Kubernetes 1.27.
  • AWS EventBridge Scheduler — accepts a ScheduleExpressionTimezone parameter.
  • GCP Cloud Scheduler — has a timeZone field on every job.

All of these handle DST transitions for you. They are strictly safer than computing a fixed UTC offset by hand.

Conversion algorithm

When you must convert manually (e.g. shared hosting that only accepts UTC cron), the algorithm is:

1. Parse the source cron in source timezone.
2. Pick a representative date (today, or a date inside the
   target DST window if the cron straddles DST boundaries).
3. Compute the UTC offset for that date in the source TZ.
4. Apply the offset to the hour field; wrap day-of-week and
   day-of-month if the hour rolls over midnight.
5. Emit UTC cron.

For Python use croniter + zoneinfo; for Node use node-cron with the timezone option; for Java use Quartz Cron with TimeZone.

FAQ

Does Brazil still have DST? No. Horário de verão was abolished by federal decree in 2019. BRT is now permanently UTC-3 (and UTC-4 in Amazonas/AC), so any Brazilian cron is stable year-round.

Container DSL or CRON_TZ — which is better? Whenever the platform supports it, prefer the container/DSL field (k8s spec.timeZone, EventBridge ScheduleExpressionTimezone). It is more visible, declarative and survives schedule edits without surprises.

Does DST really break cron? Yes — twice a year. The spring jump skips an hour entirely; the autumn fallback either repeats or skips, depending on the implementation. Best mitigation is to avoid 1:00-3:00 AM scheduling or add idempotency to jobs.

How do I test conversion? Run TZ=America/Sao_Paulo date and TZ=UTC date in two terminals; the offset should match what this tool computed.

Related Tools