diff --git a/src/index.test.ts b/src/index.test.ts index 5035ab9..baa08c0 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -385,3 +385,28 @@ describe('ms(invalid inputs)', () => { }).toThrow(); }); }); + +//multiple units +describe('ms(multipleunits)', () => { + it('should not throw an error, when ms(hasmorethanoneunit)', () => { + expect(() => { + ms('3y40s'); + }).not.toThrow(); + expect(() => { + ms('3y 40s'); + }).not.toThrow(); + expect(() => { + ms('3 y 40 s'); + }).not.toThrow(); + }); + + it('should convert all values into ms', () => { + expect(ms('1 h 45 s')).toBe(3645000); + expect(ms('3seconds40s')).toBe(43000); + expect(ms('1m1mo1ms')).toBe(2629860001); + }); + + it('should return NaN if invalid', () => { + expect(Number.isNaN(ms('3h2failure'))).toBe(true); + }); +}); diff --git a/src/index.ts b/src/index.ts index d50e3c7..e516bab 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,7 +29,10 @@ type UnitAnyCase = Capitalize | Uppercase | Unit; export type StringValue = | `${number}` | `${number}${UnitAnyCase}` - | `${number} ${UnitAnyCase}`; + | `${number} ${UnitAnyCase}` + | `${`${number}${Years}` | ``}${`${number}${Months}` | ``}${`${number}${Weeks}` | ``}${`${number}${Days}` | ``}${`${number}${Hours}` | ``}${`${number}${Minutes}` | ``}${`${number}${Seconds}` | ``}${`${number}${Milliseconds}` | `${number}` | ``}` + | `${`${number} ${Years}` | ``} ${`${number} ${Months}` | ``} ${`${number} ${Weeks}` | ``} ${`${number} ${Days}` | ``} ${`${number} ${Hours}` | ``} ${`${number} ${Minutes}` | ``} ${`${number} ${Seconds}` | ``} ${`${number} ${Milliseconds}` | `${number}` | ``}` + | `${`${number}${Years}` | ``} ${`${number}${Months}` | ``} ${`${number}${Weeks}` | ``} ${`${number}${Days}` | ``} ${`${number}${Hours}` | ``} ${`${number}${Minutes}` | ``} ${`${number}${Seconds}` | ``} ${`${number}${Milliseconds}` | `${number}` | ``}`; interface Options { /** @@ -80,7 +83,7 @@ export function parse(str: string): number { ); if (!match?.groups) { - return NaN; + return multipleUnits(str); } // Named capture groups need to be manually typed today. @@ -157,6 +160,30 @@ export function parseStrict(value: StringValue): number { return parse(value); } +/** + * Parse the given string with multiple time units and return milliseconds. + * + * @param value - A typesafe StringValue comprised of multiple strings to convert + * into milliseconds + * @returns The sum of all parsed strings value in milliseconds, or `NaN` if the + * string can't be parsed + */ + +function multipleUnits(value: string): number { + const regEx = + /\d*\.?\d+ *(?:milliseconds?|msecs?|ms|seconds?|secs?|s|months?|mo|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)/gi; + + const match = [...value.matchAll(regEx)].flat(); + const unmatchedString = value.replaceAll(regEx, ''); + const spaceRegEx = /^ *$/; + + if (match.length === 0 || spaceRegEx.exec(unmatchedString) === null) { + return NaN; + } + + return match.reduce((accumulator, unit) => parse(unit) + accumulator, 0); +} + /** * Short format for `ms`. */ diff --git a/src/parse-strict.test.ts b/src/parse-strict.test.ts index 9c30a5e..3ee9869 100644 --- a/src/parse-strict.test.ts +++ b/src/parse-strict.test.ts @@ -219,3 +219,23 @@ describe('parseStrict(invalid inputs)', () => { }).toThrow(); }); }); + +//multiple units +describe('ms(multipleunits)', () => { + it('should not throw an error, when ms(hasmorethanoneunit)', () => { + expect(() => { + parseStrict('3y40s'); + }).not.toThrow(); + expect(() => { + parseStrict('3y 40s'); + }).not.toThrow(); + expect(() => { + parseStrict('3 y 40 s'); + }).not.toThrow(); + }); + + it('should convert all values into ms', () => { + expect(parseStrict('1 h 45 s')).toBe(3645000); + expect(parseStrict('3seconds40s')).toBe(43000); + }); +}); diff --git a/src/parse.test.ts b/src/parse.test.ts index 9182411..a560334 100644 --- a/src/parse.test.ts +++ b/src/parse.test.ts @@ -206,3 +206,27 @@ describe('parse(invalid inputs)', () => { }).toThrow(); }); }); + +//multiple units +describe('ms(multipleunits)', () => { + it('should not throw an error, when ms(hasmorethanoneunit)', () => { + expect(() => { + parse('3y40s'); + }).not.toThrow(); + expect(() => { + parse('3y 40s'); + }).not.toThrow(); + expect(() => { + parse('3 y 40 s'); + }).not.toThrow(); + }); + + it('should convert all values into ms', () => { + expect(parse('1 h 45 s')).toBe(3645000); + expect(parse('3seconds40s')).toBe(43000); + }); + + it('should return NaN if invalid', () => { + expect(Number.isNaN(parse('3h2failure'))).toBe(true); + }); +});