diff --git a/app/components/malio/time/composables/timeFormat.test.ts b/app/components/malio/time/composables/timeFormat.test.ts new file mode 100644 index 0000000..3eea58e --- /dev/null +++ b/app/components/malio/time/composables/timeFormat.test.ts @@ -0,0 +1,31 @@ +import {describe, expect, it} from 'vitest' +import {clampHours, clampMinutes, formatTime, padSegment, parseTime} from './timeFormat' + +describe('timeFormat', () => { + it('parse une chaîne HH:MM valide', () => { + expect(parseTime('09:05')).toEqual({hours: 9, minutes: 5}) + }) + + it('renvoie null pour vide ou invalide', () => { + expect(parseTime('')).toBeNull() + expect(parseTime(null)).toBeNull() + expect(parseTime('abc')).toBeNull() + expect(parseTime('12')).toBeNull() + }) + + it('clamp les valeurs hors bornes au parsing', () => { + expect(parseTime('99:88')).toEqual({hours: 23, minutes: 59}) + }) + + it('formate avec zéro-padding', () => { + expect(formatTime(9, 5)).toBe('09:05') + expect(formatTime(0, 0)).toBe('00:00') + }) + + it('clamp et pad les helpers', () => { + expect(clampHours(30)).toBe(23) + expect(clampHours(-2)).toBe(0) + expect(clampMinutes(75)).toBe(59) + expect(padSegment(7)).toBe('07') + }) +}) diff --git a/app/components/malio/time/composables/timeFormat.ts b/app/components/malio/time/composables/timeFormat.ts new file mode 100644 index 0000000..02221c2 --- /dev/null +++ b/app/components/malio/time/composables/timeFormat.ts @@ -0,0 +1,32 @@ +export interface TimeParts { + hours: number + minutes: number +} + +export function clampHours(value: number): number { + if (Number.isNaN(value)) return 0 + return Math.min(23, Math.max(0, Math.trunc(value))) +} + +export function clampMinutes(value: number): number { + if (Number.isNaN(value)) return 0 + return Math.min(59, Math.max(0, Math.trunc(value))) +} + +export function padSegment(value: number): string { + return value.toString().padStart(2, '0') +} + +export function parseTime(value: string | null | undefined): TimeParts | null { + if (!value) return null + const match = /^(\d{1,2}):(\d{1,2})$/.exec(value.trim()) + if (!match) return null + return { + hours: clampHours(Number.parseInt(match[1], 10)), + minutes: clampMinutes(Number.parseInt(match[2], 10)), + } +} + +export function formatTime(hours: number, minutes: number): string { + return `${padSegment(clampHours(hours))}:${padSegment(clampMinutes(minutes))}` +}