diff --git a/src/dateTime/__tests__/format.ts b/src/dateTime/__tests__/format.ts index a7fd91e..871c6b3 100644 --- a/src/dateTime/__tests__/format.ts +++ b/src/dateTime/__tests__/format.ts @@ -1,6 +1,7 @@ -import {HTML5_INPUT_FORMATS} from '../../constants'; +import {HTML5_INPUT_FORMATS, englishFormats} from '../../constants'; import {settings} from '../../settings'; import {dateTime, dateTimeUtc} from '../dateTime'; +import {expandFormat} from '../format'; afterEach(() => { settings.updateLocale({weekStart: 1, yearStart: 1}); @@ -342,3 +343,27 @@ test('Y token', () => { expect(dateTime({input: [9999]}).format('Y')).toBe('9999'); // 'format 9999 with Y' expect(dateTime({input: [10000]}).format('Y')).toBe('+10000'); // 'format 10000 with Y' }); + +test('expand format', () => { + expect(expandFormat('[L]', englishFormats)).toBe('[L]'); + expect(expandFormat('L', englishFormats)).toBe(englishFormats.L); + expect(expandFormat('LL', englishFormats)).toBe(englishFormats.LL); + expect(expandFormat('LLL', englishFormats)).toBe(englishFormats.LLL); + expect(expandFormat('LLLL', englishFormats)).toBe(englishFormats.LLLL); + expect(expandFormat('LT', englishFormats)).toBe(englishFormats.LT); + expect(expandFormat('LTS', englishFormats)).toBe(englishFormats.LTS); + expect(expandFormat('[L]L', englishFormats)).toBe(`[L]${englishFormats.L}`); + expect(expandFormat('[L]T', englishFormats)).toBe(`[L]T`); + expect(expandFormat('l', englishFormats)).toBe('M/D/YYYY'); + expect(expandFormat('ll', englishFormats)).toBe('MMM D, YYYY'); + expect(expandFormat('lll', englishFormats)).toBe('MMM D, YYYY h:mm A'); + expect(expandFormat('llll', englishFormats)).toBe('ddd, MMM D, YYYY h:mm A'); + expect(expandFormat('l', {...englishFormats, l: 'short format'})).toBe('short format'); + expect(expandFormat('ll', {...englishFormats, ll: 'short format'})).toBe('short format'); + expect(expandFormat('lll', {...englishFormats, lll: 'short format'})).toBe('short format'); + expect(expandFormat('llll', {...englishFormats, llll: 'short format'})).toBe('short format'); + expect(expandFormat('llll', {...englishFormats, l: 'L', ll: 'l', lll: 'll', llll: 'lll'})).toBe( + englishFormats.L, + ); + expect(expandFormat('l', {...englishFormats, l: 'l'})).toBe('l'); +}); diff --git a/src/dateTime/format.ts b/src/dateTime/format.ts index ce51a60..a31002c 100644 --- a/src/dateTime/format.ts +++ b/src/dateTime/format.ts @@ -4,37 +4,44 @@ import type {Locale, LongDateFormat} from '../settings/types'; import {parseZoneInfo} from '../timeZone'; import type {DateTime} from '../typings'; -function getShortLocalizedFormatFromLongLocalizedFormat(formatBis: string) { - return formatBis.replace( +function getShortLocalizedFormatFromLongLocalizedFormat(format: string) { + return format.replace( /(\[[^\]]+])|(MMMM|MM|DD|dddd)/g, (_: string, escapeSequence: string, localizedFormat: string) => escapeSequence || localizedFormat.slice(1), ); } +const localizedFormattingTokens = /(\[[^\]]*])|(LTS?|l{1,4}|L{1,4})/g; export function expandFormat( format: string, formats: LongDateFormat = settings.getLocaleData().formats ?? englishFormats, ) { - return format.replace( - /(\[[^\]]*])|(LTS?|l{1,4}|L{1,4})/g, - (_: string, escapeSequence: string, localizedFormat: keyof LongDateFormat) => { - if (localizedFormat) { - if (localizedFormat in englishFormats) { + let result = format; + for (let i = 0; i < 5; i++) { + const expandedFormat = result.replace( + localizedFormattingTokens, + (_: string, escapeSequence: string, localizedFormat: keyof LongDateFormat) => { + if (localizedFormat) { + const LongLocalizedFormat = + localizedFormat.toUpperCase() as keyof typeof englishFormats; return ( formats[localizedFormat] || - englishFormats[localizedFormat as keyof typeof englishFormats] + englishFormats[localizedFormat as keyof typeof englishFormats] || + getShortLocalizedFormatFromLongLocalizedFormat( + formats[LongLocalizedFormat] || englishFormats[LongLocalizedFormat], + ) ); } - const LongLocalizedFormat = - localizedFormat.toUpperCase() as keyof typeof englishFormats; - return getShortLocalizedFormatFromLongLocalizedFormat( - formats[LongLocalizedFormat] || englishFormats[LongLocalizedFormat], - ); - } - return escapeSequence; - }, - ); + return escapeSequence; + }, + ); + if (expandedFormat === result) { + break; + } + result = expandedFormat; + } + return result; } export const FORMAT_DEFAULT = 'YYYY-MM-DDTHH:mm:ssZ';