From 56dbd6e29aa655678df3ec560a9d0bcfd7488130 Mon Sep 17 00:00:00 2001 From: Ben Meyrick Date: Wed, 8 Feb 2023 17:05:04 +0000 Subject: [PATCH] Improve testing and documentation (#3) * Improve testing and documentation * Improve coverage --- README.md | 67 ++++++++++++++-- src/data/numbering-systems.spec.ts | 40 +++++----- src/format.spec.ts | 23 +++--- src/format.ts | 17 +++- src/formats/ago/ago.spec.ts | 80 +++++++++---------- src/formats/ago/ago.ts | 1 + src/formats/atSeconds/atSeconds.ts | 1 + src/formats/chinese/chinese.spec.ts | 4 +- src/formats/chinese/chinese.ts | 5 +- src/formats/dayMonth/dayMonth.ts | 1 + src/formats/dayMonthYear/dayMonthYear.ts | 1 + src/formats/dayMonthname/dayMonthname.ts | 1 + .../dayMonthnameYear/dayMonthnameYear.ts | 1 + src/formats/microsoftJson/microsoftJson.ts | 1 + src/formats/monthDay/monthDay.ts | 1 + src/formats/monthDayYear/monthDayYear.spec.ts | 36 +++++---- src/formats/monthDayYear/monthDayYear.ts | 1 + src/formats/monthnameDay/monthnameDay.ts | 1 + .../monthnameDayYear/monthnameDayYear.ts | 1 + src/formats/time12Hours/time12Hours.spec.ts | 16 ++-- src/formats/time12Hours/time12Hours.ts | 1 + src/formats/time24Hours/time24Hours.spec.ts | 42 ---------- src/formats/time24Hours/time24Hours.ts | 1 + src/formats/today/today.spec.ts | 8 +- src/formats/today/today.ts | 1 + src/formats/twitter/twitter.spec.ts | 4 +- src/formats/twitter/twitter.ts | 1 + src/formats/yearMonthDay/yearMonthDay.spec.ts | 26 +++++- src/formats/yearMonthDay/yearMonthDay.ts | 74 ++++++++++++++++- src/index.ts | 2 +- src/locale-helper.ts | 12 ++- src/localeHelper.spec.ts | 10 +-- src/models/date-object.ts | 2 +- src/parser.spec.ts | 16 ++-- src/test-fixtures/generate-formats.ts | 8 +- src/test-fixtures/test-dates.ts | 2 +- src/test-fixtures/test-parser.ts | 2 +- 37 files changed, 331 insertions(+), 180 deletions(-) diff --git a/README.md b/README.md index fd0bb80..b0289c5 100644 --- a/README.md +++ b/README.md @@ -259,12 +259,6 @@ incorporated. - 9:26pm - 9pm -year month day - -- 2016-09-24 -- 2016-9-24 -- 20160924 - day monthname year - Wednesday, 01 January 2020 @@ -292,21 +286,82 @@ month day year - 03/14/2020 - 03-14-2020 +- 03.14.2020 +- 03 14 2020 - 3/14/2020 - 3-14-2020 +- 3.14.2020 +- 3 14 2020 - 03/14/20 - 03-14-20 +- 03.14.20 +- 03 14 20 +- 3/14/20 +- 3-14-20 +- 3.14.20 +- 3 14 20 day month year - 14/03/2020 - 14.03.2020 +- 14-03-2020 +- 14 03 2020 - 14/3/2020 - 14.3.2020 +- 14-3-2020 +- 14 3 2020 - 14/03/20 - 14.03.20 +- 14-03-20 +- 14 03 20 - 14/3/20 - 14.3.20 +- 14-3-20 +- 14 3 20 + +year month day + +- 2016/09/24 +- 2016/09/24 +- 2016/9/24 +- 2016/9/24 +- 16/09/24 +- 16/09/24 +- 16/9/24 +- 16/9/24 +- 2016-09-24 +- 2016-09-24 +- 2016-9-24 +- 2016-9-24 +- 16-09-24 +- 16-09-24 +- 16-9-24 +- 16-9-24 +- 2016 09 24 +- 2016 09 24 +- 2016 9 24 +- 2016 9 24 +- 16 09 24 +- 16 09 24 +- 16 9 24 +- 16 9 24 +- 2016.09.24 +- 2016.09.24 +- 2016.9.24 +- 2016.9.24 +- 16.09.24 +- 16.09.24 +- 16.9.24 +- 16.9.24 +- 20160924 +- 20160924 +- 2016924 +- 2016924 +- 160924 +- 160924 +- 16924 +- 16924 relative time diff --git a/src/data/numbering-systems.spec.ts b/src/data/numbering-systems.spec.ts index 3fe369c..d747678 100644 --- a/src/data/numbering-systems.spec.ts +++ b/src/data/numbering-systems.spec.ts @@ -18,7 +18,7 @@ describe('unicode numbering systems', () => { '٩': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "arabext"', () => { @@ -38,7 +38,7 @@ describe('unicode numbering systems', () => { '۹': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "bali"', () => { @@ -58,7 +58,7 @@ describe('unicode numbering systems', () => { '᭙': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "beng"', () => { @@ -78,7 +78,7 @@ describe('unicode numbering systems', () => { '৯': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "deva"', () => { @@ -98,7 +98,7 @@ describe('unicode numbering systems', () => { '९': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "fullwide" and "hanidec"', () => { @@ -139,7 +139,7 @@ describe('unicode numbering systems', () => { 九: 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); expect(hanidec).toEqual(expected); }); @@ -160,7 +160,7 @@ describe('unicode numbering systems', () => { '૯': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "khmr"', () => { @@ -180,7 +180,7 @@ describe('unicode numbering systems', () => { '៩': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "knda"', () => { @@ -200,7 +200,7 @@ describe('unicode numbering systems', () => { '೯': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "laoo"', () => { @@ -220,7 +220,7 @@ describe('unicode numbering systems', () => { '໙': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "latn"', () => { @@ -260,7 +260,7 @@ describe('unicode numbering systems', () => { 九: 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "limb"', () => { @@ -280,7 +280,7 @@ describe('unicode numbering systems', () => { '᥏': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "mlym"', () => { @@ -300,7 +300,7 @@ describe('unicode numbering systems', () => { '൯': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "mong"', () => { @@ -320,7 +320,7 @@ describe('unicode numbering systems', () => { '᠙': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "mymr"', () => { @@ -340,7 +340,7 @@ describe('unicode numbering systems', () => { '၉': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "orya"', () => { @@ -360,7 +360,7 @@ describe('unicode numbering systems', () => { '୯': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "tamldec"', () => { @@ -380,7 +380,7 @@ describe('unicode numbering systems', () => { '௯': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "telu"', () => { @@ -400,7 +400,7 @@ describe('unicode numbering systems', () => { '౯': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "thai"', () => { @@ -420,7 +420,7 @@ describe('unicode numbering systems', () => { '๙': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should build "tibt"', () => { @@ -440,6 +440,6 @@ describe('unicode numbering systems', () => { '༩': 9, }, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); }); diff --git a/src/format.spec.ts b/src/format.spec.ts index 4554419..2c06e1f 100644 --- a/src/format.spec.ts +++ b/src/format.spec.ts @@ -3,7 +3,7 @@ import { Format } from './format'; describe('Format', () => { it('should require units or handler', () => { function missingUnitsAndHandler() { - return new Format({ template: '' }); + return new Format({ template: '', name: 'test' }); } expect(missingUnitsAndHandler).toThrowError(); @@ -11,21 +11,21 @@ describe('Format', () => { it('should require template or matcher', () => { function missingTemplateAndRegex() { - return new Format({ units: [] }); + return new Format({ units: [], name: 'test' }); } expect(missingTemplateAndRegex).toThrowError(); }); it('should build RegExp from template', () => { - const format = new Format({ handler: () => null, template: 'year:_YEAR_' }); + const format = new Format({ handler: () => null, template: 'year:_YEAR_', name: 'test' }); const regex = format.getRegExp(); expect(regex).toEqual(/year:[1-9]\d{3}|\d{2}/i); }); it('should getMatches()', () => { - const format = new Format({ handler: () => null, matcher: /foo:(\d)(\d)/ }); + const format = new Format({ handler: () => null, matcher: /foo:(\d)(\d)/, name: 'test' }); const matches = [...format.getMatches('foo:42')!]; expect(matches).toEqual(['foo:42', '4', '2']); @@ -35,49 +35,54 @@ describe('Format', () => { const format = new Format({ units: ['year', 'month', 'day'], matcher: /./, + name: 'test', }); const actual = format.toDateTime([null, '2020', '10', '13']); - expect(actual).toEqual({ year: 2020, month: 10, day: 13 }); + expect(actual).toEqual(expect.objectContaining({ year: 2020, month: 10, day: 13 })); }); it('should convert monthname matches to Object', () => { const format = new Format({ units: ['year', 'month', 'day'], matcher: /./, + name: 'test', }); const actual = format.toDateTime([null, '2020', 'oct', '13']); - expect(actual).toEqual({ year: 2020, month: 10, day: 13 }); + expect(actual).toEqual(expect.objectContaining({ year: 2020, month: 10, day: 13 })); }); it('should convert 2-digit years', () => { const format = new Format({ units: ['year', 'month', 'day', 'minute'], matcher: /./, + name: 'test', }); const actual = format.toDateTime([null, '20', 'october', '13', '59']); - expect(actual).toEqual({ year: 2020, month: 10, day: 13, minute: 59 }); + expect(actual).toEqual(expect.objectContaining({ year: 2020, month: 10, day: 13, minute: 59 })); }); it('should attempt to parse', () => { const format = new Format({ matcher: /(\d+)m (\d+)s/, units: ['minute', 'second'], + name: 'test', }); const actual = format.attempt('56m 22s'); - expect(actual).toEqual({ minute: 56, second: 22 }); + expect(actual).toMatchObject({ minute: 56, second: 22 }); }); it('should trim()', () => { const format = new Format({ matcher: /^(\d+)s (\d+)ms$/, units: ['second', 'millisecond'], + name: 'test', }); const actual = format.attempt(' 56s 813ms\t'); - expect(actual).toEqual({ second: 56, millisecond: 813 }); + expect(actual).toEqual(expect.objectContaining({ second: 56, millisecond: 813 })); }); }); diff --git a/src/format.ts b/src/format.ts index b4a4e23..0b46405 100644 --- a/src/format.ts +++ b/src/format.ts @@ -7,6 +7,11 @@ import { Parser } from './parser'; export type FormatHandler = (matches: Array, locale: string) => DateObject | null; export interface FormatDefinition { + /** + * Name of the formatter + */ + name: string; + /** * A template for RegExp that can handle multiple languages */ @@ -39,6 +44,11 @@ export interface FormatDefinition { } export class Format implements FormatDefinition { + /** + * Name of the formatter + */ + public readonly name: string; + /** * A template for RegExp that can handle multiple languages */ @@ -74,7 +84,7 @@ export class Format implements FormatDefinition { */ private readonly regexByLocale: Record = {}; - constructor({ template, matcher, units, handler, locales }: FormatDefinition) { + constructor({ name, template, matcher, units, handler, locales }: FormatDefinition) { if (!Array.isArray(units) && typeof handler !== 'function') { throw new Error('new Format must receive a "units" array or "handler" function'); } @@ -83,6 +93,7 @@ export class Format implements FormatDefinition { throw new Error('new Format must receive a "template" string or "matcher" RegExp'); } + this.name = name; this.template = template; this.units = units; this.matcher = matcher; @@ -129,7 +140,7 @@ export class Format implements FormatDefinition { const locHelper = LocaleHelper.factory(locale); if (this.units) { - return locHelper.getObject(this.units, matches); + return locHelper.getObject(this.units, matches, this.name); } const dateObject = this.handler!(matches, locale); @@ -138,7 +149,7 @@ export class Format implements FormatDefinition { return null; } - return locHelper.castObject(dateObject); + return locHelper.castObject(dateObject, this.name); } /** diff --git a/src/formats/ago/ago.spec.ts b/src/formats/ago/ago.spec.ts index 3bdc73a..30b8fd5 100644 --- a/src/formats/ago/ago.spec.ts +++ b/src/formats/ago/ago.spec.ts @@ -20,7 +20,7 @@ describe('(amount) (unit) ago', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); expect(actual2).toEqual(new Date(Date.UTC(2012, 2 /* march */, 1, 15, 16, 0, 200))); }); @@ -36,7 +36,7 @@ describe('(amount) (unit) ago', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "2 weeks"', () => { @@ -51,7 +51,7 @@ describe('(amount) (unit) ago', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "2 days ago"', () => { @@ -66,7 +66,7 @@ describe('(amount) (unit) ago', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "18 hours ago"', () => { @@ -81,7 +81,7 @@ describe('(amount) (unit) ago', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "1 minute ago"', () => { @@ -96,7 +96,7 @@ describe('(amount) (unit) ago', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "30 seconds ago"', () => { @@ -111,7 +111,7 @@ describe('(amount) (unit) ago', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "199 milliseconds ago"', () => { @@ -126,7 +126,7 @@ describe('(amount) (unit) ago', () => { millisecond: 1, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); }); @@ -148,7 +148,7 @@ describe('-(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "-7 months"', () => { @@ -163,7 +163,7 @@ describe('-(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "-2 days"', () => { @@ -178,7 +178,7 @@ describe('-(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "-2 weeks"', () => { @@ -193,7 +193,7 @@ describe('-(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "-18 hours"', () => { @@ -208,7 +208,7 @@ describe('-(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "-1 minute"', () => { @@ -223,7 +223,7 @@ describe('-(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "-30 seconds"', () => { @@ -238,7 +238,7 @@ describe('-(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "-199 milliseconds"', () => { @@ -253,7 +253,7 @@ describe('-(amount) (unit)', () => { millisecond: 1, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); }); @@ -275,7 +275,7 @@ describe('in (amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "in 17 months"', () => { @@ -290,7 +290,7 @@ describe('in (amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "in 1 week"', () => { @@ -305,7 +305,7 @@ describe('in (amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "in 2 days"', () => { @@ -320,7 +320,7 @@ describe('in (amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "in 18 hours"', () => { @@ -335,7 +335,7 @@ describe('in (amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "in 1 minute"', () => { @@ -350,7 +350,7 @@ describe('in (amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "in 30 seconds"', () => { @@ -365,7 +365,7 @@ describe('in (amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "in 199 milliseconds"', () => { @@ -380,7 +380,7 @@ describe('in (amount) (unit)', () => { millisecond: 399, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); }); @@ -402,7 +402,7 @@ describe('+(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+17 months"', () => { @@ -417,7 +417,7 @@ describe('+(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+2 weeks"', () => { @@ -432,7 +432,7 @@ describe('+(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+2 days"', () => { @@ -447,7 +447,7 @@ describe('+(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+18 hours"', () => { @@ -462,7 +462,7 @@ describe('+(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+1 minute"', () => { @@ -477,7 +477,7 @@ describe('+(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+30 seconds"', () => { @@ -492,7 +492,7 @@ describe('+(amount) (unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+199 milliseconds"', () => { @@ -507,7 +507,7 @@ describe('+(amount) (unit)', () => { millisecond: 399, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); }); @@ -529,7 +529,7 @@ describe('+(amount)(short unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+17M"', () => { @@ -544,7 +544,7 @@ describe('+(amount)(short unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+2w"', () => { @@ -559,7 +559,7 @@ describe('+(amount)(short unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+2d"', () => { @@ -574,7 +574,7 @@ describe('+(amount)(short unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+18h"', () => { @@ -589,7 +589,7 @@ describe('+(amount)(short unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+1m"', () => { @@ -604,7 +604,7 @@ describe('+(amount)(short unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+30s"', () => { @@ -619,7 +619,7 @@ describe('+(amount)(short unit)', () => { millisecond: 200, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "+199ms"', () => { @@ -634,6 +634,6 @@ describe('+(amount)(short unit)', () => { millisecond: 399, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); }); diff --git a/src/formats/ago/ago.ts b/src/formats/ago/ago.ts index d29922f..599c686 100644 --- a/src/formats/ago/ago.ts +++ b/src/formats/ago/ago.ts @@ -2,6 +2,7 @@ import { UNIT_SHORTCUTS } from '../../data/unit-shortcuts'; import { Format } from '../../format'; export const ago = new Format({ + name: 'ago', /* prettier-ignore */ // $1 $2 $3 $4 matcher: /^(\+|-|in|) ?([\d.]+) ?(years?|months?|weeks?|days?|hours?|minutes?|seconds?|milliseconds?|ms|s|m|h|w|d|M|y)( ago)?$/i, diff --git a/src/formats/atSeconds/atSeconds.ts b/src/formats/atSeconds/atSeconds.ts index c8a2795..4d00a09 100644 --- a/src/formats/atSeconds/atSeconds.ts +++ b/src/formats/atSeconds/atSeconds.ts @@ -1,6 +1,7 @@ import { Format } from '../../format'; export const atSeconds = new Format({ + name: 'atSeconds', template: '^@(\\d+)$', handler: matches => { const seconds = parseInt(matches[1]!, 10); diff --git a/src/formats/chinese/chinese.spec.ts b/src/formats/chinese/chinese.spec.ts index 36f78d1..622a2b3 100644 --- a/src/formats/chinese/chinese.spec.ts +++ b/src/formats/chinese/chinese.spec.ts @@ -15,7 +15,7 @@ describe('chinese with full-width digits', () => { it('should handle date', () => { const actual = StringToDate.parseToObject('2017年08月31日'); const expected = { year: 2017, month: 8, day: 31 }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); }); @@ -25,6 +25,6 @@ describe('chinese with full-width digits', () => { it('should handle date', () => { const actual = StringToDate.parseToObject('二〇一七年〇八月三一日'); const expected = { year: 2017, month: 8, day: 31 }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); }); diff --git a/src/formats/chinese/chinese.ts b/src/formats/chinese/chinese.ts index 87ee11f..673c191 100644 --- a/src/formats/chinese/chinese.ts +++ b/src/formats/chinese/chinese.ts @@ -4,7 +4,10 @@ import { LocaleHelper } from '../../locale-helper'; let locHelper: LocaleHelper; +const name = 'chinese'; + export const chinese = new Format({ + name, /* prettier-ignore */ // $1 $2 $3 template: `^(${CHINESE_GROUP}{4}|${CHINESE_GROUP}{2})\\s*年\\s*(${CHINESE_GROUP}{1,2})\\s*月\\s*(${CHINESE_GROUP}{1,2})\\s*日$`, @@ -16,6 +19,6 @@ export const chinese = new Format({ locHelper.buildDigits(); } - return locHelper.castObject({ year: year!, month: month!, day: day! }); + return locHelper.castObject({ year: year!, month: month!, day: day! }, name); }, }); diff --git a/src/formats/dayMonth/dayMonth.ts b/src/formats/dayMonth/dayMonth.ts index 72f6c66..5117417 100644 --- a/src/formats/dayMonth/dayMonth.ts +++ b/src/formats/dayMonth/dayMonth.ts @@ -1,6 +1,7 @@ import { Format } from '../../format'; export const dayMonth = new Format({ + name: 'dayMonth', /* prettier-ignore */ // $1 $2 template: "^(_DAY_)[\\/. ](_MONTH_)$", diff --git a/src/formats/dayMonthYear/dayMonthYear.ts b/src/formats/dayMonthYear/dayMonthYear.ts index f4efda1..85b6736 100644 --- a/src/formats/dayMonthYear/dayMonthYear.ts +++ b/src/formats/dayMonthYear/dayMonthYear.ts @@ -1,6 +1,7 @@ import { Format } from '../../format'; export const dayMonthYear = new Format({ + name: 'dayMonthYear', /* prettier-ignore */ // $1 $2 $3 $4 template: "^(_DAY_)([\\/. -])(_MONTH_)\\2(_YEAR_)$", diff --git a/src/formats/dayMonthname/dayMonthname.ts b/src/formats/dayMonthname/dayMonthname.ts index 46b26c3..7a82d86 100644 --- a/src/formats/dayMonthname/dayMonthname.ts +++ b/src/formats/dayMonthname/dayMonthname.ts @@ -1,6 +1,7 @@ import { Format } from '../../format'; export const dayMonthname = new Format({ + name: 'dayMonthname', /* prettier-ignore */ // $1 $2 template: "^(_DAY_)(?:_ORDINAL_)?[ -](_MONTHNAME_)$", diff --git a/src/formats/dayMonthnameYear/dayMonthnameYear.ts b/src/formats/dayMonthnameYear/dayMonthnameYear.ts index bfa96ed..fad896a 100644 --- a/src/formats/dayMonthnameYear/dayMonthnameYear.ts +++ b/src/formats/dayMonthnameYear/dayMonthnameYear.ts @@ -1,6 +1,7 @@ import { Format } from '../../format'; export const dayMonthnameYear = new Format({ + name: 'dayMonthnameYear', /* prettier-ignore */ // $1 $2 $3 $4 template: "^(?:(?:_DAYNAME_),? )?(_DAY_)(?:_ORDINAL_)?([ -])(_MONTHNAME_)\\2(_YEAR_)$", diff --git a/src/formats/microsoftJson/microsoftJson.ts b/src/formats/microsoftJson/microsoftJson.ts index 8cc664c..8641652 100644 --- a/src/formats/microsoftJson/microsoftJson.ts +++ b/src/formats/microsoftJson/microsoftJson.ts @@ -1,6 +1,7 @@ import { Format } from '../../format'; export const microsoftJson = new Format({ + name: 'microsoftJson', matcher: /^\/Date\((\d+)([+-]\d{4})?\)\/$/, handler: matches => { const milliseconds = parseInt(matches[1]!, 10); diff --git a/src/formats/monthDay/monthDay.ts b/src/formats/monthDay/monthDay.ts index 8d16da9..505f5e5 100644 --- a/src/formats/monthDay/monthDay.ts +++ b/src/formats/monthDay/monthDay.ts @@ -1,6 +1,7 @@ import { Format } from '../../format'; export const monthDay = new Format({ + name: 'monthDay', /* prettier-ignore */ // $1 $2 template: "^(_MONTH_)(?:[\\/. -])(_DAY_)$", diff --git a/src/formats/monthDayYear/monthDayYear.spec.ts b/src/formats/monthDayYear/monthDayYear.spec.ts index d4833e0..8acdde9 100644 --- a/src/formats/monthDayYear/monthDayYear.spec.ts +++ b/src/formats/monthDayYear/monthDayYear.spec.ts @@ -38,29 +38,35 @@ describe('month day year for other locales', () => { it('should recognize day month year with slashes instead', () => { const actual = StringToDate.parseToObject('5/3/2021', 'FR'); - expect(actual).toEqual({ - month: 3, - day: 5, - year: 2021, - }); + expect(actual).toEqual( + expect.objectContaining({ + month: 3, + day: 5, + year: 2021, + }) + ); }); it('should recognize day month year with dashes instead', () => { const actual = StringToDate.parseToObject('5-3-2021', 'FR'); - expect(actual).toEqual({ - month: 3, - day: 5, - year: 2021, - }); + expect(actual).toEqual( + expect.objectContaining({ + month: 3, + day: 5, + year: 2021, + }) + ); }); it('should recognize day month year with dashes instead', () => { const actual = StringToDate.parseToObject('5 3 2021', 'en-US'); - expect(actual).toEqual({ - month: 5, - day: 3, - year: 2021, - }); + expect(actual).toEqual( + expect.objectContaining({ + month: 5, + day: 3, + year: 2021, + }) + ); }); }); diff --git a/src/formats/monthDayYear/monthDayYear.ts b/src/formats/monthDayYear/monthDayYear.ts index b6e32c2..d172195 100644 --- a/src/formats/monthDayYear/monthDayYear.ts +++ b/src/formats/monthDayYear/monthDayYear.ts @@ -1,6 +1,7 @@ import { Format } from '../../format'; export const monthDayYear = new Format({ + name: 'monthDayYear', /* prettier-ignore */ // $1 $2 $3 $4 template: "^(_MONTH_)([\\/. -])(_DAY_)\\2(_YEAR_)$", diff --git a/src/formats/monthnameDay/monthnameDay.ts b/src/formats/monthnameDay/monthnameDay.ts index 6f97b60..5358d94 100644 --- a/src/formats/monthnameDay/monthnameDay.ts +++ b/src/formats/monthnameDay/monthnameDay.ts @@ -1,6 +1,7 @@ import { Format } from '../../format'; export const monthnameDay = new Format({ + name: 'monthnameDay', /* prettier-ignore */ // $1 $2 template: '^(?:(?:_DAYNAME_),? )?(_MONTHNAME_)? (_DAY_)(?:_ORDINAL_)?$', diff --git a/src/formats/monthnameDayYear/monthnameDayYear.ts b/src/formats/monthnameDayYear/monthnameDayYear.ts index 4789ed7..e290228 100644 --- a/src/formats/monthnameDayYear/monthnameDayYear.ts +++ b/src/formats/monthnameDayYear/monthnameDayYear.ts @@ -1,6 +1,7 @@ import { Format } from '../../format'; export const monthnameDayYear = new Format({ + name: 'monthnameDayYear', /* prettier-ignore */ // $1 $2 $3 template: '^(?:(?:_DAYNAME_),? )?(_MONTHNAME_)? (_DAY_)(?:_ORDINAL_)?,? (_YEAR_)$', diff --git a/src/formats/time12Hours/time12Hours.spec.ts b/src/formats/time12Hours/time12Hours.spec.ts index 96050d1..c62a63f 100644 --- a/src/formats/time12Hours/time12Hours.spec.ts +++ b/src/formats/time12Hours/time12Hours.spec.ts @@ -7,7 +7,7 @@ describe('12 hour time', () => { hour: 20, }; - expect(actual).toMatchObject(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle invalid date: "Foobarbaz at 8pm"', () => { @@ -22,7 +22,7 @@ describe('12 hour time', () => { hour: 4, }; - expect(actual).toMatchObject(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle minutes: "8:15pm"', () => { @@ -32,7 +32,7 @@ describe('12 hour time', () => { minute: 15, }; - expect(actual).toMatchObject(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle seconds: "8:15:14am"', () => { @@ -43,7 +43,7 @@ describe('12 hour time', () => { second: 14, }; - expect(actual).toMatchObject(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle leap seconds: "11:59:60pm"', () => { @@ -54,7 +54,7 @@ describe('12 hour time', () => { second: 60, }; - expect(actual).toMatchObject(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle dates: "March 14, 2015 9:26pm"', () => { @@ -67,7 +67,7 @@ describe('12 hour time', () => { minute: 26, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle dates joined with "at": "March 14, 2015 at 9:26:53 am"', () => { @@ -81,7 +81,7 @@ describe('12 hour time', () => { second: 53, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle dates with commas: "4/19/2021, 10:04:02 AM"', () => { @@ -95,6 +95,6 @@ describe('12 hour time', () => { second: 2, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); }); diff --git a/src/formats/time12Hours/time12Hours.ts b/src/formats/time12Hours/time12Hours.ts index d1030c2..848b619 100644 --- a/src/formats/time12Hours/time12Hours.ts +++ b/src/formats/time12Hours/time12Hours.ts @@ -5,6 +5,7 @@ import { DateObject } from '../../models'; // lots of 12h time such as "11:59", "11:59pm", "11:59:33 pm", "11:59:33 p.m." export const time12Hours = new Format({ + name: 'time12Hours', /* prettier-ignore */ // $1 $2 $3 $4 $5 template: '^(.*?)_SPACE_*(?:at|on|T|)_SPACE_*(_H12_|_H24_)(?:\\:(_MIN_)(?:\\:(_SEC_))?)?_SPACE_*(_MERIDIEM_)$', diff --git a/src/formats/time24Hours/time24Hours.spec.ts b/src/formats/time24Hours/time24Hours.spec.ts index 9d5b938..83c5a04 100644 --- a/src/formats/time24Hours/time24Hours.spec.ts +++ b/src/formats/time24Hours/time24Hours.spec.ts @@ -5,9 +5,6 @@ testDates({ name: '24 hour time', locales: ['ar-SA', 'bn-BD', 'bn-IN', 'en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -19,9 +16,6 @@ testDates({ name: '24 hour time', locales: ['ar-SA', 'bn-BD', 'bn-IN', 'en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -44,9 +38,6 @@ testDates({ name: '24 hour time with milliseconds', locales: ['en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -59,9 +50,6 @@ testDates({ name: '24 hour time with 2-digit milliseconds', locales: ['en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -74,9 +62,6 @@ testDates({ name: '24 hour time with 1-digit milliseconds', locales: ['en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -89,9 +74,6 @@ testDates({ name: '24 hour time with microseconds', locales: ['en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -104,9 +86,6 @@ testDates({ name: '24 hour time with nanoseconds', locales: ['en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -119,9 +98,6 @@ testDates({ name: '24 hour time with timezone name - "MST"', locales: ['ar-SA', 'bn-BD', 'bn-IN', 'en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -134,9 +110,6 @@ testDates({ name: '24 hour time with long timezone name - "Eastern Daylight Time"', locales: ['ar-SA', 'bn-BD', 'bn-IN', 'en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -149,9 +122,6 @@ testDates({ name: '24 hour time with GMT hours:minutes', locales: ['en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -164,9 +134,6 @@ testDates({ name: '24 hour time with GMT hours:minutes and tz name', locales: ['en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -179,9 +146,6 @@ testDates({ name: '24 hour time with GMT hours', locales: ['en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -194,9 +158,6 @@ testDates({ name: '24 hour time with zone -hours:minutes', locales: ['en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, @@ -209,9 +170,6 @@ testDates({ name: '24 hour time with zone +hoursminutes', locales: ['en-US'], expected: { - year: 2020, - month: 10, - day: 6, hour: 17, minute: 41, second: 28, diff --git a/src/formats/time24Hours/time24Hours.ts b/src/formats/time24Hours/time24Hours.ts index 8a78f10..63900eb 100644 --- a/src/formats/time24Hours/time24Hours.ts +++ b/src/formats/time24Hours/time24Hours.ts @@ -6,6 +6,7 @@ import { DateObject } from '../../models'; // lots of 24h time such as "23:59", "T23:59:59+0700", "23:59:59 GMT-05:00", "23:59:59 CST", "T23:59:59Z" export const time24Hours = new Format({ + name: 'time24Hours', /* prettier-ignore */ // $1 $2 $3 $4 $5 $6 $7 template: '^(.*?)_SPACE_*(?:at|on|T|)_SPACE_*(_H24_)\\:(_MIN_)(?:\\:(_SEC_)(?:[\\.,](_MS_))?)?_SPACE_*(?:GMT)?_SPACE_*(_OFFSET_)?_SPACE_*(_ZONE_)?$', diff --git a/src/formats/today/today.spec.ts b/src/formats/today/today.spec.ts index 10d67d7..8bb35c0 100644 --- a/src/formats/today/today.spec.ts +++ b/src/formats/today/today.spec.ts @@ -18,7 +18,7 @@ describe('now, today, yesterday and tomorrow', () => { millisecond: 999, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "today"', () => { @@ -29,7 +29,7 @@ describe('now, today, yesterday and tomorrow', () => { day: 31, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "tomorrow"', () => { @@ -40,7 +40,7 @@ describe('now, today, yesterday and tomorrow', () => { day: 1, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "yesterday"', () => { @@ -51,6 +51,6 @@ describe('now, today, yesterday and tomorrow', () => { day: 30, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); }); diff --git a/src/formats/today/today.ts b/src/formats/today/today.ts index 63a51c3..11fdaab 100644 --- a/src/formats/today/today.ts +++ b/src/formats/today/today.ts @@ -2,6 +2,7 @@ import { Format } from '../../format'; import { DateObject } from '../../models'; export const today = new Format({ + name: 'today', matcher: /^(now|today|tomorrow|yesterday)/i, handler: match => { const now = new Date(); diff --git a/src/formats/twitter/twitter.spec.ts b/src/formats/twitter/twitter.spec.ts index d800e0c..3f48348 100644 --- a/src/formats/twitter/twitter.spec.ts +++ b/src/formats/twitter/twitter.spec.ts @@ -13,7 +13,7 @@ describe('twitter time', () => { offset: 0, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); it('should handle "Fri Apr 16 22:53:54 -0130 2017"', () => { const actual = StringToDate.parseToObject('Fri Apr 16 22:53:54 -0130 2017'); @@ -27,6 +27,6 @@ describe('twitter time', () => { offset: -90, }; - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); }); diff --git a/src/formats/twitter/twitter.ts b/src/formats/twitter/twitter.ts index a9cf15b..6c4903f 100644 --- a/src/formats/twitter/twitter.ts +++ b/src/formats/twitter/twitter.ts @@ -2,6 +2,7 @@ import { Format } from '../../format'; // example: "Fri Apr 09 12:53:54 +0000 2010" export const twitter = new Format({ + name: 'twitter', /* prettier-ignore */ // $1 $2 $3 $4 $5 $6 $7 template: '^(?:_DAYNAME_) (_MONTHNAME_) (_DAY_) (_H24_):(_MIN_):(_SEC_) (_OFFSET_) (_YEAR_)$', diff --git a/src/formats/yearMonthDay/yearMonthDay.spec.ts b/src/formats/yearMonthDay/yearMonthDay.spec.ts index 7201497..0a17331 100644 --- a/src/formats/yearMonthDay/yearMonthDay.spec.ts +++ b/src/formats/yearMonthDay/yearMonthDay.spec.ts @@ -6,6 +6,30 @@ testDates({ name: 'year month day', expected: { year: 2016, month: 9, day: 24 }, locales: ['en-US'], - formats: generateFormats('YEAR-MONTH-DAY'), + formats: generateFormats('YEAR-MONTH-DAY', ['MM', 'M'], ['/', '-', ' ', '.', '']), + formatsToRemove: [monthDayYear, dayMonthYear], +}); + +testDates({ + name: 'year month day', + expected: { year: 2016, month: 9, day: 4 }, + locales: ['en-US'], + formats: generateFormats('YEAR-MONTH-DAY', ['MM', 'M'], ['/', '-', ' ', '.', '']), + formatsToRemove: [monthDayYear, dayMonthYear], +}); + +testDates({ + name: 'year month day', + expected: { year: 2016, month: 11, day: 4 }, + locales: ['en-US'], + formats: generateFormats('YEAR-MONTH-DAY', ['MM', 'M']), + formatsToRemove: [monthDayYear, dayMonthYear], +}); + +testDates({ + name: 'year month day', + expected: { year: 2016, month: 1, day: 14 }, + locales: ['en-US'], + formats: generateFormats('YEAR-MONTH-DAY', ['MM', 'M']), formatsToRemove: [monthDayYear, dayMonthYear], }); diff --git a/src/formats/yearMonthDay/yearMonthDay.ts b/src/formats/yearMonthDay/yearMonthDay.ts index 53077b0..03f5bb2 100644 --- a/src/formats/yearMonthDay/yearMonthDay.ts +++ b/src/formats/yearMonthDay/yearMonthDay.ts @@ -1,8 +1,78 @@ import { Format } from '../../format'; +import { isNullOrUndefined } from '../../is-null-or-undefined'; +import { LocaleHelper } from '../../locale-helper'; + +let locHelper: LocaleHelper; + +const name = 'yearMonthDay'; export const yearMonthDay = new Format({ + name, /* prettier-ignore */ // $1 $2 $3 $4 - template: "^(_YEAR_)([\\/. -])(_MONTH_)\\2(_DAY_)$", - units: ['year', null, 'month', 'day'], + template: "^(_YEAR_)([\\/. -])?(_MONTH_)\\2(_DAY_)$", + handler: function ([dateExpr, year, separator, month, day], locale) { + if (!locHelper) { + locHelper = new LocaleHelper(locale); + } + + if (!isNullOrUndefined(separator) && separator !== ' ') { + return locHelper.getObject(['year', 'month', 'day'], [null, year, month, day], name); + } + + if (separator === ' ') { + [year, month, day] = dateExpr?.split(' '); + + return locHelper.getObject(['year', 'month', 'day'], [null, year, month, day], name); + } + + switch (dateExpr?.length) { + case 8: + case 7: + case 4: { + return locHelper.getObject(['year', 'month', 'day'], [null, year, month, day], name); + } + case 6: { + if (year!.length !== 2 && parseInt(year!) <= 1900) { + year = dateExpr.slice(0, 2); + + dateExpr = dateExpr.slice(2); + + if (dateExpr.length === 4) { + month = dateExpr.slice(0, 2); + day = dateExpr.slice(2); + } else if (dateExpr.length === 3 && dateExpr[0] === '0') { + month = dateExpr[1]; + day = dateExpr.slice(2); + } else { + month = dateExpr[0]; + day = dateExpr.slice(1); + } + } + + const result = locHelper.getObject(['year', 'month', 'day'], [null, year, month, day], name); + + return result; + } + case 5: { + if (month![0] === '0') { + month = month![1]; + day = dateExpr.slice(dateExpr.indexOf(month) + 1); + + return locHelper.getObject(['year', 'month', 'day'], [null, year, month, day], name); + } else if (parseInt(month![0]) > 1) { + month = month![0]; + day = dateExpr.slice(3); + + return locHelper.getObject(['year', 'month', 'day'], [null, year, month, day], name); + } else if (day![0] === '0') { + day = day![1]; + + return locHelper.getObject(['year', 'month', 'day'], [null, year, month, day], name); + } + } + } + + return null; + }, }); diff --git a/src/index.ts b/src/index.ts index b9e4eb9..39c67fc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -24,13 +24,13 @@ const StringToDate = new Parser(); // all formats can have time strings at the end StringToDate.addFormats([ + // from most unambiguous and popular to least time24Hours, time12Hours, dayMonthnameYear, monthnameDayYear, monthDayYear, dayMonthYear, - // from most unambiguous and popular to least yearMonthDay, chinese, twitter, diff --git a/src/locale-helper.ts b/src/locale-helper.ts index 24a946a..1c6d01d 100644 --- a/src/locale-helper.ts +++ b/src/locale-helper.ts @@ -67,8 +67,10 @@ export class LocaleHelper { * @param {Array} matches The values matched by a Format's RegExp * @returns {Object} */ - public getObject(units: Array, matches: Array): DateObject { - const object: DateObject = {}; + public getObject(units: Array, matches: Array, formatter?: string): DateObject { + const object: DateObject = { + formatter, + }; units.forEach((unit, i) => { if (!unit) { @@ -99,8 +101,10 @@ export class LocaleHelper { * @param {Object} object An object with one or more units * @returns {Object} An object with same units but Numeric */ - public castObject(object: LocaleCastConfig): DateObject { - const casted: DateObject = {}; + public castObject(object: LocaleCastConfig, formatter?: string): DateObject { + const casted: DateObject = { + formatter, + }; Object.entries(object).forEach(([unit, value]) => { if (unit in Unit) { diff --git a/src/localeHelper.spec.ts b/src/localeHelper.spec.ts index 83335ee..b4b10a6 100644 --- a/src/localeHelper.spec.ts +++ b/src/localeHelper.spec.ts @@ -45,7 +45,7 @@ describe('LocaleHelper general', () => { const matches = [null, '2020', '10', '+07:30']; const expected = { year: 2020, month: 10, offset: 450 }; - expect(l.getObject(units, matches)).toEqual(expected); + expect(l.getObject(units, matches, 'test')).toEqual(expect.objectContaining(expected)); }); it('should build objects from month name', () => { @@ -54,7 +54,7 @@ describe('LocaleHelper general', () => { const matches = [null, 'september', '59']; const expected = { month: 9, minute: 59 }; - expect(l.getObject(units, matches)).toEqual(expected); + expect(l.getObject(units, matches, 'test')).toEqual(expect.objectContaining(expected)); }); it('should build objects from short month name', () => { @@ -63,7 +63,7 @@ describe('LocaleHelper general', () => { const matches = [null, 'sep', '23']; const expected = { month: 9, hour: 23 }; - expect(l.getObject(units, matches)).toEqual(expected); + expect(l.getObject(units, matches, 'test')).toEqual(expect.objectContaining(expected)); }); it('should build objects from short month name with period', () => { @@ -72,7 +72,7 @@ describe('LocaleHelper general', () => { const matches = [null, 'sep.', '00']; const expected = { month: 9, second: 0 }; - expect(l.getObject(units, matches)).toEqual(expected); + expect(l.getObject(units, matches, 'test')).toEqual(expect.objectContaining(expected)); }); it('should build objects from "deva" numbers', () => { @@ -81,7 +81,7 @@ describe('LocaleHelper general', () => { const matches = [null, '٢٠١٧', '٦']; const expected = { year: 2017, month: 6 }; - expect(l.getObject(units, matches)).toEqual(expected); + expect(l.getObject(units, matches, 'test')).toMatchObject(expected); }); it('should handle invalid offsets', () => { diff --git a/src/models/date-object.ts b/src/models/date-object.ts index 6c24e09..01c3975 100644 --- a/src/models/date-object.ts +++ b/src/models/date-object.ts @@ -1,3 +1,3 @@ import { Units } from './units'; -export type DateObject = Partial>; +export type DateObject = Partial & { formatter?: string }>; diff --git a/src/parser.spec.ts b/src/parser.spec.ts index 1f7a215..796ca4c 100644 --- a/src/parser.spec.ts +++ b/src/parser.spec.ts @@ -3,7 +3,7 @@ import { Parser } from './parser'; describe('Parser', () => { it('should set a parser prop on the format', () => { - const format = new Format({ units: [], template: '' }); + const format = new Format({ units: [], template: '', name: 'test' }); const parser = new Parser(); parser.addFormat(format); @@ -13,7 +13,7 @@ describe('Parser', () => { }); it('should remove format', () => { - const format = new Format({ units: [], template: '' }); + const format = new Format({ units: [], template: '', name: 'test' }); const parser = new Parser(); parser.addFormat(format); @@ -25,7 +25,7 @@ describe('Parser', () => { }); it('should fail to remove unadded format', () => { - const format = new Format({ units: [], template: '' }); + const format = new Format({ units: [], template: '', name: 'test' }); const parser = new Parser(); const result = parser.removeFormat(format); @@ -33,7 +33,7 @@ describe('Parser', () => { }); it('should attempt() a single format', () => { - const format = new Format({ units: [], template: '' }); + const format = new Format({ units: [], template: '', name: 'test' }); const spy = jest.spyOn(format, 'attempt').mockReturnValue(null); const parser = new Parser(); @@ -48,9 +48,9 @@ describe('Parser', () => { }); it('should attempt() 2 formats', () => { - const format1 = new Format({ units: [], template: '' }); + const format1 = new Format({ units: [], template: '', name: 'test' }); const spy1 = jest.spyOn(format1, 'attempt').mockReturnValue(null); - const format2 = new Format({ units: [], template: '' }); + const format2 = new Format({ units: [], template: '', name: 'test' }); const spy2 = jest.spyOn(format2, 'attempt').mockReturnValue(null); const parser = new Parser(); @@ -68,7 +68,7 @@ describe('Parser', () => { }); it('should return invalid when all attempt()s fail', () => { - const format = new Format({ units: [], template: '' }); + const format = new Format({ units: [], template: '', name: 'test' }); jest.spyOn(format, 'attempt').mockReturnValue(null); const parser = new Parser(); @@ -82,7 +82,7 @@ describe('Parser', () => { }); it('should return invalid on empty string', () => { - const format = new Format({ units: [], template: '' }); + const format = new Format({ units: [], template: '', name: 'test' }); jest.spyOn(format, 'attempt').mockReturnValue(null); diff --git a/src/test-fixtures/generate-formats.ts b/src/test-fixtures/generate-formats.ts index d0bb175..5dd2d01 100644 --- a/src/test-fixtures/generate-formats.ts +++ b/src/test-fixtures/generate-formats.ts @@ -7,10 +7,10 @@ export function generateFormats( ): string[] { const formats: string[] = []; - for (const dayFormat of dayFormats) { - for (const monthFormat of monthFormats) { - for (const yearFormat of yearFormats) { - for (const separatorFormat of separatorFormats) { + for (const separatorFormat of separatorFormats) { + for (const yearFormat of yearFormats) { + for (const monthFormat of monthFormats) { + for (const dayFormat of dayFormats) { const format = template .replace('DAY', dayFormat) .replace('MONTH', monthFormat) diff --git a/src/test-fixtures/test-dates.ts b/src/test-fixtures/test-dates.ts index a886f69..3144927 100644 --- a/src/test-fixtures/test-dates.ts +++ b/src/test-fixtures/test-dates.ts @@ -39,7 +39,7 @@ export function testDates({ it(`${formatted} (${format})`, () => { const actual = StringToDate.parseToObject(formatted, locale); - expect(actual).toMatchObject(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); } }); diff --git a/src/test-fixtures/test-parser.ts b/src/test-fixtures/test-parser.ts index a3b29d7..15787c0 100644 --- a/src/test-fixtures/test-parser.ts +++ b/src/test-fixtures/test-parser.ts @@ -19,7 +19,7 @@ export function testParser({ it(`should handle "${date}" (${locale})`, () => { const actual = StringToDate.parseToObject(date, locale); - expect(actual).toEqual(expected); + expect(actual).toEqual(expect.objectContaining(expected)); }); }); });