import type { ApiTrainsTrainDetails } from '@owlboard/owlboard-ts'; export const estClass = (act: any, est: any) => (act ? 'act' : 'est'); /** * Converts ISO/JSON time to UK-formatted HH:MM string, with optional (default off) seconds * Ensures Europe/London timezone irrespective of browser timezone. */ export function formatUkTime( dateStr: string | Date | undefined, includeSeconds: boolean = false ): string { if (!dateStr) return '-'; const date = typeof dateStr === 'string' ? new Date(dateStr) : dateStr; if (isNaN(date.getTime())) return '-'; return date.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit', ...(includeSeconds && { second: '2-digit' }), hour12: false, timeZone: 'Europe/London' }); } /** * Converts ISO/JSON time to UK-formatted DD/MM/YY HH:MM:SS string. * Ensures Europe/London timezone irrespective of browser timezone. */ export function formatUkDateTime( dateStr: string | Date | undefined, includeSeconds: boolean = false ): string { if (!dateStr) return '--/--/-- --:--:--'; const date = typeof dateStr === 'string' ? new Date(dateStr) : dateStr; if (isNaN(date.getTime())) return '--/--/-- --:--:--'; return date .toLocaleString('en-GB', { day: '2-digit', month: '2-digit', year: '2-digit', hour: '2-digit', minute: '2-digit', ...(includeSeconds && { second: '2-digit' }), hour12: false, timeZone: 'Europe/London' }) .replace(',', ''); } /** * Specific type that can handle the TrainDetails.ServiceLocation and the ApiStationsBoard.BoardService types for delay calculation */ interface DelayInput { // Board types sta?: string | null; std?: string | null; eta?: string | null; etd?: string | null; ata?: string | null; atd?: string | null; // Journey types pta?: string | null; ptd?: string | null; wta?: string | null; wtd?: string | null; atp?: string | null; wtp?: string | null; etp?: string | null; } /** * Calculates a 'delay' value, in the formats: * RT, 1E, 7L, etc. * @param 'Schedule Location' or 'Board Service' object * @returns Delay string for departure boards */ export function calculateDelay(loc: DelayInput): { val: string; type: string; } { const pairs = [ // Departure check (Board: atd/etd vs std | Journey: atd vs ptd/wtd) { actual: loc.atd || loc.etd, sched: loc.std || loc.ptd || loc.wtd }, // Arrival check (Board: ata/eta vs sta | Journey: ata vs pta/wta) { actual: loc.ata || loc.eta, sched: loc.sta || loc.pta || loc.wta }, // Passing check { actual: loc.atp || loc.etp, sched: loc.wtp } ]; const match = pairs.find((p) => p.actual && p.sched); if (!match || !match.actual || !match.sched) return { val: '', type: 'none' }; const diffMinutes = Math.round((Date.parse(match.actual) - Date.parse(match.sched)) / 60000); if (diffMinutes === 0) return { val: 'RT', type: 'ontime' }; const absDiff = Math.abs(diffMinutes); if (diffMinutes > 0) { return { val: `${absDiff}L`, type: 'late' }; } else { return { val: `${absDiff}E`, type: 'early' }; } } /** * Accepts a pair of times (string or Date) and outputs a delay class 'delay-early', 'delay-late' or 'delay-rt' * @param sched Scheduled Time (string, Date) * @param act Actual Time (string, Date) */ export function delayClassFromTimePair(sched: any, act: any): string { if (!sched || !act) return ''; const s = new Date(sched).getTime(); const a = new Date(act).getTime(); if (isNaN(s) || isNaN(a)) return ''; const diff = a - s; const oneMinute = 60000; // on-time if within one minute if (Math.abs(diff) < oneMinute) { return 'delay-rt'; } return diff > 0 ? 'delay-late' : 'delay-early'; }