1

Horários que cruzam a meia-noite: valide o intervalo, não só o total

Um formulário de horários pode aceitar um intervalo fora da jornada e ainda mostrar um total aparentemente plausível. O teste precisa validar a posição da pausa, além de subtrair sua duração.

Exemplo fictício: entrada 22:00, saída 06:00 do dia seguinte, intervalo 23:50–00:10. São 480 minutos de duração civil, menos 20 de intervalo: 460 minutos = 07:40. Uma pausa 09:00–09:30 tem 30 minutos, mas não pertence a essa jornada; não deve simplesmente ser descontada.

Para um exemplo pequeno, restrito a uma jornada com duração menor que 24 horas, podemos representar tudo como deslocamentos em minutos a partir da entrada:

function hhmm(text) {
  if (!/^\d{2}:\d{2}$/.test(text)) throw new Error('Use HH:MM');
  const [h, m] = text.split(':').map(Number);
  if (h > 23 || m > 59) throw new Error('Horário inválido');
  return h * 60 + m;
}

function civilShift({ start, end, breakStart = '', breakEnd = '' }) {
  const first = hhmm(start);
  const offset = text => (hhmm(text) - first + 1440) % 1440;
  const span = offset(end);
  if (span === 0) throw new Error('Entrada e saída iguais são ambíguas');
  if (Boolean(breakStart) !== Boolean(breakEnd)) {
    throw new Error('Preencha os dois horários do intervalo');
  }
  let rest = 0;
  if (breakStart) {
    const a = offset(breakStart), b = offset(breakEnd);
    if (b <= a || b > span) throw new Error('Intervalo fora da jornada');
    rest = b - a;
  }
  const minutes = span - rest;
  if (minutes <= 0) throw new Error('Duração líquida inválida');
  const pad = n => String(n).padStart(2, '0');
  return { minutes, display: `${pad(Math.floor(minutes / 60))}:${pad(minutes % 60)}` };
}

Casos para conferir o contrato do formulário:

Entrada → saídaIntervaloResultado esperado
22:00 → 06:0023:50 → 00:10460 minutos / 07:40
22:00 → 06:0009:00 → 09:30rejeitar: fora da jornada
08:00 → 17:0012:00 → 13:00480 minutos / 08:00
23:30 → 01:00vazio90 minutos / 01:30
08:00 → 08:00vaziopedir esclarecimento, sem adivinhar 24h
08:00 → 17:00só a saída da pausarejeitar: intervalo incompleto
25:00 → 06:00vaziorejeitar: hora inválida

O exemplo foi executado com esses sete casos. O escopo é duração civil informada, com uma pausa e uma jornada inferior a 24h. Datas, fuso, mudança de horário, múltiplos turnos e regras de folha exigem contratos próprios. Isso não calcula direitos trabalhistas, adicional noturno ou uma jornada efetivamente medida por relógio; também não valida sozinho uma regra jurídica.

Transparência: mantenho o ContaCLT, com uma interface gratuita de horários. Compartilho o exemplo técnico completo para que a discussão seja útil sem depender da ferramenta. Não envie nomes, salários ou dados de empregados em comentários ou capturas públicas. Texto preparado com auxílio de IA; os casos do exemplo foram executados separadamente da interface do produto.

Carregando publicação patrocinada...