UNPKG

@tmlmobilidade/types

Version:
91 lines (90 loc) 2.71 kB
/* * */ import { z } from 'zod'; /* * */ const OPERATIONAL_DAY_START_HOUR = 4; const OPERATIONAL_DAY_END_HOUR = 29; /** * Parses an operational HH:MM. * * Rules: * - minimum is 04:00 * - maximum is 29:59 * - minutes must be 00–59 * - hour must be at least 2 digits in stored format */ export function operationalHhmmToMinutes(hhmm, ignoreStartHour = false) { const match = /^(\d{2,}):(\d{2})$/.exec(hhmm); if (!match) { throw new Error(`Invalid operational time: ${hhmm}`); } const hours = Number(match[1]); const minutes = Number(match[2]); if (Number.isNaN(hours) || Number.isNaN(minutes)) { throw new Error(`Invalid operational time: ${hhmm}`); } if (minutes < 0 || minutes > 59) { throw new Error(`Invalid minutes in operational time: ${hhmm}`); } const total = hours * 60 + minutes; const minAllowed = OPERATIONAL_DAY_START_HOUR * 60; // 04:00 if (!ignoreStartHour && total < minAllowed) { throw new Error(`Operational time out of range: ${hhmm}`); } const maxAllowed = (OPERATIONAL_DAY_END_HOUR * 60) + 59; // 29:59 if (!ignoreStartHour && total > maxAllowed) { throw new Error(`Operational time out of range: ${hhmm}`); } return total; } /** * Converts common typed time formats into strict HH:MM. * * Examples: * - "800" -> "08:00" * - "0800" -> "08:00" * - "2200" -> "22:00" * - "2600" -> "26:00" * - "8:00" -> "08:00" * - "26:00" -> "26:00" * * Returns null if it cannot normalize safely. */ export function normalizeOperationalHhmmInput(value) { const trimmed = value.trim(); if (!trimmed) return null; // Pure digits: last 2 are minutes, everything before is hours if (/^\d{3,}$/.test(trimmed)) { const hours = trimmed.slice(0, -2); const minutes = trimmed.slice(-2); return `${hours.padStart(2, '0')}:${minutes}`; } // HH:MM with any hour length >= 1 const match = /^(\d+):(\d{2})$/.exec(trimmed); if (match) { const [, hours, minutes] = match; return `${hours.padStart(2, '0')}:${minutes}`; } return null; } export const HHMMSchema = z .string() .refine((value) => { try { operationalHhmmToMinutes(value); return true; } catch (err) { console.warn('Invalid HHMM:', value, err); return false; } }, 'Invalid operational time (expected HH:MM between 04:00 and 29:59)') .brand(); /** * Runtime-safe creator (validates + brands) */ export const hhmm = (value) => HHMMSchema.parse(value); /* * */ export function timeToMinutes(time, ignoreStartHour = false) { return operationalHhmmToMinutes(time, ignoreStartHour); }