Exceções de evento
Eventos recorrentes se repetem por regra. A vida real, não. O Natal cai em um domingo e empurra o serviço matinal regular para um horário noturno; um feriado fecha o prédio e você cancela a reunião de oração de uma quarta-feira; um pregador convidado significa uma mudança de título por uma semana. Exceções são como o GCM lida com essas edições sem reescrever a RRULE subjacente.
Dois mecanismos, um propósito
O GCM tem duas formas de fazer com que uma única data se comporte diferente do resto de uma série:
events.exception_dates— uma colunadate[]no próprio evento. Adicione uma data aqui e essa ocorrência desaparece do calendário. Sem join de tabela, sem linha extra.- Tabela
event_exceptions— uma linha por substituição, com campos para cancelar, renomear, remarcar ou realocar uma ocorrência.
A primeira é para o caso simples ("apenas pule esta data"). A segunda é para tudo mais.
event_exceptions(
id, event_id, exception_date,
is_cancelled, override_title,
override_start_time, override_end_time,
override_location, created_at
)A exception_date é a data em que o evento pai teria caído, antes da substituição entrar em vigor. Todos os outros campos são opcionais — qualquer coisa que você deixar nulo cai no valor do evento pai.
Cancelando uma ocorrência
O caso mais comum: um Culto de Domingo regular é suspenso porque o prédio está sendo pintado, ou uma reunião de oração semanal é pulada por causa de um feriado.
Duas formas equivalentes de fazer:
- Caminho rápido — adicione a data a
events.exception_dates. A ocorrência desaparece da grade do calendário. - Caminho auditável — insira uma linha em
event_exceptionscomis_cancelled = true. A ocorrência também desaparece, mas agora você tem um registro de por que foi cancelada (visível para administradores quando abrem a data).
Para pulos ocasionais, o caminho rápido basta. Para cancelamentos que você pode precisar explicar depois (perseguições de reembolso, disputas de presença), o caminho auditável deixa um rastro.
Movendo uma ocorrência
Quando a ocorrência ainda acontece, mas em um horário ou lugar diferente, use a linha de event_exceptions para substituir apenas os campos que mudam. O resto cascateia do evento pai:
INSERT INTO event_exceptions (event_id, exception_date, is_cancelled,
override_start_time, override_location)
VALUES ('<id>', '2026-12-24', false,
'19:00', 'Sanctuary — candlelight setup');No dia 24 de dezembro o calendário ainda mostra o evento, mas o chip de horário lê 19:00 e o local lê "Sanctuary — candlelight setup". A série continua se repetindo no seu ritmo normal de domingo de manhã depois.
Campos de substituição disponíveis:
override_title— substitui o título para aquela data única. "Culto de Domingo" vira "Culto da Véspera de Natal".override_start_time/override_end_time— desloca os horários. Use ambos se a duração também muda.override_location— aponta os participantes para outro lugar pelo dia.
Se você precisa substituir campos que a tabela de exceção não carrega — cor, descrição, filial — a substituição não é expressiva o suficiente. Você vai precisar bifurcar: exclua a ocorrência com uma exceção, e crie um evento único separado para a data alterada.
Exceções vs atualizações de RRULE
Uma pergunta frequente: devo editar a regra de recorrência ou adicionar uma exceção? A regra prática:
- Uma ou duas datas mudam → adicione exceções. A regra continua descrevendo o padrão normal, e as exceções descrevem os desvios.
- O padrão em si muda para frente → edite a RRULE. Nova data de fim, novo dia da semana, novo modo mensal. A regra deve sempre descrever o que é normal, não o que era normal.
- Indo de semanal para quinzenal no meio do ano → termine a regra atual com
UNTIL=<switchover>, e crie um novo evento com a nova regra começando depois dessa data. Não tente codificar a transição dentro de uma única RRULE — mudanças deINTERVALno meio da série não são representáveis.
O movimento errado é excluir o evento recorrente quando algo muda, porque a exclusão remove suavemente cada ocorrência, incluindo as passadas ligadas à presença e aos relatórios. O movimento certo é quase sempre: adicione uma exceção, ou termine a série atual e comece uma nova.
Como as exceções renderizam
Nas visões mês e próximos, a lógica de exceção roda no lado do cliente como parte da expansão da RRULE:
- O navegador pergunta ao evento pai "em que datas você cairia nesta janela?"
- Filtra qualquer data em
events.exception_dates. - Filtra qualquer data onde
event_exceptions.is_cancelled = true. - Para as datas que sobrevivem, sobrepõe os campos de substituição de qualquer linha de
event_exceptionsnão cancelada por cima dos padrões do evento pai.
Isso significa que uma exceção com is_cancelled = false mais override_title = 'Christmas Eve Service' aparece na grade com o novo título mas com o horário, local e cor do pai — a menos que esses também sejam substituídos.
Quando pensar diferente
Se você se pega adicionando muitas exceções a um evento, o padrão está errado. Um Culto de Domingo que é renomeado seis vezes por ano para serviços especiais é um sinal de que você deveria manter "Culto de Domingo" entediante e adicionar eventos únicos separados para as datas especiais — Véspera de Natal, Páscoa, etc. Exceções são melhores como correção rara, não como modo normal.
Para as regras que governam o padrão normal, veja Padrões recorrentes. Para datas únicas que não estão ligadas a uma série recorrente, apenas crie um novo evento.
