feat : utilitaires de format et validation de date (#MUI-33)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
62
app/components/malio/date/composables/dateFormat.test.ts
Normal file
62
app/components/malio/date/composables/dateFormat.test.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import {describe, expect, it} from 'vitest'
|
||||||
|
import {formatIsoToDisplay, isDateInRange, isValidIso, parseDisplayToIso} from './dateFormat'
|
||||||
|
|
||||||
|
describe('dateFormat', () => {
|
||||||
|
describe('isValidIso', () => {
|
||||||
|
it('accepts a real ISO date', () => {
|
||||||
|
expect(isValidIso('2026-05-19')).toBe(true)
|
||||||
|
})
|
||||||
|
it('rejects a malformed string', () => {
|
||||||
|
expect(isValidIso('19/05/2026')).toBe(false)
|
||||||
|
expect(isValidIso('2026-5-9')).toBe(false)
|
||||||
|
expect(isValidIso('')).toBe(false)
|
||||||
|
})
|
||||||
|
it('rejects an impossible date', () => {
|
||||||
|
expect(isValidIso('2026-02-30')).toBe(false)
|
||||||
|
expect(isValidIso('2026-13-01')).toBe(false)
|
||||||
|
})
|
||||||
|
it('accepts Feb 29 on a leap year and rejects it otherwise', () => {
|
||||||
|
expect(isValidIso('2024-02-29')).toBe(true)
|
||||||
|
expect(isValidIso('2026-02-29')).toBe(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('formatIsoToDisplay', () => {
|
||||||
|
it('formats ISO to DD/MM/YYYY', () => {
|
||||||
|
expect(formatIsoToDisplay('2026-05-19')).toBe('19/05/2026')
|
||||||
|
})
|
||||||
|
it('returns empty string for null or invalid input', () => {
|
||||||
|
expect(formatIsoToDisplay(null)).toBe('')
|
||||||
|
expect(formatIsoToDisplay('nope')).toBe('')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('parseDisplayToIso', () => {
|
||||||
|
it('parses DD/MM/YYYY to ISO', () => {
|
||||||
|
expect(parseDisplayToIso('19/05/2026')).toBe('2026-05-19')
|
||||||
|
})
|
||||||
|
it('returns null for malformed or impossible input', () => {
|
||||||
|
expect(parseDisplayToIso('2026-05-19')).toBeNull()
|
||||||
|
expect(parseDisplayToIso('31/02/2026')).toBeNull()
|
||||||
|
expect(parseDisplayToIso('')).toBeNull()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('isDateInRange', () => {
|
||||||
|
it('returns true when no bounds are given', () => {
|
||||||
|
expect(isDateInRange('2026-05-19')).toBe(true)
|
||||||
|
})
|
||||||
|
it('respects the min bound (inclusive)', () => {
|
||||||
|
expect(isDateInRange('2026-05-19', '2026-05-19')).toBe(true)
|
||||||
|
expect(isDateInRange('2026-05-18', '2026-05-19')).toBe(false)
|
||||||
|
})
|
||||||
|
it('respects the max bound (inclusive)', () => {
|
||||||
|
expect(isDateInRange('2026-05-19', undefined, '2026-05-19')).toBe(true)
|
||||||
|
expect(isDateInRange('2026-05-20', undefined, '2026-05-19')).toBe(false)
|
||||||
|
})
|
||||||
|
it('respects both bounds', () => {
|
||||||
|
expect(isDateInRange('2026-05-15', '2026-05-10', '2026-05-20')).toBe(true)
|
||||||
|
expect(isDateInRange('2026-05-25', '2026-05-10', '2026-05-20')).toBe(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
26
app/components/malio/date/composables/dateFormat.ts
Normal file
26
app/components/malio/date/composables/dateFormat.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
export function isValidIso(iso: string): boolean {
|
||||||
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(iso)) return false
|
||||||
|
const [y, m, d] = iso.split('-').map(Number)
|
||||||
|
const date = new Date(y, m - 1, d)
|
||||||
|
return date.getFullYear() === y && date.getMonth() === m - 1 && date.getDate() === d
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatIsoToDisplay(iso: string | null): string {
|
||||||
|
if (!iso || !isValidIso(iso)) return ''
|
||||||
|
const [y, m, d] = iso.split('-')
|
||||||
|
return `${d}/${m}/${y}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseDisplayToIso(display: string): string | null {
|
||||||
|
const match = /^(\d{2})\/(\d{2})\/(\d{4})$/.exec(display.trim())
|
||||||
|
if (!match) return null
|
||||||
|
const [, dd, mm, yyyy] = match
|
||||||
|
const iso = `${yyyy}-${mm}-${dd}`
|
||||||
|
return isValidIso(iso) ? iso : null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isDateInRange(iso: string, min?: string, max?: string): boolean {
|
||||||
|
if (min && iso < min) return false
|
||||||
|
if (max && iso > max) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user