Expressão cron: como ler, escrever e acertar o fuso horário
Uma expressão cron tem cinco campos: minuto, hora, dia do mês, mês e dia da semana. Este guia explica cada campo, traz os agendamentos mais usados, mostra a regra que faz o cron rodar mais vezes do que o esperado e explica o erro mais comum no Brasil: agendar no horário de Brasília um serviço que roda em UTC.
Os cinco campos
- Minuto: 0 a 59.
- Hora: 0 a 23.
- Dia do mês: 1 a 31.
- Mês: 1 a 12 (ou JAN a DEC).
- Dia da semana: 0 a 6, com 0 no domingo (a maioria das implementações também aceita 7 como domingo, e SUN a SAT).
Em cada campo, * significa "todos", 1,15 é uma lista, 1-5 é um intervalo e */10 é "a cada 10". Para ler uma expressão em português e ver as próximas execuções, cole no interpretador de cron.
Exemplos prontos
*/5 * * * *: a cada 5 minutos.0 * * * *: a cada hora, no minuto zero.0 3 * * *: todo dia às 3h.30 8 * * 1-5: de segunda a sexta, às 8h30.0 0 1 * *: à meia-noite do dia 1 de cada mês.0 */6 * * *: a cada 6 horas (0h, 6h, 12h e 18h).
A pegadinha do dia do mês com o dia da semana
Quando os dois campos de dia estão restritos, o cron padrão roda quando qualquer um deles bate, e não quando os dois batem. 0 9 13 * 5 roda todo dia 13 e também toda sexta-feira, não só na sexta-feira 13. Se um dos dois for *, vale só o outro.
Para "a primeira segunda-feira do mês", o cron sozinho não resolve: agende 0 9 1-7 * * e confira o dia da semana dentro do script.
O fuso horário: Brasília ou UTC?
O cron do Linux usa o fuso do servidor, mas muitos agendadores usam UTC: o GitHub Actions, a maioria dos serviços de nuvem e servidores configurados em UTC. Brasília é UTC-3 o ano todo desde 2019, sem horário de verão, então 0 3 * * * em UTC roda à meia-noite de Brasília.
Para converter, some 3 horas. Das 21h em diante, em UTC já é o dia seguinte, e se a expressão tiver dias da semana eles também andam um dia. A função abaixo faz a conversão para agendamentos diários, com ou sem lista de dias:
// Brasília é UTC-3 o ano todo (não há horário de verão desde 2019).
// diasDaSemana: '*' ou uma lista como '1,3,5' (0 = domingo).
function cronDeBrasilia(minuto, hora, diasDaSemana = '*') {
const horaUtc = hora + 3;
let dias = diasDaSemana;
// Das 21h em diante, em UTC já é o dia seguinte: o dia da semana anda junto
if (horaUtc >= 24 && dias !== '*') {
dias = dias.split(',').map((d) => (Number(d) + 1) % 7).join(',');
}
return `${minuto} ${horaUtc % 24} * * ${dias}`;
} Serve para minuto e hora fixos. Faixas como 1-5 precisam virar lista (1,2,3,4,5) antes.
# Brasília é UTC-3 o ano todo (não há horário de verão desde 2019).
# dias_da_semana: "*" ou uma lista como "1,3,5" (0 = domingo).
def cron_de_brasilia(minuto: int, hora: int, dias_da_semana: str = "*") -> str:
hora_utc = hora + 3
dias = dias_da_semana
# Das 21h em diante, em UTC já é o dia seguinte: o dia da semana anda junto
if hora_utc >= 24 and dias != "*":
dias = ",".join(str((int(d) + 1) % 7) for d in dias.split(","))
return f"{minuto} {hora_utc % 24} * * {dias}" <?php
// Brasília é UTC-3 o ano todo (não há horário de verão desde 2019).
// $diasDaSemana: '*' ou uma lista como '1,3,5' (0 = domingo).
function cronDeBrasilia(int $minuto, int $hora, string $diasDaSemana = '*'): string
{
$horaUtc = $hora + 3;
$dias = $diasDaSemana;
// Das 21h em diante, em UTC já é o dia seguinte: o dia da semana anda junto
if ($horaUtc >= 24 && $dias !== '*') {
$dias = implode(',', array_map(fn($d) => ((int) $d + 1) % 7, explode(',', $dias)));
}
return sprintf('%d %d * * %s', $minuto, $horaUtc % 24, $dias);
} Cuidados
- Há variações com seis ou sete campos, com segundos no começo (Quartz, Spring) ou ano no fim. Confira quantos campos o seu agendador espera.
- No GitHub Actions, o menor intervalo é de 5 minutos, e a execução pode atrasar em horários de muita carga. Não conte com precisão de minuto.
- Evite agendar tudo em
0 * * * *ou à meia-noite: muita gente faz isso, e os serviços ficam sobrecarregados nesses horários. Um minuto quebrado, como17, ajuda. - Garanta que a tarefa aguente rodar duas vezes ou atrasar. Reinícios e trocas de servidor fazem isso acontecer.
Achou um erro neste guia? Avise por e-mail.
Ferramentas para usar junto
Perguntas frequentes
Como fazer um cron a cada 5 minutos?
Use */5 * * * *. O */5 no campo de minuto significa a cada 5 minutos, a partir do minuto zero: 0, 5, 10 e assim por diante.
O cron usa o horário de Brasília?
Depende de onde roda. O cron do Linux usa o fuso configurado no servidor. O GitHub Actions e a maioria dos serviços de nuvem usam UTC, que está 3 horas à frente de Brasília.
Domingo é 0 ou 7 no cron?
O padrão é 0. A maioria das implementações aceita 7 também como domingo, mas usar 0 funciona em todas.
Por que meu cron rodou em dias a mais?
Provavelmente os campos de dia do mês e de dia da semana estão restritos ao mesmo tempo. Nesse caso o cron roda quando qualquer um dos dois bate, não quando os dois batem.