Skip to content

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:

  1. events.exception_dates — uma coluna date[] no próprio evento. Adicione uma data aqui e essa ocorrência desaparece do calendário. Sem join de tabela, sem linha extra.
  2. 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.

sql
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_exceptions com is_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:

sql
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 de INTERVAL no 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:

  1. O navegador pergunta ao evento pai "em que datas você cairia nesta janela?"
  2. Filtra qualquer data em events.exception_dates.
  3. Filtra qualquer data onde event_exceptions.is_cancelled = true.
  4. Para as datas que sobrevivem, sobrepõe os campos de substituição de qualquer linha de event_exceptions nã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.