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ída | Intervalo | Resultado esperado |
|---|---|---|
| 22:00 → 06:00 | 23:50 → 00:10 | 460 minutos / 07:40 |
| 22:00 → 06:00 | 09:00 → 09:30 | rejeitar: fora da jornada |
| 08:00 → 17:00 | 12:00 → 13:00 | 480 minutos / 08:00 |
| 23:30 → 01:00 | vazio | 90 minutos / 01:30 |
| 08:00 → 08:00 | vazio | pedir esclarecimento, sem adivinhar 24h |
| 08:00 → 17:00 | só a saída da pausa | rejeitar: intervalo incompleto |
| 25:00 → 06:00 | vazio | rejeitar: 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.